Item merge event?

Discussion in 'Plugin Development' started by Kepler_, Oct 28, 2012.

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

    Kepler_

    I know there isnt an item merge event (for when 2 dropped items stack together) in the bukkit api, but is there a way to use the minecraft api (net.minecraft...) to stop items from merging?
     
  2. Offline

    Comphenix

    Could you elaborate on what you're trying to achieve? It might be possible to find an easier solution if I need more about what you're doing.

    For instance, if you just want to restrict the stack size of a specific type, you could set the maximum stack size with reflection. Of course, this a global setting that affects every world and every player, along with item stacks in the inventory as well. That might not be fine grained enough for your purposes, though.

    Initially, I thought you could simply override the "mergeItem" method by injecting into EntityItem, but unfortunately, this method cannot be used to inject into newly dropped items, as blocks, mobs and players reference EntityItem directly. It would probably only work for saved item stacks.

    So, I can only see two viable options:
    1. Use Icyene's loaded class swapper to inject the necessary code into mergeItem. Though I haven't tried it myself, I understand it's fairly difficult to achieve, and it will require users of your plugin to have JDK installed. It's probably more of a last resort.
    2. Inject the EntityItem once its added to the chunk's entity list, the world's entity list and the entity tracker.
    The last method should work, but it's pretty complicated. It's a lot of work just to to stop items from merging. :p
     
  3. Offline

    Kepler_

    There's a plugin that I use, ShowcaseStandalone, that has a small bug. The showcases are slabs that have a floating item on it (that cannot be picked up). The problem is that players can throw items onto the slab, the thrown item and the display item will merge, and the user cant pick the item back up again. I'm trying to find a way to stop certain items from merging. The solution that i thought of is to cancel an event that triggers when dropped items merge. The problem is that bukkit doesn't have an event for that. I'm wondering if the minecraft API has an event for that, or some other way to stop specific dropped items from merging.

    Thanks :D
     
  4. Offline

    Comphenix

    Ah, I see. There's even a ticket for this issue.

    Nope. But the method I described above would probably work.

    Looks like the developer is waiting for Bukkit to add this merge event, but I really doubt it will happen. The problem is that every item stack is checked for nearby items every server tick, which means that the merge event would continue to get called after being cancelled the first time. That's definitely not friendly in terms of performance.

    The "injection" method I detailed above would have the same problem, of course.

    I suppose a plausible compromise would be to add a "flag" that can enable or disable item merging for a given item stack (something like setItemMergeable), but I wouldn't hold my breath here either.

    No, I think the best option in this case would be to only create the "showcase" item client-side. That way, you get all the necessary features for free. Users would be unable to pick up the item, merge it with some other item stack, or destroy them with fire or lava. It's also intrinsically less susceptible to exploits.

    You can create items client-side by sending a Packet21PickupSpawn to the client (and a corresponding Packet29DestroyEntity once the player is out of range). This approach would probably require a partial rewrite of the plugin, however, so it's not done overnight ...
     
  5. Offline

    Kepler_

    That's an interesting idea.... making the client think there's an item somewhere even though there isn't. Thanks for the help :D
     
  6. Offline

    yawkat

    For the record, this can be accomplished quite easily for newly dropped items by using a different item drop method and overriding the merge method:
    Code:
    final EntityItem e = new EntityItem(((CraftWorld) location.getWorld()).getHandle(), location.getX(), location.getY(), location.getZ()) {
        @Override
        public boolean a(EntityItem entityitem) {
            // DO NOT merge items, we want to keep this exact instance.
            return false;
        }
    };
    ((CraftWorld) location.getWorld()).getHandle().addEntity(e);
    return (Item) e.getBukkitEntity();
     
  7. Offline

    netherfoam

    Not that this isnt a necro thread, but you can accomplish the same thing by just setting a random bit of lore on the item, or changing its name. I use this for QuickShop. This only works as long as you dont pick the item up. If the item gets picked up, just 'clean' the lore you added off of it. I use a random, static, id at the end of each items name eg.

    Display item1
    Display item2
    "Display item" + ++i;
     
    glen3b likes this.
Thread Status:
Not open for further replies.

Share This Page