[Solved 1.16.x] Register Custom Entity NullPointerException

Hello Guys, at first, sorry for the bad english skills^^

I need help by the registration and spawning of a custom Entity. I get a NullPointerException, when i try spawn the custom Entity.

Error-Log

java.lang.NullPointerException: null
at net.minecraft.server.v1_16_R3.AttributeMapBase.lambda$a$1(AttributeMapBase.java:52) ~[patched_1.16.5.jar:git-Paper-562]
at java.util.HashMap.computeIfAbsent(HashMap.java:1133) ~[?:?]
at net.minecraft.server.v1_16_R3.AttributeMapBase.a(AttributeMapBase.java:51) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityLiving.getAttributeInstance(EntityLiving.java:2131) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityLiving.(EntityLiving.java:264) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityInsentient.(EntityInsentient.java:129) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityCreature.(EntityCreature.java:20) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityAgeable.(EntityAgeable.java:23) ~[patched_1.16.5.jar:git-Paper-562] at net.minecraft.server.v1_16_R3.EntityVillagerAbstract.(EntityVillagerAbstract.java:64) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityVillager.(EntityVillager.java:136) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityVillager.(EntityVillager.java:132) ~[patched_1.16.5.jar:git-Paper-562]
at net.meyerit.haj.entity.VillagerTraderEntity.(VillagerTraderEntity.java:23) ~[?:?]
at net.minecraft.server.v1_16_R3.EntityTypes.a(EntityTypes.java:483) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityTypes.createCreature(EntityTypes.java:356) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityTypes.spawnCreature(EntityTypes.java:342) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityTypes.spawnCreature(EntityTypes.java:323) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityTypes.spawnCreature(EntityTypes.java:317) ~[patched_1.16.5.jar:git-Paper-562]
at net.meyerit.haj.CustomEntityType.spawn(CustomEntityType.java:38) ~[?:?]
at net.meyerit.haj.HaveAJob.useItem(HaveAJob.java:90) ~[?:?]
at com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor2.execute(Unknown Source) ~[?:?]
at org.bukkit.plugin.EventExecutor.lambda$create$1(EventExecutor.java:69) ~[patched_1.16.5.jar:git-Paper-562]
at co.aikar.timings.TimedEventExecutor.execute(TimedEventExecutor.java:80) ~[patched_1.16.5.jar:git-Paper-562]
at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:70) ~[patched_1.16.5.jar:git-Paper-562]
at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:607) ~[patched_1.16.5.jar:git-Paper-562]
at org.bukkit.craftbukkit.v1_16_R3.event.CraftEventFactory.callPlayerInteractEvent(CraftEventFactory.java:531) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.PlayerInteractManager.a(PlayerInteractManager.java:498) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.PlayerConnection.a(PlayerConnection.java:1698) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.PacketPlayInUseItem.a(PacketPlayInUseItem.java:31) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.PacketPlayInUseItem.a(PacketPlayInUseItem.java:9) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.PlayerConnectionUtils.lambda$ensureMainThread$1(PlayerConnectionUtils.java:35) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.TickTask.run(SourceFile:18) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.IAsyncTaskHandler.executeTask(IAsyncTaskHandler.java:136) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.IAsyncTaskHandlerReentrant.executeTask(SourceFile:23) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.IAsyncTaskHandler.executeNext(IAsyncTaskHandler.java:109) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.MinecraftServer.bb(MinecraftServer.java:1252) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.MinecraftServer.executeNext(MinecraftServer.java:1245) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.IAsyncTaskHandler.executeAll(IAsyncTaskHandler.java:95) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.MinecraftServer.a(MinecraftServer.java:1381) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.MinecraftServer.w(MinecraftServer.java:1116) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.MinecraftServer.lambda$a$0(MinecraftServer.java:289) ~[patched_1.16.5.jar:git-Paper-562]
at java.lang.Thread.run(Thread.java:834) [?:?]

Register and Spawn
public final class PluginName extends JavaPlugin implements Listener
{
    public static CustomEntityType<VillagerTraderEntity> VILLAGER_TRADER = new CustomEntityType<>("customtrader", VillagerTraderEntity.class, EntityTypes.VILLAGER, VillagerTraderEntity::new);

    @Override
    public void onLoad()
    {
        VILLAGER_TRADER.register();
    }

    @EventHandler
    public void useItem(PlayerInteractEvent playerInteractEvent)
    {
        if(playerInteractEvent.hasItem())
        {
            ItemStack item = playerInteractEvent.getItem();
            assert item != null;

            if(item.getType() == Material.STICK)
            {
               VILLAGER_TRADER.spawn(Objects.requireNonNull(playerInteractEvent.getInteractionPoint()));
            }
        }
    }
}
CustomEntityType
public class CustomEntityType<T extends EntityLiving>
{
	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 String getID()
    {
        return key.getKey();
    }

    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.i().getKey().replace("entity/", "")));
        // Add our custom entity to the entity registry map
        EntityTypes.Builder<T> a = EntityTypes.Builder.a(maker, EnumCreatureType.CREATURE);
        entityType = a.a(key.getKey());
        IRegistry.a(IRegistry.ENTITY_TYPE, key.getKey(), entityType);
        Bukkit.getConsoleSender().sendMessage("Register Entity with ID \"" + this.key.getKey() + "\" with Class " + clazz + " as Type of: " + entityType);
        registered = true;
	}
VillagerTraderEntity
public class VillagerTraderEntity extends EntityVillager
{
    public VillagerTraderEntity(Location location, String name, String tag, VillagerData villagerData)
    {
        super(EntityTypes.VILLAGER, ((CraftWorld) location.getWorld()).getHandle());
        this.setPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
        this.setCustomName(new ChatComponentText(name));
        this.setCustomNameVisible(true);
        this.addScoreboardTag(tag);
        this.setVillagerData(villagerData);
    }

    public VillagerTraderEntity(EntityTypes entityTypes, World world)
    {
        super(entityTypes, world);
    }

    @Override
    protected void mobTick()
    {
    }

    @Override
    protected void initPathfinder()
    {
        this.goalSelector.a(0, new PathfinderGoalRandomLookaround(this));
        this.goalSelector.a(1, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 0.5F));
    }

    @Override
    public IChatBaseComponent getScoreboardDisplayName()
    {
        return new ChatComponentText("Händler");
    }

    @Override
    public void saveData(NBTTagCompound nbttagcompound)
    {
        super.saveData(nbttagcompound);
        nbttagcompound.setString("id", HaveAJob.VILLAGER_TRADER.getID());
    }

    @Override
    public void loadData(NBTTagCompound nbttagcompound)
    {
        super.loadData(nbttagcompound);
    }
}

The CustomEntityType Class is from this Thread on Spigot.

Maybe someone can help me :slight_smile:

You forgot to register the generic Attribute.
Setting a value of an generic Attribute which isn’t registered for this entity throws a npe.

1 Like

I just registered all the attributes, but still get a NullPointerException.

Error-Log

java.lang.NullPointerException: null
at net.minecraft.server.v1_16_R3.AttributeMapBase.lambda$a$1(AttributeMapBase.java:52) ~[patched_1.16.5.jar:git-Paper-562]
at java.util.HashMap.computeIfAbsent(HashMap.java:1133) ~[?:?]
at net.minecraft.server.v1_16_R3.AttributeMapBase.a(AttributeMapBase.java:51) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityLiving.getAttributeInstance(EntityLiving.java:2131) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityLiving.(EntityLiving.java:264) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityInsentient.(EntityInsentient.java:129) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityCreature.(EntityCreature.java:20) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityAgeable.(EntityAgeable.java:23) ~[patched_1.16.5.jar:git-Paper-562] at net.minecraft.server.v1_16_R3.EntityVillagerAbstract.(EntityVillagerAbstract.java:64) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityVillager.(EntityVillager.java:136) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityVillager.(EntityVillager.java:132) ~[patched_1.16.5.jar:git-Paper-562]
at net.meyerit.haj.entity.VillagerTraderEntity.(VillagerTraderEntity.java:61) ~[?:?]
at net.minecraft.server.v1_16_R3.EntityTypes.a(EntityTypes.java:483) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityTypes.createCreature(EntityTypes.java:356) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityTypes.spawnCreature(EntityTypes.java:342) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityTypes.spawnCreature(EntityTypes.java:323) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.EntityTypes.spawnCreature(EntityTypes.java:317) ~[patched_1.16.5.jar:git-Paper-562]
at net.meyerit.haj.CustomEntityType.spawn(CustomEntityType.java:38) ~[?:?]
at net.meyerit.haj.HaveAJob.useItem(HaveAJob.java:90) ~[?:?]
at com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor2.execute(Unknown Source) ~[?:?]
at org.bukkit.plugin.EventExecutor.lambda$create$1(EventExecutor.java:69) ~[patched_1.16.5.jar:git-Paper-562]
at co.aikar.timings.TimedEventExecutor.execute(TimedEventExecutor.java:80) ~[patched_1.16.5.jar:git-Paper-562]
at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:70) ~[patched_1.16.5.jar:git-Paper-562]
at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:607) ~[patched_1.16.5.jar:git-Paper-562]
at org.bukkit.craftbukkit.v1_16_R3.event.CraftEventFactory.callPlayerInteractEvent(CraftEventFactory.java:531) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.PlayerInteractManager.a(PlayerInteractManager.java:498) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.PlayerConnection.a(PlayerConnection.java:1698) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.PacketPlayInUseItem.a(PacketPlayInUseItem.java:31) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.PacketPlayInUseItem.a(PacketPlayInUseItem.java:9) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.PlayerConnectionUtils.lambda$ensureMainThread$1(PlayerConnectionUtils.java:35) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.TickTask.run(SourceFile:18) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.IAsyncTaskHandler.executeTask(IAsyncTaskHandler.java:136) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.IAsyncTaskHandlerReentrant.executeTask(SourceFile:23) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.IAsyncTaskHandler.executeNext(IAsyncTaskHandler.java:109) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.MinecraftServer.bb(MinecraftServer.java:1252) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.MinecraftServer.executeNext(MinecraftServer.java:1245) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.IAsyncTaskHandler.awaitTasks(IAsyncTaskHandler.java:119) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.MinecraftServer.sleepForTick(MinecraftServer.java:1206) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.MinecraftServer.w(MinecraftServer.java:1120) ~[patched_1.16.5.jar:git-Paper-562]
at net.minecraft.server.v1_16_R3.MinecraftServer.lambda$a$0(MinecraftServer.java:289) ~[patched_1.16.5.jar:git-Paper-562]
at java.lang.Thread.run(Thread.java:834) [?:?]

VillagerTraderEntity
public class VillagerTraderEntity extends EntityVillager
{
    private static final Map<EntityTypes<?>, AttributeProvider> DEFAULT_ATTRIBUTES;
    static {
        try {
            final Field modifiers = Field.class.getDeclaredField("modifiers");
            modifiers.setAccessible(true);
            final Field field = AttributeDefaults.class.getDeclaredField("b");
            modifiers.setInt(field, modifiers.getInt(field) & ~Modifier.FINAL);
            field.setAccessible(true);
            DEFAULT_ATTRIBUTES = new HashMap((Map<EntityTypes<?>, AttributeProvider>) field.get(null));
            field.set(null, DEFAULT_ATTRIBUTES);
        } catch (Throwable reason) {
            throw new RuntimeException(reason);
        }
    }

    private void setup()
    {
        DEFAULT_ATTRIBUTES.put(EntityTypes.VILLAGER, DEFAULT_ATTRIBUTES.get(GenericAttributes.ATTACK_DAMAGE));
        DEFAULT_ATTRIBUTES.put(EntityTypes.VILLAGER, DEFAULT_ATTRIBUTES.get(GenericAttributes.ARMOR));
        DEFAULT_ATTRIBUTES.put(EntityTypes.VILLAGER, DEFAULT_ATTRIBUTES.get(GenericAttributes.ARMOR_TOUGHNESS));
        DEFAULT_ATTRIBUTES.put(EntityTypes.VILLAGER, DEFAULT_ATTRIBUTES.get(GenericAttributes.MAX_HEALTH));
        DEFAULT_ATTRIBUTES.put(EntityTypes.VILLAGER, DEFAULT_ATTRIBUTES.get(GenericAttributes.ATTACK_KNOCKBACK));
        DEFAULT_ATTRIBUTES.put(EntityTypes.VILLAGER, DEFAULT_ATTRIBUTES.get(GenericAttributes.ATTACK_SPEED));
        DEFAULT_ATTRIBUTES.put(EntityTypes.VILLAGER, DEFAULT_ATTRIBUTES.get(GenericAttributes.FLYING_SPEED));
        DEFAULT_ATTRIBUTES.put(EntityTypes.VILLAGER, DEFAULT_ATTRIBUTES.get(GenericAttributes.FOLLOW_RANGE));
        DEFAULT_ATTRIBUTES.put(EntityTypes.VILLAGER, DEFAULT_ATTRIBUTES.get(GenericAttributes.JUMP_STRENGTH));
        DEFAULT_ATTRIBUTES.put(EntityTypes.VILLAGER, DEFAULT_ATTRIBUTES.get(GenericAttributes.KNOCKBACK_RESISTANCE));
        DEFAULT_ATTRIBUTES.put(EntityTypes.VILLAGER, DEFAULT_ATTRIBUTES.get(GenericAttributes.LUCK));
        DEFAULT_ATTRIBUTES.put(EntityTypes.VILLAGER, DEFAULT_ATTRIBUTES.get(GenericAttributes.SPAWN_REINFORCEMENTS));
        DEFAULT_ATTRIBUTES.put(EntityTypes.VILLAGER, DEFAULT_ATTRIBUTES.get(GenericAttributes.MOVEMENT_SPEED));
        DEFAULT_ATTRIBUTES.put(EntityTypes.VILLAGER, EntityInsentient.p().a());
    }

    public VillagerTraderEntity(Location location, String name, String tag, VillagerData villagerData)
    {
        super(EntityTypes.VILLAGER, ((CraftWorld) location.getWorld()).getHandle());
        this.setPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
        this.setCustomName(new ChatComponentText(name));
        this.setCustomNameVisible(true);
        this.addScoreboardTag(tag);
        this.setVillagerData(villagerData);
        this.setup();
    }

    public VillagerTraderEntity(EntityTypes entityTypes, World world)
    {
        super(entityTypes, world);
        this.setup();
    }

    @Override
    protected void mobTick()
    {
    }

    @Override
    protected void initPathfinder()
    {
        this.goalSelector.a(0, new PathfinderGoalRandomLookaround(this));
        this.goalSelector.a(1, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 0.5F));
    }

    @Override
    public IChatBaseComponent getScoreboardDisplayName()
    {
        return new ChatComponentText("Händler");
    }

    @Override
    public void saveData(NBTTagCompound nbttagcompound)
    {
        super.saveData(nbttagcompound);
        nbttagcompound.setString("id", HaveAJob.VILLAGER_TRADER.getID());
    }

    @Override
    public void loadData(NBTTagCompound nbttagcompound)
    {
        super.loadData(nbttagcompound);
    }
}

Is this the right way to register attributes?

No it ist the wrong. way of doing it.

Just use that. https://papermc.io/javadocs/paper/1.16/org/bukkit/attribute/Attributable.html#registerAttribute-org.bukkit.attribute.Attribute-

https://papermc.io/javadocs/paper/1.16/org/bukkit/attribute/Attribute.html#GENERIC_ARMOR

this.getBukkitEntity().registerAttribute(Attribute.GENERIC_ARMOR)

Just do the same with the other attributes.

1 Like

You are my hero :smiley: It works! Thank you so much :sunglasses: :ok_hand:

Happy to see that my pr has its first user.