Skip to content

Commit

Permalink
Fix tree generators working on the unbuffered underlying world. (#2705)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
wizjany authored Jan 27, 2025
1 parent 4b6b0d9 commit f002c03
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.concurrency.LazyReference;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.entity.EntityTypes;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.Registries;
Expand All @@ -37,6 +36,7 @@
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
Expand All @@ -50,6 +50,7 @@
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.function.Predicate;

public class PaperweightServerLevelDelegateProxy implements InvocationHandler {

Expand Down Expand Up @@ -86,7 +87,11 @@ private BlockEntity getBlockEntity(BlockPos blockPos) {
}

private BlockState getBlockState(BlockPos blockPos) {
return adapter.adapt(this.editSession.getBlock(BlockVector3.at(blockPos.getX(), blockPos.getY(), blockPos.getZ())));
return adapter.adapt(this.editSession.getBlockWithBuffer(BlockVector3.at(blockPos.getX(), blockPos.getY(), blockPos.getZ())));
}

private boolean isStateAtPosition(BlockPos blockPos, Predicate<BlockState> predicate) {
return predicate.test(getBlockState(blockPos));
}

private boolean setBlock(BlockPos blockPos, BlockState blockState) {
Expand All @@ -98,11 +103,7 @@ private boolean setBlock(BlockPos blockPos, BlockState blockState) {
}

private boolean removeBlock(BlockPos blockPos) {
try {
return editSession.setBlock(BlockVector3.at(blockPos.getX(), blockPos.getY(), blockPos.getZ()), BlockTypes.AIR.getDefaultState());
} catch (MaxChangedBlocksException e) {
throw new RuntimeException(e);
}
return setBlock(blockPos, Blocks.AIR.defaultBlockState());
}

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

addMethodHandleToTable(
builder,
StaticRefraction.IS_STATE_AT_POSITION,
lookup.unreflect(PaperweightServerLevelDelegateProxy.class.getDeclaredMethod("isStateAtPosition", BlockPos.class, Predicate.class))
);

MethodHandle addEntity = lookup.unreflect(PaperweightServerLevelDelegateProxy.class.getDeclaredMethod("addEntity", Entity.class));
addMethodHandleToTable(
builder,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public final class StaticRefraction {
);
public static final String NEXT_TICK_TIME = Refraction.pickName("nextTickTime", "e");
public static final String GET_BLOCK_STATE = Refraction.pickName("getBlockState", "a_");
public static final String IS_STATE_AT_POSITION = Refraction.pickName("isStateAtPosition", "a");
/**
* {@code addFreshEntityWithPassengers(Entity entity)}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;

public class PaperweightServerLevelDelegateProxy implements InvocationHandler, AutoCloseable {

Expand Down Expand Up @@ -99,7 +100,11 @@ private BlockEntity getBlockEntity(BlockPos blockPos) {
}

private BlockState getBlockState(BlockPos blockPos) {
return adapter.adapt(this.editSession.getBlock(adapt(blockPos)));
return adapter.adapt(this.editSession.getBlockWithBuffer(adapt(blockPos)));
}

private boolean isStateAtPosition(BlockPos blockPos, Predicate<BlockState> predicate) {
return predicate.test(getBlockState(blockPos));
}

private boolean setBlock(BlockPos blockPos, BlockState blockState) {
Expand Down Expand Up @@ -134,7 +139,7 @@ private void handleBlockEntity(BlockPos blockPos, BlockState blockState) {
createdBlockEntities.remove(pos);
}

private boolean removeBlock(BlockPos blockPos, boolean bl) {
private boolean removeBlock(BlockPos blockPos) {
return setBlock(blockPos, Blocks.AIR.defaultBlockState());
}

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

addMethodHandleToTable(
builder,
StaticRefraction.IS_STATE_AT_POSITION,
lookup.unreflect(PaperweightServerLevelDelegateProxy.class.getDeclaredMethod("isStateAtPosition", BlockPos.class, Predicate.class))
);

MethodHandle addEntity = lookup.unreflect(PaperweightServerLevelDelegateProxy.class.getDeclaredMethod("addEntity", Entity.class));
addMethodHandleToTable(
builder,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public final class StaticRefraction {
);
public static final String NEXT_TICK_TIME = Refraction.pickName("nextTickTime", "e");
public static final String GET_BLOCK_STATE = Refraction.pickName("getBlockState", "a_");
public static final String IS_STATE_AT_POSITION = Refraction.pickName("isStateAtPosition", "a");
/**
* {@code addFreshEntityWithPassengers(Entity entity)}.
*/
Expand Down
24 changes: 24 additions & 0 deletions worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,30 @@ public BaseBlock getFullBlock(BlockVector3 position) {
return world.getFullBlock(position);
}

/**
* As with {@link #getBlock(BlockVector3)}, gets the block at the given position.
* However, this may return blocks not yet set to the world (i.e., buffered) by
* the current EditSession.
*
* @param position position of the block
* @return the block
*/
public BlockState getBlockWithBuffer(BlockVector3 position) {
return this.bypassNone.getBlock(position);
}

/**
* As with {@link #getFullBlock(BlockVector3)}, gets the block at the given position,
* but as with {@link #getBlockWithBuffer(BlockVector3)}, this may return a block in
* the current EditSession's buffer rather than from the world.
*
* @param position position of the block
* @return the block
*/
public BaseBlock getFullBlockWithBuffer(BlockVector3 position) {
return this.bypassNone.getFullBlock(position);
}

/**
* Returns the highest solid 'terrain' block.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;

public class FabricServerLevelDelegateProxy implements InvocationHandler, AutoCloseable {

Expand Down Expand Up @@ -81,7 +82,7 @@ private BlockEntity getBlockEntity(BlockPos blockPos) {
}

private BlockState getBlockState(BlockPos blockPos) {
return FabricAdapter.adapt(this.editSession.getBlock(FabricAdapter.adapt(blockPos)));
return FabricAdapter.adapt(this.editSession.getBlockWithBuffer(FabricAdapter.adapt(blockPos)));
}

private boolean setBlock(BlockPos blockPos, BlockState blockState) {
Expand Down Expand Up @@ -147,6 +148,13 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
return getBlockState(blockPos);
}
}
case "isStateAtPosition", "method_16358" -> {
if (args.length == 2 && args[0] instanceof BlockPos blockPos && args[1] instanceof Predicate) {
@SuppressWarnings("unchecked")
Predicate<BlockState> predicate = (Predicate<BlockState>) args[1];
return predicate.test(getBlockState(blockPos));
}
}
case "getBlockEntity", "method_8321" -> {
if (args.length == 1 && args[0] instanceof BlockPos blockPos) {
return getBlockEntity(blockPos);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;

public class NeoForgeServerLevelDelegateProxy implements InvocationHandler, AutoCloseable {

Expand Down Expand Up @@ -82,7 +83,7 @@ private BlockEntity getBlockEntity(BlockPos blockPos) {
}

private BlockState getBlockState(BlockPos blockPos) {
return NeoForgeAdapter.adapt(this.editSession.getBlock(NeoForgeAdapter.adapt(blockPos)));
return NeoForgeAdapter.adapt(this.editSession.getBlockWithBuffer(NeoForgeAdapter.adapt(blockPos)));
}

private boolean setBlock(BlockPos blockPos, BlockState blockState) {
Expand Down Expand Up @@ -150,6 +151,13 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
return getBlockState(blockPos);
}
}
case "isStateAtPosition", "m_7433_" -> {
if (args.length == 2 && args[0] instanceof BlockPos blockPos && args[1] instanceof Predicate) {
@SuppressWarnings("unchecked")
Predicate<BlockState> predicate = (Predicate<BlockState>) args[1];
return predicate.test(getBlockState(blockPos));
}
}
case "getBlockEntity", "m_7702_" -> {
if (args.length == 1 && args[0] instanceof BlockPos blockPos) {
return getBlockEntity(blockPos);
Expand Down

0 comments on commit f002c03

Please sign in to comment.