Skip to content

Commit f002c03

Browse files
authored
Fix tree generators working on the unbuffered underlying world. (#2705)
Adds two methods to EditSession to allow getting blocks which are buffered by the EditSession, not yet set in the world. This allows the proxies used by tree generators to know the eventual state of the world, rather than the "real" state.
1 parent 4b6b0d9 commit f002c03

7 files changed

Lines changed: 71 additions & 11 deletions

File tree

worldedit-bukkit/adapters/adapter-1.21.3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_3/PaperweightServerLevelDelegateProxy.java

Lines changed: 14 additions & 7 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,7 @@
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;
4040
import net.minecraft.world.level.block.entity.BlockEntity;
4141
import net.minecraft.world.level.block.state.BlockState;
4242
import net.minecraft.world.phys.Vec3;
@@ -50,6 +50,7 @@
5050
import java.lang.reflect.InvocationHandler;
5151
import java.lang.reflect.Method;
5252
import java.lang.reflect.Proxy;
53+
import java.util.function.Predicate;
5354

5455
public class PaperweightServerLevelDelegateProxy implements InvocationHandler {
5556

@@ -86,7 +87,11 @@ private BlockEntity getBlockEntity(BlockPos blockPos) {
8687
}
8788

8889
private BlockState getBlockState(BlockPos blockPos) {
89-
return adapter.adapt(this.editSession.getBlock(BlockVector3.at(blockPos.getX(), blockPos.getY(), blockPos.getZ())));
90+
return adapter.adapt(this.editSession.getBlockWithBuffer(BlockVector3.at(blockPos.getX(), blockPos.getY(), blockPos.getZ())));
91+
}
92+
93+
private boolean isStateAtPosition(BlockPos blockPos, Predicate<BlockState> predicate) {
94+
return predicate.test(getBlockState(blockPos));
9095
}
9196

9297
private boolean setBlock(BlockPos blockPos, BlockState blockState) {
@@ -98,11 +103,7 @@ private boolean setBlock(BlockPos blockPos, BlockState blockState) {
98103
}
99104

100105
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);
105-
}
106+
return setBlock(blockPos, Blocks.AIR.defaultBlockState());
106107
}
107108

108109
private boolean addEntity(Entity entity) {
@@ -144,6 +145,12 @@ private static void addMethodHandleToTable(
144145
lookup.unreflect(PaperweightServerLevelDelegateProxy.class.getDeclaredMethod("getBlockState", BlockPos.class))
145146
);
146147

148+
addMethodHandleToTable(
149+
builder,
150+
StaticRefraction.IS_STATE_AT_POSITION,
151+
lookup.unreflect(PaperweightServerLevelDelegateProxy.class.getDeclaredMethod("isStateAtPosition", BlockPos.class, Predicate.class))
152+
);
153+
147154
MethodHandle addEntity = lookup.unreflect(PaperweightServerLevelDelegateProxy.class.getDeclaredMethod("addEntity", Entity.class));
148155
addMethodHandleToTable(
149156
builder,

worldedit-bukkit/adapters/adapter-1.21.3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_3/StaticRefraction.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public final class StaticRefraction {
3737
);
3838
public static final String NEXT_TICK_TIME = Refraction.pickName("nextTickTime", "e");
3939
public static final String GET_BLOCK_STATE = Refraction.pickName("getBlockState", "a_");
40+
public static final String IS_STATE_AT_POSITION = Refraction.pickName("isStateAtPosition", "a");
4041
/**
4142
* {@code addFreshEntityWithPassengers(Entity entity)}.
4243
*/

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import java.lang.reflect.Proxy;
5454
import java.util.HashMap;
5555
import java.util.Map;
56+
import java.util.function.Predicate;
5657

5758
public class PaperweightServerLevelDelegateProxy implements InvocationHandler, AutoCloseable {
5859

@@ -99,7 +100,11 @@ private BlockEntity getBlockEntity(BlockPos blockPos) {
99100
}
100101

101102
private BlockState getBlockState(BlockPos blockPos) {
102-
return adapter.adapt(this.editSession.getBlock(adapt(blockPos)));
103+
return adapter.adapt(this.editSession.getBlockWithBuffer(adapt(blockPos)));
104+
}
105+
106+
private boolean isStateAtPosition(BlockPos blockPos, Predicate<BlockState> predicate) {
107+
return predicate.test(getBlockState(blockPos));
103108
}
104109

105110
private boolean setBlock(BlockPos blockPos, BlockState blockState) {
@@ -134,7 +139,7 @@ private void handleBlockEntity(BlockPos blockPos, BlockState blockState) {
134139
createdBlockEntities.remove(pos);
135140
}
136141

137-
private boolean removeBlock(BlockPos blockPos, boolean bl) {
142+
private boolean removeBlock(BlockPos blockPos) {
138143
return setBlock(blockPos, Blocks.AIR.defaultBlockState());
139144
}
140145

@@ -191,6 +196,12 @@ private static void addMethodHandleToTable(
191196
lookup.unreflect(PaperweightServerLevelDelegateProxy.class.getDeclaredMethod("getBlockState", BlockPos.class))
192197
);
193198

199+
addMethodHandleToTable(
200+
builder,
201+
StaticRefraction.IS_STATE_AT_POSITION,
202+
lookup.unreflect(PaperweightServerLevelDelegateProxy.class.getDeclaredMethod("isStateAtPosition", BlockPos.class, Predicate.class))
203+
);
204+
194205
MethodHandle addEntity = lookup.unreflect(PaperweightServerLevelDelegateProxy.class.getDeclaredMethod("addEntity", Entity.class));
195206
addMethodHandleToTable(
196207
builder,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public final class StaticRefraction {
3737
);
3838
public static final String NEXT_TICK_TIME = Refraction.pickName("nextTickTime", "e");
3939
public static final String GET_BLOCK_STATE = Refraction.pickName("getBlockState", "a_");
40+
public static final String IS_STATE_AT_POSITION = Refraction.pickName("isStateAtPosition", "a");
4041
/**
4142
* {@code addFreshEntityWithPassengers(Entity entity)}.
4243
*/

worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,30 @@ public BaseBlock getFullBlock(BlockVector3 position) {
714714
return world.getFullBlock(position);
715715
}
716716

717+
/**
718+
* As with {@link #getBlock(BlockVector3)}, gets the block at the given position.
719+
* However, this may return blocks not yet set to the world (i.e., buffered) by
720+
* the current EditSession.
721+
*
722+
* @param position position of the block
723+
* @return the block
724+
*/
725+
public BlockState getBlockWithBuffer(BlockVector3 position) {
726+
return this.bypassNone.getBlock(position);
727+
}
728+
729+
/**
730+
* As with {@link #getFullBlock(BlockVector3)}, gets the block at the given position,
731+
* but as with {@link #getBlockWithBuffer(BlockVector3)}, this may return a block in
732+
* the current EditSession's buffer rather than from the world.
733+
*
734+
* @param position position of the block
735+
* @return the block
736+
*/
737+
public BaseBlock getFullBlockWithBuffer(BlockVector3 position) {
738+
return this.bypassNone.getFullBlock(position);
739+
}
740+
717741
/**
718742
* Returns the highest solid 'terrain' block.
719743
*

worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricServerLevelDelegateProxy.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import java.lang.reflect.Proxy;
4242
import java.util.HashMap;
4343
import java.util.Map;
44+
import java.util.function.Predicate;
4445

4546
public class FabricServerLevelDelegateProxy implements InvocationHandler, AutoCloseable {
4647

@@ -81,7 +82,7 @@ private BlockEntity getBlockEntity(BlockPos blockPos) {
8182
}
8283

8384
private BlockState getBlockState(BlockPos blockPos) {
84-
return FabricAdapter.adapt(this.editSession.getBlock(FabricAdapter.adapt(blockPos)));
85+
return FabricAdapter.adapt(this.editSession.getBlockWithBuffer(FabricAdapter.adapt(blockPos)));
8586
}
8687

8788
private boolean setBlock(BlockPos blockPos, BlockState blockState) {
@@ -147,6 +148,13 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
147148
return getBlockState(blockPos);
148149
}
149150
}
151+
case "isStateAtPosition", "method_16358" -> {
152+
if (args.length == 2 && args[0] instanceof BlockPos blockPos && args[1] instanceof Predicate) {
153+
@SuppressWarnings("unchecked")
154+
Predicate<BlockState> predicate = (Predicate<BlockState>) args[1];
155+
return predicate.test(getBlockState(blockPos));
156+
}
157+
}
150158
case "getBlockEntity", "method_8321" -> {
151159
if (args.length == 1 && args[0] instanceof BlockPos blockPos) {
152160
return getBlockEntity(blockPos);

worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeServerLevelDelegateProxy.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import java.lang.reflect.Proxy;
4343
import java.util.HashMap;
4444
import java.util.Map;
45+
import java.util.function.Predicate;
4546

4647
public class NeoForgeServerLevelDelegateProxy implements InvocationHandler, AutoCloseable {
4748

@@ -82,7 +83,7 @@ private BlockEntity getBlockEntity(BlockPos blockPos) {
8283
}
8384

8485
private BlockState getBlockState(BlockPos blockPos) {
85-
return NeoForgeAdapter.adapt(this.editSession.getBlock(NeoForgeAdapter.adapt(blockPos)));
86+
return NeoForgeAdapter.adapt(this.editSession.getBlockWithBuffer(NeoForgeAdapter.adapt(blockPos)));
8687
}
8788

8889
private boolean setBlock(BlockPos blockPos, BlockState blockState) {
@@ -150,6 +151,13 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
150151
return getBlockState(blockPos);
151152
}
152153
}
154+
case "isStateAtPosition", "m_7433_" -> {
155+
if (args.length == 2 && args[0] instanceof BlockPos blockPos && args[1] instanceof Predicate) {
156+
@SuppressWarnings("unchecked")
157+
Predicate<BlockState> predicate = (Predicate<BlockState>) args[1];
158+
return predicate.test(getBlockState(blockPos));
159+
}
160+
}
153161
case "getBlockEntity", "m_7702_" -> {
154162
if (args.length == 1 && args[0] instanceof BlockPos blockPos) {
155163
return getBlockEntity(blockPos);

0 commit comments

Comments
 (0)