Reflection with custom entity class?

Discussion in 'Spigot Plugin Development' started by IconByte, May 18, 2016.

  1. hello. is there any way how I could make my custom entity class with reflection for multiple bukkit versions?
    As of right now I have to extend EntityZombie class which is NMS's class file.

    Code (Text):

    package net.iconbyte.npc;

    import org.bukkit.Location;
    import org.bukkit.craftbukkit.v1_9_R2.CraftWorld;
    import org.bukkit.craftbukkit.v1_9_R2.entity.CraftGuardian;
    import org.bukkit.craftbukkit.v1_9_R2.entity.CraftLivingEntity;
    import org.bukkit.entity.Zombie;
    import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;

    import net.minecraft.server.v1_9_R2.DamageSource;
    import net.minecraft.server.v1_9_R2.EntityGuardian;
    import net.minecraft.server.v1_9_R2.NBTTagCompound;

    public class ZombieNPC extends EntityZombie { <--- This extension with reflection...?
        public ZombieNPC(CraftWorld world) {
            super(world.getHandle());
        }

        @Override
        public boolean damageEntity(DamageSource damagesource, float f) {
            return false;
        }

        @Override
        public void g(double d0, double d1,double d2) {
            return;
        }

        @Override
        public void move(double d0, double d1,double d2) {
            return;
        }

        public static Zombie spawnZombie(Location loc) {
            CraftWorld mcWorld = ((CraftWorld) loc.getWorld());
            ZombieNPC customEntity = new ZombieNPC(mcWorld);
            customEntity.setLocation(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
            ((CraftLivingEntity) customEntity.getBukkitEntity()).setRemoveWhenFarAway(false);
            mcWorld.getHandle().addEntity(customEntity, SpawnReason.CUSTOM);
            removeSounds(customEntity);
            removeAI(customEntity);
            return (CraftZombie) customEntity.getBukkitEntity();
        }

        private static void removeSounds(ZombieNPC customEntity) {
            CraftZombie craftEntity = ((CraftZombie) customEntity.getBukkitEntity());
            NBTTagCompound nbtTag = new NBTTagCompound();
            craftEntity.getHandle().c(nbtTag);
            nbtTag.setInt("Silent", 1);
            craftEntity.getHandle().f(nbtTag);
        }

        private static void removeAI(ZombieNPC customEntity) {
            CraftZombie craftEntity = ((CraftZombie) customEntity.getBukkitEntity());
            NBTTagCompound nbtTag = new NBTTagCompound();
            craftEntity.getHandle().c(nbtTag);
            nbtTag.setInt("NoAI", 1);
            craftEntity.getHandle().f(nbtTag);
        }
    }
     
  2. You can use a bytecode manipulation framework like ASM to do this.
     
  3. Yes it's possible like @PickNChew said above. However method names in the entity classes change almost every update. You could make a list of previous names to support multiple older versions. However, supporting future versions is almost impossible.
     
  4. Sorry for replying so late, but do you mean creating a list as creating multiple class files for each version, and then using the correct class by the server's spigot version?
     
  5. That's also possible, but I actually meant a list of method names, so that you can dynamically compile the class for the version running. Then you might have a small chance that you can support a future version without updating. But like I said, most likely the method/field names will change.