Skip to content

Commit ea21e38

Browse files
committed
Merge branch 'version/7.3.x'
2 parents c220445 + 97630e6 commit ea21e38

8 files changed

Lines changed: 347 additions & 138 deletions

File tree

CHANGELOG.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
7.3.10
2+
- Added support for 1.21.4
3+
- Improved a few translation lines relating to URLs and newlines
4+
- Fixed issues relating to block entities in generated features and structures
5+
16
7.3.9
27
- Added support for 1.21.3
38
- Fixed tools not behaving correctly when mods embed worlds in worlds

worldedit-bukkit/adapters/adapter-1.21.4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_4/PaperweightAdapter.java

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.mojang.serialization.Codec;
3030
import com.mojang.serialization.Lifecycle;
3131
import com.sk89q.worldedit.EditSession;
32+
import com.sk89q.worldedit.MaxChangedBlocksException;
3233
import com.sk89q.worldedit.WorldEditException;
3334
import com.sk89q.worldedit.blocks.BaseItem;
3435
import com.sk89q.worldedit.blocks.BaseItemStack;
@@ -117,7 +118,6 @@
117118
import net.minecraft.world.item.context.UseOnContext;
118119
import net.minecraft.world.level.ChunkPos;
119120
import net.minecraft.world.level.LevelSettings;
120-
import net.minecraft.world.level.WorldGenLevel;
121121
import net.minecraft.world.level.biome.Biome;
122122
import net.minecraft.world.level.block.Block;
123123
import net.minecraft.world.level.block.Blocks;
@@ -939,33 +939,55 @@ public void initializeRegistries() {
939939

940940
public boolean generateFeature(ConfiguredFeatureType type, World world, EditSession session, BlockVector3 pt) {
941941
ServerLevel originalWorld = ((CraftWorld) world).getHandle();
942-
ConfiguredFeature<?, ?> k = originalWorld.registryAccess().lookupOrThrow(Registries.CONFIGURED_FEATURE).getValue(ResourceLocation.tryParse(type.id()));
942+
ConfiguredFeature<?, ?> feature = originalWorld.registryAccess().lookupOrThrow(Registries.CONFIGURED_FEATURE).getValue(ResourceLocation.tryParse(type.id()));
943943
ServerChunkCache chunkManager = originalWorld.getChunkSource();
944-
WorldGenLevel proxyLevel = PaperweightServerLevelDelegateProxy.newInstance(session, originalWorld, this);
945-
return k != null && k.place(proxyLevel, chunkManager.getGenerator(), random, new BlockPos(pt.x(), pt.y(), pt.z()));
944+
try (PaperweightServerLevelDelegateProxy.LevelAndProxy proxyLevel =
945+
PaperweightServerLevelDelegateProxy.newInstance(session, originalWorld, this)) {
946+
return feature != null && feature.place(proxyLevel.level(), chunkManager.getGenerator(), random, new BlockPos(pt.x(), pt.y(), pt.z()));
947+
} catch (MaxChangedBlocksException e) {
948+
throw new RuntimeException(e);
949+
}
946950
}
947951

948952
public boolean generateStructure(StructureType type, World world, EditSession session, BlockVector3 pt) {
949953
ServerLevel originalWorld = ((CraftWorld) world).getHandle();
950954
Registry<Structure> structureRegistry = originalWorld.registryAccess().lookupOrThrow(Registries.STRUCTURE);
951-
Structure k = structureRegistry.getValue(ResourceLocation.tryParse(type.id()));
952-
if (k == null) {
955+
Structure structure = structureRegistry.getValue(ResourceLocation.tryParse(type.id()));
956+
if (structure == null) {
953957
return false;
954958
}
955959

956960
ServerChunkCache chunkManager = originalWorld.getChunkSource();
957-
WorldGenLevel proxyLevel = PaperweightServerLevelDelegateProxy.newInstance(session, originalWorld, this);
958-
ChunkPos chunkPos = new ChunkPos(new BlockPos(pt.x(), pt.y(), pt.z()));
959-
StructureStart structureStart = k.generate(structureRegistry.wrapAsHolder(k), originalWorld.dimension(), originalWorld.registryAccess(), chunkManager.getGenerator(), chunkManager.getGenerator().getBiomeSource(), chunkManager.randomState(), originalWorld.getStructureManager(), originalWorld.getSeed(), chunkPos, 0, proxyLevel, biome -> true);
961+
try (PaperweightServerLevelDelegateProxy.LevelAndProxy proxyLevel =
962+
PaperweightServerLevelDelegateProxy.newInstance(session, originalWorld, this)) {
963+
ChunkPos chunkPos = new ChunkPos(new BlockPos(pt.x(), pt.y(), pt.z()));
964+
StructureStart structureStart = structure.generate(
965+
structureRegistry.wrapAsHolder(structure), originalWorld.dimension(), originalWorld.registryAccess(),
966+
chunkManager.getGenerator(), chunkManager.getGenerator().getBiomeSource(), chunkManager.randomState(),
967+
originalWorld.getStructureManager(), originalWorld.getSeed(), chunkPos, 0,
968+
proxyLevel.level(), biome -> true
969+
);
960970

961-
if (!structureStart.isValid()) {
962-
return false;
963-
} else {
964-
BoundingBox boundingBox = structureStart.getBoundingBox();
965-
ChunkPos min = new ChunkPos(SectionPos.blockToSectionCoord(boundingBox.minX()), SectionPos.blockToSectionCoord(boundingBox.minZ()));
966-
ChunkPos max = new ChunkPos(SectionPos.blockToSectionCoord(boundingBox.maxX()), SectionPos.blockToSectionCoord(boundingBox.maxZ()));
967-
ChunkPos.rangeClosed(min, max).forEach((chunkPosx) -> structureStart.placeInChunk(proxyLevel, originalWorld.structureManager(), chunkManager.getGenerator(), originalWorld.getRandom(), new BoundingBox(chunkPosx.getMinBlockX(), originalWorld.getMinY(), chunkPosx.getMinBlockZ(), chunkPosx.getMaxBlockX(), originalWorld.getMaxY(), chunkPosx.getMaxBlockZ()), chunkPosx));
968-
return true;
971+
if (!structureStart.isValid()) {
972+
return false;
973+
} else {
974+
BoundingBox boundingBox = structureStart.getBoundingBox();
975+
ChunkPos min = new ChunkPos(SectionPos.blockToSectionCoord(boundingBox.minX()), SectionPos.blockToSectionCoord(boundingBox.minZ()));
976+
ChunkPos max = new ChunkPos(SectionPos.blockToSectionCoord(boundingBox.maxX()), SectionPos.blockToSectionCoord(boundingBox.maxZ()));
977+
ChunkPos.rangeClosed(min, max).forEach((chunkPosx) ->
978+
structureStart.placeInChunk(
979+
proxyLevel.level(), originalWorld.structureManager(), chunkManager.getGenerator(),
980+
originalWorld.getRandom(),
981+
new BoundingBox(
982+
chunkPosx.getMinBlockX(), originalWorld.getMinY(), chunkPosx.getMinBlockZ(),
983+
chunkPosx.getMaxBlockX(), originalWorld.getMaxY(), chunkPosx.getMaxBlockZ()
984+
), chunkPosx
985+
)
986+
);
987+
return true;
988+
}
989+
} catch (MaxChangedBlocksException e) {
990+
throw new RuntimeException(e);
969991
}
970992
}
971993

worldedit-bukkit/adapters/adapter-1.21.4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_4/PaperweightServerLevelDelegateProxy.java

Lines changed: 71 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import com.sk89q.worldedit.math.BlockVector3;
2929
import com.sk89q.worldedit.util.Location;
3030
import com.sk89q.worldedit.util.concurrency.LazyReference;
31-
import com.sk89q.worldedit.world.block.BlockTypes;
3231
import com.sk89q.worldedit.world.entity.EntityTypes;
3332
import net.minecraft.core.BlockPos;
3433
import net.minecraft.core.registries.Registries;
@@ -37,6 +36,8 @@
3736
import net.minecraft.server.level.ServerLevel;
3837
import net.minecraft.world.entity.Entity;
3938
import net.minecraft.world.level.WorldGenLevel;
39+
import net.minecraft.world.level.block.Blocks;
40+
import net.minecraft.world.level.block.EntityBlock;
4041
import net.minecraft.world.level.block.entity.BlockEntity;
4142
import net.minecraft.world.level.block.state.BlockState;
4243
import net.minecraft.world.phys.Vec3;
@@ -50,59 +51,91 @@
5051
import java.lang.reflect.InvocationHandler;
5152
import java.lang.reflect.Method;
5253
import java.lang.reflect.Proxy;
54+
import java.util.HashMap;
55+
import java.util.Map;
5356

54-
public class PaperweightServerLevelDelegateProxy implements InvocationHandler {
57+
public class PaperweightServerLevelDelegateProxy implements InvocationHandler, AutoCloseable {
58+
59+
private static BlockVector3 adapt(BlockPos blockPos) {
60+
return BlockVector3.at(blockPos.getX(), blockPos.getY(), blockPos.getZ());
61+
}
5562

5663
private final EditSession editSession;
5764
private final ServerLevel serverLevel;
5865
private final PaperweightAdapter adapter;
66+
private final Map<BlockVector3, BlockEntity> createdBlockEntities = new HashMap<>();
5967

6068
private PaperweightServerLevelDelegateProxy(EditSession editSession, ServerLevel serverLevel, PaperweightAdapter adapter) {
6169
this.editSession = editSession;
6270
this.serverLevel = serverLevel;
6371
this.adapter = adapter;
6472
}
6573

66-
public static WorldGenLevel newInstance(EditSession editSession, ServerLevel serverLevel, PaperweightAdapter adapter) {
67-
return (WorldGenLevel) Proxy.newProxyInstance(
68-
serverLevel.getClass().getClassLoader(),
69-
serverLevel.getClass().getInterfaces(),
70-
new PaperweightServerLevelDelegateProxy(editSession, serverLevel, adapter)
74+
public record LevelAndProxy(WorldGenLevel level, PaperweightServerLevelDelegateProxy proxy) implements AutoCloseable {
75+
@Override
76+
public void close() throws MaxChangedBlocksException {
77+
proxy.close();
78+
}
79+
}
80+
81+
public static LevelAndProxy newInstance(EditSession editSession, ServerLevel serverLevel, PaperweightAdapter adapter) {
82+
PaperweightServerLevelDelegateProxy proxy = new PaperweightServerLevelDelegateProxy(editSession, serverLevel, adapter);
83+
return new LevelAndProxy(
84+
(WorldGenLevel) Proxy.newProxyInstance(
85+
serverLevel.getClass().getClassLoader(),
86+
serverLevel.getClass().getInterfaces(),
87+
proxy
88+
),
89+
proxy
7190
);
7291
}
7392

7493
@Nullable
7594
private BlockEntity getBlockEntity(BlockPos blockPos) {
76-
BlockEntity tileEntity = this.serverLevel.getChunkAt(blockPos).getBlockEntity(blockPos);
77-
if (tileEntity == null) {
78-
return null;
79-
}
80-
tileEntity.loadWithComponents(
81-
(CompoundTag) adapter.fromNative(this.editSession.getFullBlock(BlockVector3.at(blockPos.getX(), blockPos.getY(), blockPos.getZ())).getNbtReference().getValue()),
82-
this.serverLevel.registryAccess()
83-
);
84-
85-
return tileEntity;
95+
// This doesn't synthesize or load from world. I think editing existing block entities without setting the block
96+
// (in the context of features) should not be supported in the first place.
97+
BlockVector3 pos = adapt(blockPos);
98+
return createdBlockEntities.get(pos);
8699
}
87100

88101
private BlockState getBlockState(BlockPos blockPos) {
89-
return adapter.adapt(this.editSession.getBlock(BlockVector3.at(blockPos.getX(), blockPos.getY(), blockPos.getZ())));
102+
return adapter.adapt(this.editSession.getBlock(adapt(blockPos)));
90103
}
91104

92105
private boolean setBlock(BlockPos blockPos, BlockState blockState) {
93106
try {
94-
return editSession.setBlock(BlockVector3.at(blockPos.getX(), blockPos.getY(), blockPos.getZ()), adapter.adapt(blockState));
107+
handleBlockEntity(blockPos, blockState);
108+
return editSession.setBlock(adapt(blockPos), adapter.adapt(blockState));
95109
} catch (MaxChangedBlocksException e) {
96110
throw new RuntimeException(e);
97111
}
98112
}
99113

100-
private boolean removeBlock(BlockPos blockPos) {
101-
try {
102-
return editSession.setBlock(BlockVector3.at(blockPos.getX(), blockPos.getY(), blockPos.getZ()), BlockTypes.AIR.getDefaultState());
103-
} catch (MaxChangedBlocksException e) {
104-
throw new RuntimeException(e);
114+
// For BlockEntity#setBlockState, not sure why it's deprecated
115+
@SuppressWarnings("deprecation")
116+
private void handleBlockEntity(BlockPos blockPos, BlockState blockState) {
117+
BlockVector3 pos = adapt(blockPos);
118+
if (blockState.hasBlockEntity()) {
119+
if (!(blockState.getBlock() instanceof EntityBlock entityBlock)) {
120+
// This will probably never happen, as Mojang's own code assumes that
121+
// hasBlockEntity implies instanceof EntityBlock, but just to be safe...
122+
throw new AssertionError("BlockState has block entity but block is not an EntityBlock: " + blockState);
123+
}
124+
BlockEntity newEntity = entityBlock.newBlockEntity(blockPos, blockState);
125+
if (newEntity != null) {
126+
newEntity.setBlockState(blockState);
127+
createdBlockEntities.put(pos, newEntity);
128+
// Should we load existing NBT here? This is for feature / structure gen so it seems unnecessary.
129+
// But it would align with the behavior of the real setBlock method.
130+
return;
131+
}
105132
}
133+
// Discard any block entity that was previously created if new block is set without block entity
134+
createdBlockEntities.remove(pos);
135+
}
136+
137+
private boolean removeBlock(BlockPos blockPos, boolean bl) {
138+
return setBlock(blockPos, Blocks.AIR.defaultBlockState());
106139
}
107140

108141
private boolean addEntity(Entity entity) {
@@ -117,6 +150,20 @@ private boolean addEntity(Entity entity) {
117150
return editSession.createEntity(location, baseEntity) != null;
118151
}
119152

153+
@Override
154+
public void close() throws MaxChangedBlocksException {
155+
for (Map.Entry<BlockVector3, BlockEntity> entry : createdBlockEntities.entrySet()) {
156+
BlockVector3 blockPos = entry.getKey();
157+
BlockEntity blockEntity = entry.getValue();
158+
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId(serverLevel.registryAccess());
159+
editSession.setBlock(
160+
blockPos,
161+
adapter.adapt(blockEntity.getBlockState())
162+
.toBaseBlock(LazyReference.from(() -> (LinCompoundTag) adapter.toNative(tag)))
163+
);
164+
}
165+
}
166+
120167
private static void addMethodHandleToTable(
121168
ImmutableTable.Builder<String, MethodType, MethodHandle> table,
122169
String methodName,

worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import com.sk89q.worldedit.world.item.ItemTypes;
4242
import net.minecraft.commands.CommandSourceStack;
4343
import net.minecraft.core.BlockPos;
44+
import net.minecraft.core.RegistryAccess;
4445
import net.minecraft.core.component.DataComponentPatch;
4546
import net.minecraft.core.registries.Registries;
4647
import net.minecraft.nbt.CompoundTag;
@@ -195,13 +196,18 @@ public static BaseBlock adapt(BlockEntity blockEntity) {
195196
if (!blockEntity.hasLevel()) {
196197
throw new IllegalArgumentException("BlockEntity must have a level");
197198
}
199+
RegistryAccess registries = blockEntity.getLevel().registryAccess();
200+
return adapt(blockEntity, registries);
201+
}
202+
203+
public static BaseBlock adapt(BlockEntity blockEntity, RegistryAccess registries) {
198204
int blockStateId = Block.getId(blockEntity.getBlockState());
199205
BlockState worldEdit = BlockStateIdAccess.getBlockStateById(blockStateId);
200206
if (worldEdit == null) {
201207
worldEdit = FabricTransmogrifier.transmogToWorldEdit(blockEntity.getBlockState());
202208
}
203209
// Save this outside the reference to ensure it doesn't mutate
204-
CompoundTag savedNative = blockEntity.saveWithId(blockEntity.getLevel().registryAccess());
210+
CompoundTag savedNative = blockEntity.saveWithId(registries);
205211
return worldEdit.toBaseBlock(LazyReference.from(() -> NBTConverter.fromNative(savedNative)));
206212
}
207213

0 commit comments

Comments
 (0)