WorldEdit

WorldEdit

45M Downloads

//copy and //stack do not copy entities riding status

PhoenixIV opened this issue · 4 comments

commented

WorldEdit Version

7.2.5

Platform Version

Fabric 0.11.3

Bug Description

Trying to copy a region with entities riding minecarts. Both, minecart and mob get duplicated, but the mob is not riding the minecart anymore.

Expected Behavior

When copying a mob riding a minecart the mob should also ride it in the copy.

Reproduction Steps

  1. Copy / Stack a region with -e argument

Anything Else?

I noticed when duplicating layers for testing a cat-based creeper farm. The riding status is considered important here, because if not in minecart the cat will teleport if the player hurts.

commented

In the hopes of further speeding up a fix, I have constructed a proof of concept, based on my duplicate issue analysis, which I have also tested. Below is a replacement for com.sk89q.worldedit.bukkit.adapter.impl.v1_18_R2.PaperweightAdapter#getEntity and com.sk89q.worldedit.bukkit.adapter.impl.v1_18_R2.PaperweightAdapter#createEntity alongside an additional utility method. The changes was made on the version/7.2.x branch. When using the below code, passengers are correctly spawned in and retain all the metadata correctly. I assume the same changes can be used for the 1.18.1 and 1.17.1, as the code being changed is identical, but I have not tested those two versions.

All that needs doing now, is someone with better knowledge of WorldEdit to review this and consider if it has any possible implications elsewhere in the code, that I have not forseen...

@Override
public BaseEntity getEntity(org.bukkit.entity.Entity entity) {
    checkNotNull(entity);

    CraftEntity craftEntity = ((CraftEntity) entity);
    Entity mcEntity = craftEntity.getHandle();

    // Do not allow creating of passenger entity snapshots, passengers are included in the vehicle entity
    if (mcEntity.isPassenger()) {
        return null;
    }

    String id = getEntityId(mcEntity);

    net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
    readEntityIntoTag(mcEntity, tag);
    return new BaseEntity(com.sk89q.worldedit.world.entity.EntityTypes.get(id), (CompoundTag) toNative(tag));
}

@Nullable
@Override
public org.bukkit.entity.Entity createEntity(Location location, BaseEntity state) {
    checkNotNull(location);
    checkNotNull(state);

    CraftWorld craftWorld = ((CraftWorld) location.getWorld());
    ServerLevel worldServer = craftWorld.getHandle();

    String entityId = state.getType().getId();

    CompoundTag nativeTag = state.getNbtData();
    net.minecraft.nbt.CompoundTag tag;
    if (nativeTag != null) {
        tag = (net.minecraft.nbt.CompoundTag) fromNative(nativeTag);
        removeUnwantedEntityTagsRecursively(tag);
    } else {
        tag = new net.minecraft.nbt.CompoundTag();
    }

    tag.putString("id", entityId);

    Entity createdEntity = EntityType.loadEntityRecursive(tag, craftWorld.getHandle(), (loadedEntity) -> {
        loadedEntity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
        return loadedEntity;
    });

    if (createdEntity != null) {
        worldServer.addFreshEntityWithPassengers(createdEntity, SpawnReason.CUSTOM);
        return createdEntity.getBukkitEntity();
    } else {
        return null;
    }
}

// This removes all unwanted tags from the main entity and all its passengers
private void removeUnwantedEntityTagsRecursively(net.minecraft.nbt.CompoundTag tag) {
    for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
        tag.remove(name);
    }

    // Adapted from net.minecraft.world.entity.EntityType#loadEntityRecursive
    if (tag.contains("Passengers", 9)) {
        net.minecraft.nbt.ListTag nbttaglist = tag.getList("Passengers", 10);

        for (int i = 0; i < nbttaglist.size(); ++i) {
            removeUnwantedEntityTagsRecursively(nbttaglist.getCompound(i));
        }
    }
}
commented

potentially useful info in duplicate issue (#2052) for anyone who wants to look into this/PR a fix

commented

@RedEpicness From what @wizjany said I guess you are free to create a pull request, which will be reviewed anyway. But this is already more than enough, thanks for your efforts!

commented

And buckit plugin