Escad

Custom Entity Registration (1.15.2, commented)

Mar 28th, 2020
582
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 4.24 KB | None | 0 0
  1. public class CustomEntityType<T extends EntityLiving> {
  2.  
  3.     @Nullable
  4.     private static Field REGISTRY_MAT_MAP;
  5.  
  6.     static {
  7.         try {
  8.             REGISTRY_MAT_MAP = RegistryMaterials.class.getDeclaredField("c");
  9.         } catch (ReflectiveOperationException err) {
  10.             // Should only occur if REGISTRY_MAT_MAP field name changes
  11.             REGISTRY_MAT_MAP = null;
  12.             err.printStackTrace();
  13.         }
  14.     }
  15.  
  16.     private final MinecraftKey key;
  17.     private final Class<T> clazz;
  18.     private final EntityTypes.b<T> maker;
  19.     private EntityTypes<? super T> parentType;
  20.     private EntityTypes<T> entityType;
  21.     private boolean registered;
  22.  
  23.     public CustomEntityType(String name, Class<T> customEntityClass, EntityTypes<? super T> parentType, EntityTypes.b<T> maker) {
  24.         this.key = MinecraftKey.a(name);
  25.         this.clazz = customEntityClass;
  26.         this.parentType = parentType;
  27.         this.maker = maker;
  28.     }
  29.  
  30.     public boolean isRegistered() {
  31.         return registered;
  32.     }
  33.  
  34.     public org.bukkit.entity.Entity spawn(WorldServer server, Location loc) {
  35.         Entity entity = entityType.spawnCreature(server,
  36.                 null, null, null, new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()),
  37.                 EnumMobSpawn.EVENT, true, false);
  38.         return entity == null ? null : entity.getBukkitEntity();
  39.     }
  40.  
  41.     public void register() throws IllegalStateException {
  42.         if (registered || IRegistry.ENTITY_TYPE.getOptional(key).isPresent()) {
  43.             // Throw exception if for some reason a registered custom entity is being registered again
  44.             throw new IllegalStateException(String.format
  45.                     ("Unable to register entity with key '%s' as it is already registered.", key));
  46.             return;
  47.         }
  48.         // Get name-datafixer mappings
  49.         Map<Object, Type<?>> dataTypes = (Map<Object, Type<?>>)DataConverterRegistry.a()
  50.                 .getSchema(DataFixUtils.makeKey(SharedConstants.getGameVersion().getWorldVersion()))
  51.                 .findChoiceType(DataConverterTypes.ENTITY_TREE).types();
  52.         // Map custom entity name to parent entity datafixer
  53.         dataTypes.put(key.toString(), dataTypes.get(parentType.h().toString().replace("entity/", "")));
  54.         EntityTypes.a<T> a = EntityTypes.a.a(maker, EnumCreatureType.CREATURE);
  55.         entityType = a.a(key.getKey());
  56.         // Map custom entity key to entity type in deep registry materials map
  57.         IRegistry.a(IRegistry.ENTITY_TYPE, key.getKey(), entityType);
  58.         registered = true; // boolean checker to prevent illegal registration states
  59.     }
  60.  
  61.     @SuppressWarnings("unchecked") // Suppress warning on cast to registry material map
  62.     public void unregister() throws IllegalStateException {
  63.         if (!registered) {
  64.             // Throw exception if for some reason an non-registered custom entity is being "unregistered"
  65.             throw new IllegalArgumentException(String.format
  66.                     ("Entity with key '%s' could not be unregistered, as it is not in the registry", key));
  67.         }
  68.         // Remove the mapping for our custom entity type to a vanilla entity type
  69.         Map<Object, Type<?>> dataTypes = (Map<Object, Type<?>>)DataConverterRegistry.a()
  70.                 .getSchema(DataFixUtils.makeKey(SharedConstants.getGameVersion().getWorldVersion()))
  71.                 .findChoiceType(DataConverterTypes.ENTITY_TREE).types();
  72.         dataTypes.remove(key.toString());
  73.  
  74.         try {
  75.             if (REGISTRY_MAT_MAP == null) {
  76.                 // Should only occur if REGISTRY_MAT_MAP's field name changes
  77.                 throw new ReflectiveOperationException("Field not initially found");
  78.             }
  79.             // Remove deep registry mapping for our custom entity's NamespacedKey
  80.             REGISTRY_MAT_MAP.setAccessible(true);
  81.             Object o = REGISTRY_MAT_MAP.get(IRegistry.ENTITY_TYPE);
  82.             ((BiMap<MinecraftKey, ?>)o).remove(key);
  83.             // Set the modified map
  84.             REGISTRY_MAT_MAP.set(IRegistry.ENTITY_TYPE, o);
  85.             REGISTRY_MAT_MAP.setAccessible(false);
  86.             registered = false;
  87.         } catch (ReflectiveOperationException err) {
  88.             // Should only occur if REGISTRY_MAT_MAP's type changes
  89.             err.printStackTrace();
  90.         }
  91.     }
  92.  
  93. }
Add Comment
Please, Sign In to add comment