need some help cloning metadata from one entity to another

Discussion in 'Plugin Development' started by xize, Aug 27, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    xize

    Hello,

    So I got a little bit frozen, I'm trying to write a custom event what triggers when a zombie or pigman tries to pickup a item the problem is when the entity picks up the item all the metadata of the Item entity even when it drops by killing, it will be gone so in order of that I store a copy of that Item entity before it gets picked with the metadata in memory even when it does not exist with all risks to memory leaks included.

    but my question now is how would I go about of re adding all the metadata from one stored Item object what already does not exist to a other new spawned Item drop if I'm correct all values are still safe since its stored in memory although some are may not couldn't test it cus I got stuck on copying the metadata from one entity to another.

    my custom event caller cough cough I know this look horrible but I just don't want to hook in nms:

    Code:
    public class CallEntityPickupEvent {
        
        private final LinkedHashMap<Monster, Item> items = new LinkedHashMap<Monster, Item>();
        
        public void startEvent() {
            new BukkitRunnable() {
                private Iterator<Entry<Monster, Item>> it;
                
                public Iterator<Entry<Monster, Item>> getIterator() {
                    if(!(it instanceof Iterator)) {
                        this.it = items.entrySet().iterator();
                    }
                    return it;
                }
                
                @Override
                public void run() {
                    for(World w : Bukkit.getWorlds()) {
                        for(Entity entity : w.getEntities()) {
                            if(entity instanceof Zombie || entity instanceof PigZombie) {
                                for(Entity a : entity.getNearbyEntities(1, 1, 1)) {
                                    if(a instanceof Item) {
                                        items.put((Monster)entity, (Item)a);
                                    }
                                }
                            }
                        }
                    }
                    
                    while(getIterator().hasNext()) {
                        Entry<Monster, Item> entry = getIterator().next();
                        if(entry.getKey().getEquipment().getItemInHand().getType() == entry.getValue().getItemStack().getType()) {
                            //passed the objects through the constructor so it will be not null and then remove the cached version from the map.
                            Bukkit.getPluginManager().callEvent(new EntityPickupItemEvent(entry.getKey(), entry.getValue()));
                            getIterator().remove();
                        } else if(entry.getKey().getLocation().distanceSquared(entry.getValue().getLocation()) > 2) {
                            //here is no need the fire the event the zombie or pigman has walked by and didn't picked anything up in one tick.
                            getIterator().remove();
                        }
                    }
                }
                
            }.runTaskTimer(xEssentials.getPlugin(), 0L, 1L);
        }
    }
    
    and my event it self I got a little bit stuck on what todo in the cancel state since there is not a easy way to copy the metadata :p

    Code:
    public class EntityPickupItemEvent extends EntityEvent implements Cancellable {
        
        private static final HandlerList handlers = new HandlerList();
        
        private boolean cancel = false;
        private final Item drop;
        
        public EntityPickupItemEvent(Monster monster, Item orginaldrop) {
            super(monster);
            this.drop = orginaldrop;
        }
        
        @Override
        public boolean isCancelled() {
            return cancel;
        }
        @Override
        public void setCancelled(boolean arg0) {
            if(arg0) {
                Monster monster = (Monster)getEntity();
                monster.getEquipment().setItemInHand(null);
                
                ItemStack stack = drop.getItemStack();
                Item item = drop.getWorld().dropItem(drop.getLocation(), stack);
                
                //here I'm stuck.
                
                this.cancel = true;
            }
            this.cancel = false;
        }
        
        public HandlerList getHandlers() {
            return handlers;
        }
        
        public static HandlerList getHandlerList() {
            return handlers;
        }
    }
    
    anyways I know the mather of my implementation is strict unsafe and shouldn't be encouraged in anyway, but I'm just playing around experimenting is always good.

    also if this event already exist maybe on a other name? please let me know, I couldn't find a non nms way of detecting when a entity picks up a item:p

    thanks:)
     
Thread Status:
Not open for further replies.

Share This Page