1.15.2 I am getting a NullPointerException when my custom entity is registered.

Discussion in 'Spigot Plugin Development' started by HoiTemmieColeg, Apr 2, 2020.

  1. I followed @Escad's tutorial(ish) on how to create a custom entity here but I'm getting an error. When my plugin loads and my Custom Giant is registered, I get a NullPointerException.

    Here are the relevant variables from my JavaPlugin class:
    Code (Java):
    @Override
    public void onLoad() {
        zombie = new CustomEntityType<CustomGiantZombie>("GiantBossEntity", CustomGiantZombie.class, EntityTypes.GIANT, CustomGiantZombie::new);
        zombie.register();
    }

    public CustomEntityType<CustomGiantZombie> zombie;
    Here is CustomEntityType.java:
    Code (Java):
    public class CustomEntityType<T extends EntityLiving> {

        @Nullable
        private static Field REGISTRY_MAT_MAP;

        static {
            try {
                REGISTRY_MAT_MAP = RegistryMaterials.class.getDeclaredField("c");
            } catch (ReflectiveOperationException err) {
                err.printStackTrace();
                REGISTRY_MAT_MAP = null;
                // technically should only occur if server version changes or jar is modified in "weird" ways
            }
        }

        private final MinecraftKey key;
        private final Class<T> clazz;
        private final EntityTypes.b<T> maker;
        private EntityTypes<? super T> parentType;
        private EntityTypes<T> entityType;
        private boolean registered;

        public CustomEntityType(String name, Class<T> customEntityClass, EntityTypes<? super T> parentType, EntityTypes.b<T> maker) {
            this.key = MinecraftKey.a(name); // returns null if 256+ chars, non-alphanumeric, or contains uppercase chars
            this.clazz = customEntityClass;
            this.parentType = parentType;
            this.maker = maker;
        }

        public org.bukkit.entity.Entity spawn(Location loc) {
            // Parameters: nmsWorld, initialNBT, customName, spawningPlayer, blockPos, spawnReason, fixPos, flag1(?)
            Entity entity = entityType.spawnCreature(((CraftWorld)loc.getWorld()).getHandle(),
                    null, null, null, new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()),
                    EnumMobSpawn.EVENT, true, false);
            return entity == null ? null : entity.getBukkitEntity();
        }

        public void register() throws IllegalStateException {
            if (registered || IRegistry.ENTITY_TYPE.getOptional(key).isPresent()) {
                throw new IllegalStateException(String.format
                        ("Unable to register entity with key '%s' as it is already registered.", key));
            }
            // Add custom entity to data fixers map with parent entity's data fixer
            Map<Object, Type<?>> dataTypes = (Map<Object, Type<?>>)DataConverterRegistry.a()
                    .getSchema(DataFixUtils.makeKey(SharedConstants.getGameVersion().getWorldVersion()))
                    .findChoiceType(DataConverterTypes.ENTITY_TREE).types(); // DataConverterTypes.ENTITY in < 1.15.2
            dataTypes.put(key.toString(), dataTypes.get(parentType.h().toString().replace("entity/", "")));
            // Add our custom entity to the entity registry map
            EntityTypes.a<T> a = EntityTypes.a.a(maker, EnumCreatureType.CREATURE);
            entityType = a.a(key.getKey());
            IRegistry.a(IRegistry.ENTITY_TYPE, key.getKey(), entityType);
            registered = true;
        }

        @SuppressWarnings("unchecked")
        public void unregister() throws IllegalStateException {
            if (!registered) {
                throw new IllegalArgumentException(String.format
                        ("Entity with key '%s' could not be unregistered, as it is not in the registry", key));
            }
            // Remove custom entity from data fixers map
            Map<Object, Type<?>> dataTypes = (Map<Object, Type<?>>)DataConverterRegistry.a()
                    .getSchema(DataFixUtils.makeKey(SharedConstants.getGameVersion().getWorldVersion()))
                    .findChoiceType(DataConverterTypes.ENTITY_TREE).types();
            dataTypes.remove(key.toString());
            try {
                // Remove our custom entity from entity registry map, which takes a little reflection in 1.15
                if (REGISTRY_MAT_MAP == null) {
                    throw new ReflectiveOperationException("Field not initially found");
                }
                REGISTRY_MAT_MAP.setAccessible(true);
                Object o = REGISTRY_MAT_MAP.get(IRegistry.ENTITY_TYPE);
                ((BiMap<MinecraftKey, ?>)o).remove(key);
                REGISTRY_MAT_MAP.set(IRegistry.ENTITY_TYPE, o);
                REGISTRY_MAT_MAP.setAccessible(false);
                registered = false;
            } catch (ReflectiveOperationException err) {
                err.printStackTrace();
            }
        }

    }
    Here is CustomGiantEntity.java
    Code (Java):

    public class CustomGiantZombie extends EntityGiantZombie {

        public CustomGiantZombie(EntityTypes<? extends EntityGiantZombie> entityType, World world) {
            this(world);
        }

        public CustomGiantZombie(World world) {
            super(EntityTypes.GIANT, world);
        }
    }
    Finally, my error is here:
    Code (Text):
    [org.bukkit.craftbukkit.v1_15_R1.CraftServer] null initializing CreaturesTest vv1.0-SNAPSHOT (Is it up to date?)
    java.lang.NullPointerException: null
            at net.almostmc.creaturesTest.CustomMobs.CustomEntityType.register(CustomEntityType.java:60) ~[?:?]
            at net.almostmc.creaturesTest.Creatures.onLoad(Creatures.java:22) ~[?:?]
            at org.bukkit.craftbukkit.v1_15_R1.CraftServer.loadPlugins(CraftServer.java:363) ~[patched_1.15.2.jar:git-Paper-143]
            at net.minecraft.server.v1_15_R1.DedicatedServer.init(DedicatedServer.java:234) ~[patched_1.15.2.jar:git-Paper-143]
            at net.minecraft.server.v1_15_R1.MinecraftServer.run(MinecraftServer.java:885) ~[patched_1.15.2.jar:git-Paper-143]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_241]
    Now I would love to troubleshoot this myself, but I don't really understand the cause of the error, which is why I'm asking for help.

    I apologize for being a nuisance, but it would be awesome if someone could help me understand the cause of this issue so I can fix it.
     
  2.  
    • Agree Agree x 1
  3. Thank you so much! I feel really dumb right now.
     
  4. Hey, Thanks Escad for making my qestion even possible

    So my registration works fine, my spawning works as well, but I was wondering how to not super the Parent entity to get the pig that acts like a zombie....
    I tried making the Parententitytypes in the construktor null, but I wasn't working as I already guessed.
    So how do I do this without getting a NullPointerException?

    I hope you can help me.. :)