Development Assistance HELP: Nested Classes, NMS mobs, and a noSuchMethodException

Discussion in 'Plugin Help/Development/Requests' started by westjet, Apr 26, 2015.

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

    westjet

    OK, the other day I was trying to make all my NMS methods, classes and fields in one class file. Then I would use reflection to choose the class that corresponds to the right version of MC/Spigot that the server is running. This works nicely, but I get an error almost every time I turn the server on or when a player approaches a regular sheep that was generated by minecraft in world that has nothing to do with my plugin. The NMS I need to do includes spawning a custom mob, NMS methods that manage the custom mob and other NMS parts of my project.

    This is that all-inclusive class:

    Code:
    package com.dumbninja22.plugin.ver;
    
    import java.lang.reflect.Field;
    import java.util.List;
    import java.util.Map;
    
    import net.minecraft.server.v1_8_R2.IChatBaseComponent;
    import net.minecraft.server.v1_8_R2.IChatBaseComponent.ChatSerializer;
    import net.minecraft.server.v1_8_R2.PacketPlayOutTitle;
    import net.minecraft.server.v1_8_R2.AttributeInstance;
    import net.minecraft.server.v1_8_R2.BiomeBase;
    import net.minecraft.server.v1_8_R2.EntityInsentient;
    import net.minecraft.server.v1_8_R2.EntitySheep;
    import net.minecraft.server.v1_8_R2.EntityTypes;
    import net.minecraft.server.v1_8_R2.EnumColor;
    import net.minecraft.server.v1_8_R2.GenericAttributes;
    import net.minecraft.server.v1_8_R2.PacketPlayOutTitle.EnumTitleAction;
    import net.minecraft.server.v1_8_R2.PathEntity;
    import net.minecraft.server.v1_8_R2.PathfinderGoalSelector;
    import net.minecraft.server.v1_8_R2.BiomeBase.BiomeMeta;
    import net.minecraft.server.v1_8_R2.World;
    
    import org.bukkit.Location;
    import org.bukkit.craftbukkit.v1_8_R2.entity.CraftPlayer;
    import org.bukkit.craftbukkit.v1_8_R2.CraftWorld;
    import org.bukkit.craftbukkit.v1_8_R2.entity.CraftEntity;
    import org.bukkit.craftbukkit.v1_8_R2.entity.CraftSheep;
    import org.bukkit.craftbukkit.v1_8_R2.util.UnsafeList;
    import org.bukkit.entity.Entity;
    import org.bukkit.entity.EntityType;
    import org.bukkit.entity.Player;
    import org.bukkit.scheduler.BukkitRunnable;
    
    import com.dumbninja22.plugin.Main;
    import com.dumbninja22.plugin.NMS; //This import is an interface class
    
    public class v1_8_R2 implements NMS {
      
        public void registerEntities() {
            CustomEntityType.registerEntities();
          
        }
      
    public void nmsMethodOne(String str, Player p) {
            //NMS Method
          
        }
      
    public EnumColor nmsMethodTwo() {
         
          
        }
    
      
      
        public void anotherNMSMethod(){
           
          
       
      
      
        public void anotherNMSMethod(){
    
    
    
        }
           
      
        //The custom entity sheep
        public enum CustomEntityType {
            CUSTOMSHEEP("Sheep",91,EntityType.SHEEP,EntitySheep.class,v1_8_R2.CustomEntitySheep.class);
                private String name = new String();
                private int id;
                private EntityType entityType;
                private Class<? extends EntityInsentient> nmsClass;
                private Class<? extends EntityInsentient> customClass;
               
                private CustomEntityType(/*The name of the NMS entity*/String name, /*The entity id*/int id, /*The entity type*/EntityType entityType, /*The origional NMS class*/ Class<? extends EntityInsentient> nmsClass, /*The custom class*/ Class<? extends EntityInsentient> customClass) {
                this.name = name;
                this.id = id;
                this.entityType = entityType;
                this.nmsClass = nmsClass;
                this.customClass = customClass;
                }
               
                public String getName() {
                return name;
                }
               
                public int getID() {
                return id;
                }
               
                public EntityType getEntityType() {
                return entityType;
                }
               
                public Class<? extends EntityInsentient> getNMSClass() {
                return nmsClass;
                }
               
                public Class<? extends EntityInsentient> getCustomClass() {
                return customClass;
                }
    
                /*Register our entities to the server, add to onEnable()*/
                public static void registerEntities() {
                for (CustomEntityType entity : values()) /*Get our entities*/
                a(entity.getCustomClass(), entity.getName(), entity.getID());
                /*Get all biomes on the server*/
                BiomeBase[] biomes;
                try {
                biomes = (BiomeBase[]) getPrivateStatic(BiomeBase.class, "biomes");
                } catch (Exception exc) {
                return;
                }
                for (BiomeBase biomeBase : biomes) {
                if (biomeBase == null)
                break;
                for (String field : new String[] { "at", "au", "av", "aw" }) //Lists that hold all entity types
                try {
                Field list = BiomeBase.class.getDeclaredField(field);
                list.setAccessible(true);
                @SuppressWarnings("unchecked")
                List<BiomeMeta> mobList = (List<BiomeMeta>) list.get(biomeBase);
               
                for (BiomeMeta meta : mobList)
                for (CustomEntityType entity : values())
                if (entity.getNMSClass().equals(meta.b)) /*Test if the entity has the custom entity type*/
                meta.b = entity.getCustomClass(); //Set it's meta to our custom class's meta
                } catch (Exception e) {
                e.printStackTrace();
                }
                }
                }
              
              
              
                public static Entity spawn(Location location) {
                    World nmsWorld = ((CraftWorld) location.getWorld()).getHandle();
                    CustomEntitySheep customSheepy = new v1_8_R2(). new CustomEntitySheep(nmsWorld);
                    customSheepy.setPosition(location.getX(), location.getY(), location.getZ());
                    nmsWorld.addEntity(customSheepy);
                  
                    return customSheepy.getBukkitEntity();
    
    
                  
                 
                }
                /*Method(add to onDisable()) to prevent server leaks when the plugin gets disabled*/
                @SuppressWarnings("rawtypes")
                public static void unregisterEntities() {
                for (CustomEntityType entity : values()) {
                // Remove our class references.
                try {
                ((Map) getPrivateStatic(EntityTypes.class, "d")).remove(entity.getCustomClass());
                } catch (Exception e) {
                e.printStackTrace();
                }
               
                try {
                ((Map) getPrivateStatic(EntityTypes.class, "f")).remove(entity.getCustomClass());
                } catch (Exception e) {
                e.printStackTrace();
                }
                }
               
                for (CustomEntityType entity : values())
                try {
                a(entity.getNMSClass(), entity.getName(), entity.getID());
                } catch (Exception e) {
                e.printStackTrace();
                }
               
                BiomeBase[] biomes;
                try {
                biomes = (BiomeBase[]) getPrivateStatic(BiomeBase.class, "biomes"); /*Get all biomes again*/
                } catch (Exception exc) {
                return;
                }
                for (BiomeBase biomeBase : biomes) {
                if (biomeBase == null)
                break;
               
                for (String field : new String[] { "at", "au", "av", "aw" }) /*The entity list*/
                try {
                Field list = BiomeBase.class.getDeclaredField(field);
                list.setAccessible(true);
                @SuppressWarnings("unchecked")
                List<BiomeMeta> mobList = (List<BiomeMeta>) list.get(biomeBase);
               
                for (BiomeMeta meta : mobList)
                for (CustomEntityType entity : values())
                if (entity.getCustomClass().equals(meta.b))
                meta.b = entity.getNMSClass(); /*Set the entities meta back to the NMS one*/
                } catch (Exception e) {
                e.printStackTrace();
                }
                }
                }
                /*A little Util for getting a private field*/
                @SuppressWarnings("rawtypes")
                private static Object getPrivateStatic(Class clazz, String f) throws Exception {
                Field field = clazz.getDeclaredField(f);
                field.setAccessible(true);
                return field.get(null);
                }
                /*Set data into the entitytypes class from NMS*/
                @SuppressWarnings({ "unchecked", "rawtypes" })
                private static void a(Class paramClass, String paramString, int paramInt) {
                try {
                ((Map) getPrivateStatic(EntityTypes.class, "c")).put(paramString, paramClass);
                ((Map) getPrivateStatic(EntityTypes.class, "d")).put(paramClass, paramString);
                ((Map) getPrivateStatic(EntityTypes.class, "e")).put(Integer.valueOf(paramInt), paramClass);
                ((Map) getPrivateStatic(EntityTypes.class, "f")).put(paramClass, Integer.valueOf(paramInt));
                ((Map) getPrivateStatic(EntityTypes.class, "g")).put(paramString, Integer.valueOf(paramInt));
                } catch (Exception exc) {
                }
                }
        }
      
      
       
      
        public class CustomEntitySheep extends EntitySheep {
    
          
    //Yes, this IS an NMS world (1.8.3)
            public CustomEntitySheep(World mcWorld) {
                super(mcWorld);
              
                try {
                    Field bField = PathfinderGoalSelector.class.getDeclaredField("b");
                    bField.setAccessible(true);
                    Field cField = PathfinderGoalSelector.class.getDeclaredField("c");
                    cField.setAccessible(true);
                    bField.set(goalSelector, new UnsafeList<PathfinderGoalSelector>());
                    bField.set(targetSelector, new UnsafeList<PathfinderGoalSelector>());
                    cField.set(goalSelector, new UnsafeList<PathfinderGoalSelector>());
                    cField.set(targetSelector, new UnsafeList<PathfinderGoalSelector>());
                  
                    } catch (Exception exc) {
                    exc.printStackTrace();
                    }
              
            }
      
        }
        public Entity spawn(Location location) {
            Entity e = CustomEntityType.spawn(location);
            return e;
        }
    
    }
    
    I'm getting this error:

    Code:
    java.lang.NoSuchMethodException: com.dumbninja22.plugin.ver.v1_8_R2$CustomEntitySheep.<init>(net.minecraft.server.v1_8_R2.World)
    [15:13:55] [Server thread/WARN]:     at java.lang.Class.getConstructor0(Unknown Source)
    [15:13:55] [Server thread/WARN]:     at java.lang.Class.getConstructor(Unknown Source)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.SpawnerCreature.a(SpawnerCreature.java:276)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.ChunkProviderGenerate.getChunkAt(SourceFile:475)
    [15:13:55] [Server thread/WARN]:     at org.bukkit.craftbukkit.v1_8_R2.generator.NormalChunkGenerator.getChunkAt(NormalChunkGenerator.java:51)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.ChunkProviderServer.getChunkAt(ChunkProviderServer.java:266)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.Chunk.loadNearby(Chunk.java:985)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.ChunkProviderServer.originalGetChunkAt(ChunkProviderServer.java:185)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.ChunkProviderServer.getChunkAt(ChunkProviderServer.java:118)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.PlayerChunkMap$PlayerChunk.<init>(PlayerChunkMap.java:337)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.PlayerChunkMap.a(PlayerChunkMap.java:93)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.PlayerChunkMap.b(PlayerChunkMap.java:172)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.PlayerChunkMap.movePlayer(PlayerChunkMap.java:249)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.PlayerList.d(PlayerList.java:336)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.PlayerConnection.a(PlayerConnection.java:453)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.PacketPlayInFlying.a(SourceFile:126)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.PacketPlayInFlying$PacketPlayInPositionLook.a(SourceFile:18)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.PlayerConnectionUtils$1.run(SourceFile:13)
    [15:13:55] [Server thread/WARN]:     at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    [15:13:55] [Server thread/WARN]:     at java.util.concurrent.FutureTask.run(Unknown Source)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.SystemUtils.a(SourceFile:60)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.MinecraftServer.A(MinecraftServer.java:714)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.DedicatedServer.A(DedicatedServer.java:368)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.MinecraftServer.z(MinecraftServer.java:655)
    [15:13:55] [Server thread/WARN]:     at net.minecraft.server.v1_8_R2.MinecraftServer.run(MinecraftServer.java:558)
    [15:13:55] [Server thread/WARN]:     at java.lang.Thread.run(Unknown Source)
         
     
  2. Offline

    westjet

    Well then. It appears I had to compromise, but at least my problem is solved. I ended up separating the custom sheep class and constructor and putting it in another "file" within the project. That does mean that everytime a new MC version comes out I'll have to copy/paste two files instead of one, but what can I do. Lesson Learned: Nested classes are not as good as advertised.

    If there are no more comments/suggestions, I'm requesting a lock.
     
Thread Status:
Not open for further replies.

Share This Page