Solved Save an entity as a string and create a new one from it

  • After careful consideration and due to limited usage, we’ve made the decision to discontinue the PaperMC forums. Moving forward, we recommend using Hangar for plugin uploads, and for all other community discussions and support, please join us on Discord.

richie

New member
Jan 24, 2022
2
0
1
Hi,
I want to cache an entity as a string to be able to create a copy of it later.

I have already searched a bit with Google and now I have the following code.

to get the string(works)
Java:
net.minecraft.world.entity.Entity nmsEntity = ((CraftEntity) entity).getHandle();
        CompoundTag compound = new CompoundTag();
        nmsEntity.serializeEntity(compound);
        CompoundTag compoundCopy = compound.copy();

        forbiddenKeys.forEach(tag -> {
            compoundCopy.remove(tag);
        });

        this.entity = compound.toString();

to create an entity from the string
Java:
public @Nullable Entity spawnEntity(Location location) throws CommandSyntaxException {
        CompoundTag compound = TagParser.parseTag(entity);
        CompoundTag compoundCopy = compound.copy();
        Level worldServer = ((CraftWorld) location.getWorld()).getHandle();



        net.minecraft.world.entity.Entity nmsEntity = EntityType.create(compoundCopy, worldServer).get();
        nmsEntity.setPos(location.getX(), location.getY(), location.getZ());

        return nmsEntity != null ? nmsEntity.getBukkitEntity() : null;
    }

Unfortunately, creating the entity does not work. No entity is created and there is no error message.

Is there a more elegant solution for this or a paper Function I don't know yet?

I would like to save everything(passengers(except players), items) when saving.

Thanks for your help
Richie

Sorry for my bad english
 

Machine Maker

Paper Developer
Staff member
Dec 17, 2021
151
6
24
18
California
There is API to serialize an entity to a byte[] which is then not human-readable. If you don't care about that, you can use that API in UnsafeValues. I don't recall exactly what it serializes, so if it includes passengers or not.
 

richie

New member
Jan 24, 2022
2
0
1
Thank you for the quick reply.

I found a working solution that works with the json string.

Java:
public String getJsonEntity(Entity entity) {
    net.minecraft.world.entity.Entity nmsEntity = ((CraftEntity) entity).getHandle();
    CompoundTag compound = new CompoundTag();
    nmsEntity.serializeEntity(compound);
    CompoundTag compoundCopy = compound.copy();
    forbiddenKeys.forEach(compoundCopy::remove);

    return compoundCopy.toString();
}

Java:
public @Nullable Entity spawnEntity(Location location) throws CommandSyntaxException {
    CompoundTag compound = TagParser.parseTag(entity);
    net.minecraft.world.entity.Entity entityNms = spawnEntity(location, compound);

    return entityNms == null ? null : entityNms.getBukkitEntity();
}

private static net.minecraft.world.entity.Entity spawnEntity(Location location, CompoundTag nbt) {
    CompoundTag compoundTag = nbt.copy();
    ServerLevel worldServer = ((CraftWorld) location.getWorld()).getHandle();

    net.minecraft.world.entity.Entity entity = EntityType.loadEntityRecursive(compoundTag, worldServer, (entity1) -> {
        entity1.moveTo(location.x(), location.y(), location.z(), location.getPitch(), location.getYaw());
        entity1.spawnReason = CreatureSpawnEvent.SpawnReason.DEFAULT;
        return entity1;
    });

    if (entity == null) {
        //error message
        return null;
    } else {
        if (!worldServer.tryAddFreshEntityWithPassengers(entity, CreatureSpawnEvent.SpawnReason.SPAWNER_EGG)) {
            //error message
            return null;
        } else {
            return entity;
        }
    }
}

This is my experiment code.
Could be better, but shows how it works.