1.16.5 Simulate the use of an ItemStack (Spawn Egg) at a Location

Discussion in 'Spigot Plugin Development' started by Sigong, Jul 2, 2021.

  1. I have an ItemStack. I would like to cause the effect that would happen if a player right clicked a block with that ItemStack. How do I do this?

    (I'm trying to spawn the entity that would spawn if a spawn egg itemstack a player is holding were used on a block. Since the entity can be defined using NBT tags to have various attributes, armor etc, and doesn't even necessarily match the entity type that the spawn egg would usually produce, this isn't as simple as cutting "_SPAWN_EGG" off the ItemStack material and spawning whatever entity's type is left. I thought, instead of reading NBT, creating an entity object, spawning the entity, it would be simpler to just simulate what would happen if the egg were used.)
     
  2. Optic_Fusion1

    Resource Staff

    If you want a custom spawn egg that functions EXACTLY like the minecraft one...best bet is to use NMS and create one using NBT and convert it into a bukkit itemstack
     
  3. I already have the spawn egg as an ItemStack. I want to spawn the entity that would spawn if it were used, at a certain location. I thought the best way to do this would be to somehow simulate its use, but I can't figure out how.
     
  4. Code (Text):

    @EventHandler
        public void onInteract(PlayerInteractEvent e) {
            Player player = e.getPlayer();
           
            ItemStack item = new ItemStack(Material.IRON_INGOT);
           
            if(player.getInventory().getItemInMainHand() != null) {
                if(player.getInventory().getItemInMainHand().isSimilar(item)) {
                    if(e.getAction() == Action.LEFT_CLICK_BLOCK) {
                        //Do something
                    }
                }
            }
        }
     
     
    • Agree Agree x 1
  5. I know how to detect if a player uses an item.

    To make this more clear: I want to create a function that takes in an ItemStack and a BlockFace as arguments, and causes whatever effect would happen if a player right clicked that BlockFace with that ItemStack, whatever the ItemStack is. The function won't be triggered by a Player right clicking a block, in fact, assume that no Player has right clicked with that ItemStack at all.
     
  6. I think I know what you need.
    1. You'll need to create a fake player - let's call him Chad69LIT420 - and put the item in their hand (I don't think it matters which one).
    2. Manually create PlayerInteractEvent (with Chad as the player) and call it. Check if the item is still in Chad's hand: if not - you're done, otherwise jump to #5.
    3. Manually create PlayerDropItemEvent (with Chad as the player) and call it. Wait a few seconds. Check if the "dropped item" was removed: if yes - you're done, otherwise jump to #5.
    4. At this point nothing "custom" has happened, so just go ahead and spawn the mob the egg is associated with.
    5. You're done!
    I think this should be enough.
     
  7. I'm confused, what is the purpose of dropping the item?

    Also, doing step 4 manually is what I'm trying to avoid by simulating the click (the entity that a given egg would spawn can differ from the egg's type, and can contain NBT data that would make it spawn with armor, etc if the egg were used normally by a player, so I thought that simulating the egg's use would be simpler than reading the NBT data and creating an Entity object and spawning it. This is my central problem. I'm trying to avoid dealing with converting NBT data from an ItemStack into an entity)

    Another reframing: The player class has a performCommand method which makes the player perform a command without their input. Is there a way to create a similar method, but for right clicking at a given location?

    Edit: If I create a PlayerInteractEvent, will it actually cause the interaction I want, or will it just declare to other plugins that it happened?
     
    #7 Sigong, Jul 2, 2021
    Last edited: Jul 2, 2021
  8. Some plugins (like MythicMobs) use egg droppin g instead of right-clicking, so just in case.

    The whole point of the previous steps was to make sure other plugins' custom spawning is called before you can check if you use the regular spawning.
    In #4 what you need to do is this: find the Minecraft's NMS class that calls the mob spawning from an egg, extract the NBT info from the egg (there're plenty of guides for that), and use the NMS function with the extracted NBT as a variable to spawn the mob with the proper info.

    No. Commands use functions eventually, so no point really.


    No, you're just calling it to make sure other plugins' custom spawning is called (just in case) before continuing to a regular spawn.
     
  9. This is how dispensers spawn with spawn eggs:
    Code (Java):

    EntityTypes entitytypes = ((ItemMonsterEgg) itemstack.getItem()).a(itemstack.getTag());
    try {
            entitytypes.spawnCreature(isourceblock.getWorld(), itemstack, (EntityHuman) null, isourceblock.getBlockPosition().shift(enumdirection), EnumMobSpawn.DISPENSER, enumdirection != EnumDirection.UP, false);
                    } catch (Exception exception) {
                        LOGGER.error("Error while dispensing spawn egg from dispenser at {}", isourceblock.getBlockPosition(), exception); // CraftBukkit - decompile error
                        return ItemStack.EMPTY;
                    }
    Edit: Just noticed that the thread is for 1.16.5 while the code above is from 1.17 so will be slightly different.
     
    #9 antiPerson, Jul 2, 2021
    Last edited: Jul 2, 2021