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

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
132
6
19
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.