Greenadine

CustomEntityType.java

Sep 17th, 2017
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 7.59 KB | None | 0 0
  1. package me.greenadine.scarecrow.nms;
  2.  
  3. import java.lang.reflect.Field;
  4. import java.util.List;
  5. import java.util.Map;
  6.  
  7. import org.bukkit.entity.EntityType;
  8.  
  9. import net.minecraft.server.v1_12_R1.BiomeBase;
  10. import net.minecraft.server.v1_12_R1.BiomeBase.BiomeMeta;
  11. import net.minecraft.server.v1_12_R1.EntityBat;
  12. import net.minecraft.server.v1_12_R1.EntityChicken;
  13. import net.minecraft.server.v1_12_R1.EntityCow;
  14. import net.minecraft.server.v1_12_R1.EntityHorse;
  15. import net.minecraft.server.v1_12_R1.EntityHorseDonkey;
  16. import net.minecraft.server.v1_12_R1.EntityHorseMule;
  17. import net.minecraft.server.v1_12_R1.EntityHorseSkeleton;
  18. import net.minecraft.server.v1_12_R1.EntityInsentient;
  19. import net.minecraft.server.v1_12_R1.EntityLlama;
  20. import net.minecraft.server.v1_12_R1.EntityMushroomCow;
  21. import net.minecraft.server.v1_12_R1.EntityOcelot;
  22. import net.minecraft.server.v1_12_R1.EntityParrot;
  23. import net.minecraft.server.v1_12_R1.EntityPig;
  24. import net.minecraft.server.v1_12_R1.EntityRabbit;
  25. import net.minecraft.server.v1_12_R1.EntitySheep;
  26. import net.minecraft.server.v1_12_R1.EntitySquid;
  27. import net.minecraft.server.v1_12_R1.EntityTypes;
  28. import net.minecraft.server.v1_12_R1.EntityVillager;
  29.  
  30. public enum CustomEntityType {
  31.    
  32.     BAT("Bat", 65, EntityType.BAT, EntityBat.class, CustomEntityBat.class),
  33.     CHICKEN("Chicken", 93, EntityType.CHICKEN, EntityChicken.class, CustomEntityBat.class),
  34.     COW("Cow", 92, EntityType.COW, EntityCow.class, CustomEntityBat.class),
  35.     MUSHROOM_COW("Mooshroom", 96, EntityType.MUSHROOM_COW, EntityMushroomCow.class, CustomEntityBat.class),
  36.     OCELOT("Ocelot", 98, EntityType.OCELOT, EntityOcelot.class, CustomEntityBat.class),
  37.     PARROT("Parrot", 105, EntityType.PARROT, EntityParrot.class, CustomEntityBat.class),
  38.     PIG("Pig", 90, EntityType.PIG, EntityPig.class, CustomEntityBat.class),
  39.     RABBIT("Rabbit", 101, EntityType.RABBIT, EntityRabbit.class, CustomEntityBat.class),
  40.     SHEEP("Sheep", 91, EntityType.SHEEP, EntitySheep.class, CustomEntityBat.class),
  41.     SQUID("Squid", 94, EntityType.SQUID, EntitySquid.class, CustomEntityBat.class),
  42.     HORSE("Horse", 100, EntityType.HORSE, EntityHorse.class, CustomEntityBat.class),
  43.     HORSE_SKELETON("Skeleton Horse", 28, EntityType.SKELETON_HORSE, EntityHorseSkeleton.class, CustomEntityBat.class),
  44.     HORSE_DONKEY("Donkey", 31, EntityType.DONKEY, EntityHorseDonkey.class, CustomEntityBat.class),
  45.     HORSE_MULE("MULE", 32, EntityType.MULE, EntityHorseMule.class, CustomEntityBat.class),
  46.     LLAMA("Llama", 103, EntityType.LLAMA, EntityLlama.class, CustomEntityBat.class),
  47.     VILLAGER("Villager", 120, EntityType.VILLAGER, EntityVillager.class, CustomEntityBat.class);
  48.    
  49.      
  50.     private String name;
  51.     private int id;
  52.     private EntityType entityType;
  53.     private Class<? extends EntityInsentient> nmsClass;
  54.     private Class<? extends EntityInsentient> customClass;
  55.      
  56.     private CustomEntityType(String name, int id, EntityType entityType, Class<? extends EntityInsentient> nmsClass, Class<? extends EntityInsentient> customClass)
  57.     {
  58.         this.name = name;
  59.         this.id = id;
  60.         this.entityType = entityType;
  61.         this.nmsClass = nmsClass;
  62.         this.customClass = customClass;
  63.     }
  64.      
  65.     public String getName()
  66.     {
  67.         return name;
  68.     }
  69.      
  70.     public int getID()
  71.     {
  72.         return id;
  73.     }
  74.      
  75.     public EntityType getEntityType()
  76.     {
  77.         return entityType;
  78.     }
  79.      
  80.     public Class<? extends EntityInsentient> getNMSClass()
  81.     {
  82.         return nmsClass;
  83.     }
  84.      
  85.     public Class<? extends EntityInsentient> getCustomClass()
  86.     {
  87.         return customClass;
  88.     }
  89.      
  90.     /**
  91.     * Register our entities.
  92.     */
  93.     public static void registerEntities()
  94.     {
  95.         for (CustomEntityType entity : values())
  96.             a(entity.getCustomClass(), entity.getName(), entity.getID());
  97.      
  98.         // BiomeBase#biomes became private.
  99.         BiomeBase[] biomes;
  100.         try
  101.         {
  102.             biomes = (BiomeBase[]) getPrivateStatic(BiomeBase.class, "biomes");
  103.         } catch (Exception exc)
  104.         {
  105.             // Unable to fetch.
  106.             return;
  107.         }
  108.         for (BiomeBase biomeBase : biomes)
  109.         {
  110.             if (biomeBase == null)
  111.                 break;
  112.      
  113.             // This changed names from J, K, L and M.
  114.             for (String field : new String[] { "as", "at", "au", "av" })
  115.             {
  116.                 try
  117.                 {
  118.                     Field list = BiomeBase.class.getDeclaredField(field);
  119.                     list.setAccessible(true);
  120.                     @SuppressWarnings("unchecked")
  121.                     List<BiomeMeta> mobList = (List<BiomeMeta>) list.get(biomeBase);
  122.      
  123.                     // Write in our custom class.
  124.                     for (BiomeMeta meta : mobList)
  125.                         for (CustomEntityType entity : values())
  126.                             if (entity.getNMSClass().equals(meta.b))
  127.                                 meta.b = entity.getCustomClass();
  128.                 } catch (Exception e)
  129.                 {
  130.                     e.printStackTrace();
  131.                 }
  132.             }
  133.         }
  134.     }
  135.      
  136.     /**
  137.     * Unregister our entities to prevent memory leaks. Call on disable.
  138.     */
  139.     @SuppressWarnings("rawtypes")
  140.     public static void unregisterEntities() {
  141.         for (CustomEntityType entity : values()) {
  142.             // Remove our class references.
  143.             try {
  144.                 ((Map) getPrivateStatic(EntityTypes.class, "d")).remove(entity.getCustomClass());
  145.             } catch (Exception e) {
  146.                 e.printStackTrace();
  147.             }
  148.            
  149.             try {
  150.                 ((Map) getPrivateStatic(EntityTypes.class, "f")).remove(entity.getCustomClass());
  151.             } catch (Exception e) {
  152.                 e.printStackTrace();
  153.             }
  154.         }
  155.          
  156.         for (CustomEntityType entity : values())
  157.             try {
  158.                 // Unregister each entity by writing the NMS back in place of the custom class.
  159.                 a(entity.getNMSClass(), entity.getName(), entity.getID());
  160.             } catch (Exception e) {
  161.                 e.printStackTrace();
  162.             }
  163.          
  164.             // Biomes#biomes was made private so use reflection to get it.
  165.             BiomeBase[] biomes;
  166.             try {
  167.                 biomes = (BiomeBase[]) getPrivateStatic(BiomeBase.class, "biomes");
  168.             } catch (Exception exc) {
  169.                 // Unable to fetch.
  170.                 return;
  171.             }
  172.             for (BiomeBase biomeBase : biomes) {
  173.                 if (biomeBase == null)
  174.                     break;
  175.          
  176.                 // The list fields changed names but update the meta regardless.
  177.                 for (String field : new String[] { "as", "at", "au", "av" })
  178.                     try {
  179.                         Field list = BiomeBase.class.getDeclaredField(field);
  180.                         list.setAccessible(true);
  181.                         @SuppressWarnings("unchecked")
  182.                         List<BiomeMeta> mobList = (List<BiomeMeta>) list.get(biomeBase);
  183.                        
  184.                         // Make sure the NMS class is written back over our custom class.
  185.                         for (BiomeMeta meta : mobList)
  186.                             for (CustomEntityType entity : values())
  187.                                 if (entity.getCustomClass().equals(meta.b))
  188.                                     meta.b = entity.getNMSClass();
  189.                     } catch (Exception e) {
  190.                         e.printStackTrace();
  191.                     }
  192.             }
  193.     }
  194.      
  195.     /**
  196.     * A convenience method.
  197.     * @param clazz The class.
  198.     * @param f The string representation of the private static field.
  199.     * @return The object found
  200.     * @throws Exception if unable to get the object.
  201.     */
  202.     @SuppressWarnings("rawtypes")
  203.     private static Object getPrivateStatic(Class clazz, String f) throws Exception {
  204.         Field field = clazz.getDeclaredField(f);
  205.         field.setAccessible(true);
  206.         return field.get(null);
  207.         }
  208.      
  209.     /*
  210.     * Since 1.7.2 added a check in their entity registration, simply bypass it and write to the maps ourself.
  211.     */
  212.     @SuppressWarnings({ "unchecked", "rawtypes" })
  213.     private static void a(Class paramClass, String paramString, int paramInt) {
  214.         try {
  215.             ((Map) getPrivateStatic(EntityTypes.class, "c")).put(paramString, paramClass);
  216.             ((Map) getPrivateStatic(EntityTypes.class, "d")).put(paramClass, paramString);
  217.             ((Map) getPrivateStatic(EntityTypes.class, "e")).put(Integer.valueOf(paramInt), paramClass);
  218.             ((Map) getPrivateStatic(EntityTypes.class, "f")).put(paramClass, Integer.valueOf(paramInt));
  219.             ((Map) getPrivateStatic(EntityTypes.class, "g")).put(paramString, Integer.valueOf(paramInt));
  220.         } catch (Exception exc) {
  221.             // Unable to register the new class.
  222.         }
  223.     }
  224. }
Advertisement
Add Comment
Please, Sign In to add comment