fix: set villager offers temporarily to save NBT without sending event (#2357)

This commit is contained in:
Jordan
2023-10-02 20:36:21 +01:00
committed by GitHub
parent 66c2dc3eda
commit dccf82ab1b
20 changed files with 177 additions and 42 deletions

View File

@ -38,6 +38,7 @@ import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.PaperweightFaweAdapter;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.PaperweightPlatformAdapter;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extension.platform.Watchdog;
import com.sk89q.worldedit.extent.Extent;
@ -288,7 +289,9 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
* @param tag the tag
*/
private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag tag) {
entity.save(tag);
//FAWE start - avoid villager async catcher
PaperweightPlatformAdapter.readEntityIntoTag(entity, tag);
//FAWE end
}
private static Block getBlockFromType(BlockType blockType) {

View File

@ -135,10 +135,6 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
return resourceLocation == null ? null : resourceLocation.toString();
}
private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) {
entity.save(compoundTag);
}
@Override
public BukkitImplAdapter<net.minecraft.nbt.Tag> getParent() {
return parent;
@ -367,7 +363,7 @@ public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundBinaryTag> saveTag = () -> {
final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag();
readEntityIntoTag(mcEntity, minecraftTag);
PaperweightPlatformAdapter.readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work
final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag);
final Map<String, BinaryTag> tags = NbtUtils.getCompoundBinaryTagValues(tag);

View File

@ -374,7 +374,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
public Iterator<CompoundTag> iterator() {
Iterable<CompoundTag> result = entities.stream().map(input -> {
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
input.save(tag);
PaperweightPlatformAdapter.readEntityIntoTag(input, tag);
return (CompoundTag) adapter.toNative(tag);
}).collect(Collectors.toList());
return result.iterator();
@ -394,7 +394,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
@SuppressWarnings("rawtypes")
public synchronized <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) {
forceLoadSections = false;
copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null;
copy = createCopy ? new PaperweightGetBlocks_Copy(getChunk()) : null;
try {
ServerLevel nmsWorld = serverLevel;
LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ);

View File

@ -74,7 +74,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
protected void storeEntity(Entity entity) {
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag();
entity.save(compoundTag);
PaperweightPlatformAdapter.readEntityIntoTag(entity, compoundTag);
entities.add((CompoundTag) adapter.toNative(compoundTag));
}

View File

@ -34,6 +34,8 @@ import net.minecraft.server.level.TicketType;
import net.minecraft.util.BitStorage;
import net.minecraft.util.Unit;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.npc.AbstractVillager;
import net.minecraft.world.item.trading.MerchantOffers;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.biome.Biome;
@ -90,6 +92,9 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
private static final Field fieldGameEventDispatcherSections;
private static final MethodHandle methodremoveBlockEntityTicker;
private static final Field fieldOffers;
private static final MerchantOffers OFFERS = new MerchantOffers();
private static final Field fieldRemove;
private static final Logger LOGGER = LogManagerCompat.getLogger();
@ -145,6 +150,9 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
fieldRemove.setAccessible(true);
fieldOffers = AbstractVillager.class.getDeclaredField(Refraction.pickName("offers", "bU"));
fieldOffers.setAccessible(true);
} catch (RuntimeException e) {
throw e;
} catch (Throwable rethrow) {
@ -492,4 +500,27 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
return chunk.level.entityManager.getEntities(chunk.getPos());
}
public static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) {
boolean isVillager = entity instanceof AbstractVillager && !Fawe.isMainThread();
boolean unset = false;
if (isVillager) {
try {
if (fieldOffers.get(entity) != null) {
fieldOffers.set(entity, OFFERS);
unset = true;
}
} catch (IllegalAccessException e) {
throw new RuntimeException("Failed to set offers field to villager to avoid async catcher.", e);
}
}
entity.save(compoundTag);
if (unset) {
try {
fieldOffers.set(entity, null);
} catch (IllegalAccessException e) {
throw new RuntimeException("Failed to set offers field to null again on villager.", e);
}
}
}
}