NMS Custom Mount don't spawn

Discussion in 'Spigot Plugin Development' started by T4R13N, Jun 6, 2018.

  1. Hello I have a problem. I make a code for create custom animals for mounture system in 1.12 and when the entity spawn, it despawn just after

    Code (Java):
    package fr.hookwood.cloudmc.entity.Mount;

    import net.minecraft.server.v1_12_R1.*;
    import java.lang.reflect.Field;

    public class CustomEnderman extends EntityEnderman {

        public CustomEnderman(World world) {
            super(world);
            this.fireProof = true;
        }
       
        @Override
        public float g(float sideMot, float forMot) {
            if (this.passengers != null) {
                EntityLiving passenger = (EntityLiving) this.passengers.get(0);
                this.yaw = passenger.yaw;
                this.lastYaw = this.yaw;
                this.pitch = (passenger.pitch * 0.5F);
                setYawPitch(this.yaw, this.pitch);
                this.aN = this.yaw;
                this.aP = this.aN;
           
                Float speedmultiplicator = 3F;
                sideMot = passenger.be * speedmultiplicator;
                forMot = passenger.bf * speedmultiplicator;
                if(forMot <= 0.0F) {
                        forMot *= 0.25F;
                }
                 Field jump = null;
                    try {
                        jump = EntityLiving.class.getDeclaredField("bd");
                    } catch (NoSuchFieldException e1) {
                        e1.printStackTrace();
                    } catch (SecurityException e1) {
                        e1.printStackTrace();
                    }
                    jump.setAccessible(true);

                    if (jump != null && this.onGround) {
                        try {
                            if (jump.getBoolean(passenger)) {
                                double jumpHeight = 0.5D;  
                                this.motY = jumpHeight;    
                            }
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                super.g(sideMot, forMot);
            }
            return forMot;
        }
       
        @Override
        public String getName() {
            return this.getClass().getSimpleName();
        }

    }
    Code (Java):
    package fr.hookwood.cloudmc.entity.Mount;

    import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.List;

    import org.bukkit.entity.EntityType;

    import net.minecraft.server.v1_12_R1.BiomeBase;
    import net.minecraft.server.v1_12_R1.Entity;
    import net.minecraft.server.v1_12_R1.EntityBat;
    import net.minecraft.server.v1_12_R1.EntityBlaze;
    import net.minecraft.server.v1_12_R1.EntityCaveSpider;
    import net.minecraft.server.v1_12_R1.EntityChicken;
    import net.minecraft.server.v1_12_R1.EntityCow;
    import net.minecraft.server.v1_12_R1.EntityEnderman;
    import net.minecraft.server.v1_12_R1.EntityGuardian;
    import net.minecraft.server.v1_12_R1.EntityHorse;
    import net.minecraft.server.v1_12_R1.EntityInsentient;
    import net.minecraft.server.v1_12_R1.EntityIronGolem;
    import net.minecraft.server.v1_12_R1.EntityOcelot;
    import net.minecraft.server.v1_12_R1.EntityPig;
    import net.minecraft.server.v1_12_R1.EntitySkeleton;
    import net.minecraft.server.v1_12_R1.EntitySpider;
    import net.minecraft.server.v1_12_R1.EntityTypes;
    import net.minecraft.server.v1_12_R1.EntityWolf;
    import net.minecraft.server.v1_12_R1.EntityZombie;
    import net.minecraft.server.v1_12_R1.MinecraftKey;
    import net.minecraft.server.v1_12_R1.RegistryID;
    import net.minecraft.server.v1_12_R1.RegistryMaterials;

    public enum CustomEntityType {

        ZOMBIE("Zombie", 54, EntityType.ZOMBIE, EntityZombie.class, CustomZombie.class),
        PIG("Pig", 90, EntityType.PIG, EntityPig.class, CustomPig.class),
        CHICKEN("Chicken", 93, EntityType.CHICKEN, EntityChicken.class, CustomChicken.class),
        COW("Cow", 92, EntityType.COW, EntityCow.class, CustomCow.class),
        ENDERMAN("Enderman", 58, EntityType.ENDERMAN, EntityEnderman.class, CustomEnderman.class),
        GUARDIAN("Guardian", 68, EntityType.GUARDIAN, EntityGuardian.class, CustomGuardian.class),
        IRONGOLEM("IronGolem", 99, EntityType.IRON_GOLEM, EntityIronGolem.class, CustomIronGolem.class),
        OCELOT("Ocelot", 98, EntityType.OCELOT, EntityOcelot.class, CustomOcelot.class),
        SKELETON("Skeleton", 51, EntityType.SKELETON, EntitySkeleton.class, CustomSkeleton.class),
        WOLF("Wolf", 95, EntityType.WOLF, EntityWolf.class, CustomWolf.class),
        HORSE("Horse", 100, EntityType.HORSE, EntityHorse.class, CustomCheval.class),
        BLAZE("Blaze", 61, EntityType.BLAZE, EntityBlaze.class, CustomBlaze.class),
        BAT("Bat", 65, EntityType.BAT, EntityBat.class, CustomBat.class),
        SPIDER("Spider", 52, EntityType.SPIDER, EntitySpider.class, CustomSpider.class),
       CAVE_SPIDER("CaveSpider", 59, EntityType.CAVE_SPIDER, EntityCaveSpider.class, CustomCaveSpider.class);

        public static List<Entity> CustomEntityType = new ArrayList<>();
       
        private String name;
        private int id;
        private EntityType entityType;
        private MinecraftKey minecraftKey;
        private Class<? extends EntityInsentient> nmsClass;
        private Class<? extends EntityInsentient> customClass;
       
        CustomEntityType(String name, int id, EntityType entityType, Class<? extends EntityInsentient> nmsClass,
                       Class<? extends EntityInsentient> customClass) {
            this.name = name;
            this.id = id;
            this.entityType = entityType;
            this.minecraftKey = new MinecraftKey(name);
            this.nmsClass = nmsClass;
            this.customClass = customClass;
        }
       
        public String getName() {
            return name;
        }
       
        public int getID() {
            return id;
        }
       
        public EntityType getEntityType() {
            return entityType;
        }
       
        public MinecraftKey getMinecraftKey() {
            return this.minecraftKey;
        }
       
        public Class<? extends EntityInsentient> getNMSClass() {
            return nmsClass;
        }
       
        public Class<? extends EntityInsentient> getCustomClass() {
            return customClass;
        }
       
        public static void registerEntities() {
            for (CustomEntityType entity : values()) {
                try {
                    @SuppressWarnings("unchecked") RegistryID<Class<? extends Entity>> registryID = (RegistryID<Class<? extends Entity>>) getPrivateField(RegistryMaterials.class, EntityTypes.b, "a");
                    Object[] idToClassMap = (Object[]) getPrivateField(RegistryID.class, registryID, "d");
                   
                    Object oldValue = idToClassMap[entity.getID()];
                   
                    registryID.a(entity.getCustomClass(), entity.getID());
                   
                    idToClassMap[entity.getID()] = oldValue;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
           
            for (BiomeBase biomeBase : (Iterable<BiomeBase>) BiomeBase.i) {
                if (biomeBase == null)
                    break;
                for (String field : new String[]{ "t", "u", "v", "w" })
                    try {
                        Field list = BiomeBase.class.getDeclaredField(field);
                        list.setAccessible(true);
                        @SuppressWarnings("unchecked") List<BiomeBase.BiomeMeta> mobList = (List<BiomeBase.BiomeMeta>) list
                                .get(biomeBase);
                       
                        for (BiomeBase.BiomeMeta meta : mobList)
                            for (CustomEntityType entity : values())
                                if (entity.getNMSClass().equals(meta.b))
                                    meta.b = entity.getCustomClass();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
            }
        }
       
        public static void unregisterEntities() {
            for (CustomEntityType entity : values()) {
                try {
                    EntityTypes.b.a(entity.getID(), entity.getMinecraftKey(), entity.getNMSClass());
                } catch (Exception exc) {
                }
            }
        }
       
        public static Object getPrivateField(Class<?> clazz, Object handle, String fieldName) throws Exception {
            Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(handle);
        }
    }
     

    Code (Java):
    public static void spawnEnderMan(Player p){
            WorldServer nmsWorld = ((CraftWorld) p.getLocation().getWorld()).getHandle();
            make(new CustomEnderman(nmsWorld), p);
        }



        private static void addMounter(int ID, Player p){
            if(!mounter.containsKey(p.getName())){
                mounter.put(p.getName(), ID);
            }

        }

        public static void removeMounter(Player p){
            if(mounter.containsKey(p.getName())){
                int ID = mounter.get(p.getName());
                for(org.bukkit.entity.Entity e : p.getWorld().getEntities()){
                    if(e.getEntityId() == ID){
                        e.remove();
                        mounter.remove(p.getName());
                        break;
                    }
                }
            }

        }


        private static void make(EntityLiving nmsEntity, Player player){
            if(!canSummonMount(player.getLocation())){
                player.sendMessage("§8[§6CloudMC§8]§cVous ne pouvez pas avoir votre monture ici !");
                return;
            }
            try{
            LivingEntity mount = (LivingEntity) nmsEntity.getBukkitEntity();

            Location loc = player.getLocation();
            World nmsWorld = ((CraftWorld) loc.getWorld()).getHandle();
            nmsEntity.setPosition(loc.getX(), loc.getY() + 0.3, loc.getZ());
            nmsWorld.addEntity(nmsEntity, CreatureSpawnEvent.SpawnReason.CUSTOM);

            mount.setMaxHealth(mount.getMaxHealth());
            mount.setPassenger(player);

            removeMounter(player);
            addMounter(mount.getEntityId(), player);
            }catch(Error e){
                System.err.println(e);
            player.sendMessage("§8[§6CloudMC§8]§cMonture spawn !");
               
            }
        }

        public static boolean canSummonMount(Location location) {
            org.bukkit.World world = location.getWorld();
            Block block = location.getBlock();
            for(int x = location.getBlockX() - 1; x <= location.getBlockX() + 1; x++){
                for(int y = location.getBlockY(); y <= location.getBlockY() + 1; y++){
                    for(int z = location.getBlockZ() - 1; z <= location.getBlockZ() + 1; z++){
                        block = world.getBlockAt(x, y, z);
                        if (block.getType().isSolid()) return false;
                    }
                }
            }

            return true;
        }

        public static void removeAllPets(){
            for(Player p : Bukkit.getOnlinePlayers()){
                Mount.removeMounter(p);
            }
        }
    Code (Java):
            Bukkit.getScheduler().runTaskLater(this, new Runnable() {
                public void run() {
                    CustomEntityType.registerEntities();
                }
            }, 10);

    Thanks if you can help me to resolve this !
     
  2. Without looking too deeply, I see you are attempting to get the Bukkit id of the entity before it's been added to the world. I'm pretty sure that could be an issue, but I'm half asleep right now and could be way off base here..
     
  3. You are trying to get the Bukkit ID before you create it, just as BillyGalbreath Said.
     
  4. Okey so I resolve a problem, it was an event that was disable animal spawn on server. But now i have a big problem on the nms passenger


    [​IMG]

    and the code is
    Code (Text):
    package fr.hookwood.cloudmc.entity.Mount;



    import java.lang.reflect.Field;

    import org.bukkit.craftbukkit.v1_12_R1.util.UnsafeList;

    import net.minecraft.server.v1_12_R1.EntityHorse;
    import net.minecraft.server.v1_12_R1.EntityLiving;
    import net.minecraft.server.v1_12_R1.PathfinderGoalSelector;
    import net.minecraft.server.v1_12_R1.World;



    public class CustomCheval extends EntityHorse{

        private float speed = 0.8F;

        public CustomCheval(World world) {

            super(world);
           
        }

        @Override
        public float g(float sideMot, float forMot) {
            if (this.passengers != null) {
                EntityLiving passenger = (EntityLiving) this.passengers.get(1);
                this.yaw = passenger.yaw;
                this.lastYaw = this.yaw;
                this.pitch = (passenger.pitch * 0.5F);
                setYawPitch(this.yaw, this.pitch);
                this.aN = this.yaw;
                this.aP = this.aN;
           
                Float speedmultiplicator = 3F;
                sideMot = passenger.be * speedmultiplicator;
                forMot = ((EntityLiving) this.passengers).bf * speedmultiplicator;
                if(forMot <= 0.0F) {
                        forMot *= 0.25F;
                }
                 Field jump = null;
                    try {
                        jump = EntityLiving.class.getDeclaredField("bd");
                    } catch (NoSuchFieldException e1) {
                        e1.printStackTrace();
                    } catch (SecurityException e1) {
                        e1.printStackTrace();
                    }
                    jump.setAccessible(true);

                    if (jump != null && this.onGround) {    
                        try {
                            if (jump.getBoolean(passenger)) {
                                double jumpHeight = 0.5D;  
                                this.motY = jumpHeight;      
                            }
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                super.g(sideMot, forMot);
            }
            return forMot;
        }
       
        @Override
        public String getName() {
            return this.getClass().getSimpleName();
        }

    }
     

    So I search on internet, and I don't know how to resolve it ^^
    [​IMG]
     

    Attached Files:

  5. On 1.12 the method changed to:
    Code (Java):
    @Override
    public void a(float f, final float f1, float f2) {
        super.a(f, f1, f2);
    }
    Instead of:
    Code (Java):
    @Override
    public void g(float f, float f1) {
        super.g(f, f1);
    }
     
  6. So what is the f2 float utilisation ? Is it useless ? Or i need to use it somewhere ?
     
  7. To understand NMS its sometimes best to cross reference MCP. MCP has most things deobfuscated and named much better than NMS.

    NMS: [​IMG]

    MCP: [​IMG]

    ;)
     
    • Like Like x 1
  8. Easiest way is to clone Forge into your IDE as seen from my above screenshots.

    If you want a quicker view for something specific (or want to see the MCP<->OBF mappings) then you can use the MCP Mapping Viewer as shown here

    [​IMG]
     
    • Informative Informative x 1
  9. I thought it was a deobfuscator tool. My bad, thanks anyways.
     
  10. It is. MCP is deobfuscated vanilla code. There are lots of tools to view it, but I find the easiest way to browse it is to clone Forge into your IDE since Forge uses MCP mappings to deobfuscate everything.

    You can download a ZIP of all the mappings if you want, but thats all MCP is. Mappings. http://www.modcoderpack.com/

    Paper is even attempting to make the switch from NMS to MCP, but idk how active they are at pursuing that.

    Many years ago CraftBukkit used to be MCP, too. But the team at the time decided it was taking too long between versions for MCP to update so they made their own mappings for the bare minimum they needed to get the job done. Wasn't an issue until Spigot started getting stale which is causing more and more plugins to dig into NMS to do the things they need.
     
  11. I meant a deobfuscator tool to deobfuscate any jar file like plugins for example.