Register and Spawn a Custom Entity on 1.13.x


Here is a crude example on how to register and spawn a custom entity on 1.13.x with some comments on whats actually going on.

This is NOT for replacing vanilla entities. This is simply adding a new entity that extends from an existing vanilla entity. Replacing vanilla entities is a bit more involved and will be covered in a different tutorial/resource topic.

This is compatible with CraftBukkit, Spigot, and Paper server implementations.

Any questions or concerns, feel free to ask. I will update this topic as questions/concerns are addressed.

import com.mojang.datafixers.types.Type;
import net.minecraft.server.v1_13_R2.BlockPosition;
import net.minecraft.server.v1_13_R2.DataConverterRegistry;
import net.minecraft.server.v1_13_R2.DataConverterTypes;
import net.minecraft.server.v1_13_R2.EntityTypes;
import net.minecraft.server.v1_13_R2.EntityZombie;
import net.minecraft.server.v1_13_R2.World;
import org.bukkit.Location;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.craftbukkit.v1_13_R2.CraftWorld;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;

import java.util.Map;
import java.util.function.Function;

public class MyAwesomePlugin extends JavaPlugin {
    // this is where we store our custom entity type (for use with spawning, etc)
    public static EntityTypes CUSTOM_ZOMBIE;

    public void onLoad() {
        // register the custom entity in the server
        // it is recommended to do this when the server is loading
        // but since we're not replacing vanilla entities it can be
        // done later if wanted
        CUSTOM_ZOMBIE = injectNewEntity("custom_zombie", "zombie", CustomZombie.class, CustomZombie::new);

    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
        if (!(sender instanceof Player)) {
            sender.sendMessage("This is a player only command!");
            return true;

        // spawn CustomZombie where player is standing
        Entity spawnedEntity = spawnEntity(CUSTOM_ZOMBIE, ((Player) sender).getLocation());

        if (spawnedEntity == null) {
            sender.sendMessage("Could not spawn entity!");
        } else {
            sender.sendMessage("Custom zombie spawned!");
        return true;

     * Spawns entity at specified Location
     * @param entityTypes Type of entity to spawn
     * @param loc Location to spawn at
     * @return Reference to the spawned bukkit Entity
    public Entity spawnEntity(EntityTypes entityTypes, Location loc) {
        net.minecraft.server.v1_13_R2.Entity nmsEntity = entityTypes.a( // NMS method to spawn an entity from an EntityTypes
                ((CraftWorld) loc.getWorld()).getHandle(), // reference to the NMS world
                null, // EntityTag NBT compound
                null, // custom name of entity
                null, // player reference. used to know if player is OP to apply EntityTag NBT compound
                new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()), // the BlockPosition to spawn at
                true, // center entity on BlockPosition and correct Y position for Entity's height
                false); // not sure. alters the Y position. this is only ever true when using spawn egg and clicked face is UP

        // feel free to further modify your entity here if wanted
        // it's already been added to the world at this point

        return nmsEntity == null ? null : nmsEntity.getBukkitEntity(); // convert to a Bukkit entity

    private EntityTypes injectNewEntity(String name, String extend_from, Class<? extends net.minecraft.server.v1_13_R2.Entity> clazz, Function<? super World, ? extends net.minecraft.server.v1_13_R2.Entity> function) {
        // get the server's datatypes (also referred to as "data fixers")
        Map<Object, Type<?>> dataTypes = (Map<Object, Type<?>>) DataConverterRegistry.a().getSchema(DataFixUtils.makeKey(SharedConstants.a().getWorldVersion())).findChoiceType(DataConverterTypes.n).types();
        // inject the new custom entity (this registers the
        // name/id with the server so you can use it in things
        // like the vanilla /summon command)
        dataTypes.put("minecraft:" + name, dataTypes.get("minecraft:" + extend_from));
        // create and return an EntityTypes for the custom entity
        // store this somewhere so you can reference it later (like for spawning)
        return EntityTypes.a(name, EntityTypes.a.a(clazz, function));

     * The custom zombie
    public static class CustomZombie extends EntityZombie {
        public CustomZombie(World world) {

        // TODO add custom stuffs to make it custom


Thanks for this, Im super stoked to give it a whirl :slight_smile:


Thanks for this indeed! Trying to rewrite a 1.12 plugin that is heavily NMS for custom entities and this is a good start. Would a de-register be simply dataTypes.remove(“mineraft:”+name) ?


I’m honestly not sure about de-registering. The system wasnt designed for that at all, so idk how it would react. Worth a shot, though. Let us know :slight_smile:


Would you have any idea on how to make this mob persistent over a restart (Or even trigger a CreatureSpawnEvent)?


It should persist restarts if you are doing the injection in onLoad.


But it doesn’t persist the custom entity. At least not for me. It persists after a reload, but not after a restart.


I’ve tried to use your code here as a basis for doing it in 1.14 spigot. What i cobbled together mostly works except the entity always looks like a pig, but it’s sounds and behaviors are of the entity im extending from. Curious to know if you have had any luck figuring it out for 1.14.


use DataFixUtils.makeKey(SharedConstants.a().getWorldVersion()) in place of 15190.

I finally figured out where that number came from, and that’s the wrong number for 1.14 :slight_smile:

Updated original post to reflect this.


cool i’ll give that a shot thanks.