BlockPlacementRule cleanup

This commit is contained in:
themode 2020-12-20 03:24:29 +01:00
parent 81592d8b56
commit ffbde089f8
7 changed files with 69 additions and 68 deletions

View File

@ -4,6 +4,7 @@ import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Player; import net.minestom.server.entity.Player;
import net.minestom.server.event.CancellableEvent; import net.minestom.server.event.CancellableEvent;
import net.minestom.server.event.PlayerEvent; import net.minestom.server.event.PlayerEvent;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockManager; import net.minestom.server.instance.block.BlockManager;
import net.minestom.server.instance.block.CustomBlock; import net.minestom.server.instance.block.CustomBlock;
import net.minestom.server.utils.BlockPosition; import net.minestom.server.utils.BlockPosition;
@ -25,11 +26,10 @@ public class PlayerBlockPlaceEvent extends PlayerEvent implements CancellableEve
private boolean cancelled; private boolean cancelled;
public PlayerBlockPlaceEvent(@NotNull Player player, short blockStateId, short customBlockId, public PlayerBlockPlaceEvent(@NotNull Player player, @NotNull Block block,
@NotNull BlockPosition blockPosition, @NotNull Player.Hand hand) { @NotNull BlockPosition blockPosition, @NotNull Player.Hand hand) {
super(player); super(player);
this.blockStateId = blockStateId; this.blockStateId = block.getBlockId();
this.customBlockId = customBlockId;
this.blockPosition = blockPosition; this.blockPosition = blockPosition;
this.hand = hand; this.hand = hand;
this.consumeBlock = true; this.consumeBlock = true;

View File

@ -300,7 +300,7 @@ public class InstanceContainer extends Instance {
private short executeBlockPlacementRule(short blockStateId, @NotNull BlockPosition blockPosition) { private short executeBlockPlacementRule(short blockStateId, @NotNull BlockPosition blockPosition) {
final BlockPlacementRule blockPlacementRule = BLOCK_MANAGER.getBlockPlacementRule(blockStateId); final BlockPlacementRule blockPlacementRule = BLOCK_MANAGER.getBlockPlacementRule(blockStateId);
if (blockPlacementRule != null) { if (blockPlacementRule != null) {
return blockPlacementRule.blockRefresh(this, blockPosition, blockStateId); return blockPlacementRule.blockUpdate(this, blockPosition, blockStateId);
} }
return blockStateId; return blockStateId;
} }
@ -331,7 +331,7 @@ public class InstanceContainer extends Instance {
final BlockPlacementRule neighborBlockPlacementRule = BLOCK_MANAGER.getBlockPlacementRule(neighborStateId); final BlockPlacementRule neighborBlockPlacementRule = BLOCK_MANAGER.getBlockPlacementRule(neighborStateId);
if (neighborBlockPlacementRule != null) { if (neighborBlockPlacementRule != null) {
final BlockPosition neighborPosition = new BlockPosition(neighborX, neighborY, neighborZ); final BlockPosition neighborPosition = new BlockPosition(neighborX, neighborY, neighborZ);
final short newNeighborId = neighborBlockPlacementRule.blockRefresh(this, final short newNeighborId = neighborBlockPlacementRule.blockUpdate(this,
neighborPosition, neighborStateId); neighborPosition, neighborStateId);
if (neighborStateId != newNeighborId) { if (neighborStateId != newNeighborId) {
refreshBlockStateId(neighborPosition, newNeighborId); refreshBlockStateId(neighborPosition, newNeighborId);

View File

@ -9,6 +9,8 @@ import org.jetbrains.annotations.NotNull;
public abstract class BlockPlacementRule { public abstract class BlockPlacementRule {
public static final int CANCEL_CODE = -1;
private final short blockId; private final short blockId;
public BlockPlacementRule(short blockId) { public BlockPlacementRule(short blockId) {
@ -19,16 +21,6 @@ public abstract class BlockPlacementRule {
this(block.getBlockId()); this(block.getBlockId());
} }
/**
* Gets if the block can be placed in {@code blockPosition}.
* Can for example, be used for blocks which have to be placed on a solid block.
*
* @param instance the instance of the block
* @param blockPosition the position where the block is trying to get place
* @return true if the block placement position is valid
*/
public abstract boolean canPlace(@NotNull Instance instance, @NotNull BlockPosition blockPosition);
/** /**
* Called when the block state id can be updated (for instance if a neighbour block changed). * Called when the block state id can be updated (for instance if a neighbour block changed).
* *
@ -37,7 +29,7 @@ public abstract class BlockPlacementRule {
* @param currentStateID the current block state id of the block * @param currentStateID the current block state id of the block
* @return the updated block state id * @return the updated block state id
*/ */
public abstract short blockRefresh(@NotNull Instance instance, @NotNull BlockPosition blockPosition, short currentStateID); public abstract short blockUpdate(@NotNull Instance instance, @NotNull BlockPosition blockPosition, short currentStateID);
/** /**
* Called when the block is placed. * Called when the block is placed.
@ -45,11 +37,13 @@ public abstract class BlockPlacementRule {
* @param instance the instance of the block * @param instance the instance of the block
* @param block the block placed * @param block the block placed
* @param blockFace the block face * @param blockFace the block face
* @param blockPosition the block position
* @param pl the player who placed the block * @param pl the player who placed the block
* @return the block state id of the placed block * @return the block state id of the placed block,
* {@link #CANCEL_CODE} to prevent the placement
*/ */
public abstract short blockPlace(@NotNull Instance instance, public abstract short blockPlace(@NotNull Instance instance,
@NotNull Block block, @NotNull BlockFace blockFace, @NotNull Block block, @NotNull BlockFace blockFace, @NotNull BlockPosition blockPosition,
@NotNull Player pl); @NotNull Player pl);
public short getBlockId() { public short getBlockId() {

View File

@ -18,17 +18,14 @@ public class AxisPlacementRule extends BlockPlacementRule {
} }
@Override @Override
public boolean canPlace(@NotNull Instance instance, @NotNull BlockPosition blockPosition) { public short blockUpdate(@NotNull Instance instance, @NotNull BlockPosition blockPosition, short currentId) {
return true;
}
@Override
public short blockRefresh(@NotNull Instance instance, @NotNull BlockPosition blockPosition, short currentId) {
return currentId; return currentId;
} }
@Override @Override
public short blockPlace(@NotNull Instance instance, @NotNull Block block, @NotNull BlockFace blockFace, @NotNull Player pl) { public short blockPlace(@NotNull Instance instance,
@NotNull Block block, @NotNull BlockFace blockFace, @NotNull BlockPosition blockPosition,
@NotNull Player pl) {
String axis = "y"; String axis = "y";
if (blockFace == BlockFace.WEST || blockFace == BlockFace.EAST) { if (blockFace == BlockFace.WEST || blockFace == BlockFace.EAST) {
axis = "x"; axis = "x";

View File

@ -16,13 +16,7 @@ public class RedstonePlacementRule extends BlockPlacementRule {
} }
@Override @Override
public boolean canPlace(@NotNull Instance instance, @NotNull BlockPosition blockPosition) { public short blockUpdate(@NotNull Instance instance, @NotNull BlockPosition blockPosition, short currentId) {
BlockUtils block = new BlockUtils(instance, blockPosition);
return block.below().getBlock().isSolid();
}
@Override
public short blockRefresh(@NotNull Instance instance, @NotNull BlockPosition blockPosition, short currentId) {
BlockUtils block = new BlockUtils(instance, blockPosition); BlockUtils block = new BlockUtils(instance, blockPosition);
String east = "none"; String east = "none";
@ -104,7 +98,14 @@ public class RedstonePlacementRule extends BlockPlacementRule {
} }
@Override @Override
public short blockPlace(@NotNull Instance instance, @NotNull Block block, @NotNull BlockFace blockFace, @NotNull Player pl) { public short blockPlace(@NotNull Instance instance,
@NotNull Block block, @NotNull BlockFace blockFace, @NotNull BlockPosition blockPosition,
@NotNull Player pl) {
final short belowBlockId = instance.getBlockStateId(blockPosition.getX(), blockPosition.getY() - 1, blockPosition.getZ());
if (!Block.fromStateId(belowBlockId).isSolid()) {
return CANCEL_CODE;
}
return getBlockId(); return getBlockId();
} }

View File

@ -18,15 +18,10 @@ public class WallPlacementRule extends BlockPlacementRule {
} }
@Override @Override
public boolean canPlace(@NotNull Instance instance, @NotNull BlockPosition blockPosition) { public short blockUpdate(@NotNull Instance instance, @NotNull BlockPosition blockPosition, short currentId) {
return true; final int x = blockPosition.getX();
} final int y = blockPosition.getY();
final int z = blockPosition.getZ();
@Override
public short blockRefresh(@NotNull Instance instance, @NotNull BlockPosition blockPosition, short currentId) {
int x = blockPosition.getX();
int y = blockPosition.getY();
int z = blockPosition.getZ();
String east = "none"; String east = "none";
String north = "none"; String north = "none";
@ -57,7 +52,9 @@ public class WallPlacementRule extends BlockPlacementRule {
} }
@Override @Override
public short blockPlace(@NotNull Instance instance, @NotNull Block block, @NotNull BlockFace blockFace, @NotNull Player pl) { public short blockPlace(@NotNull Instance instance,
@NotNull Block block, @NotNull BlockFace blockFace, @NotNull BlockPosition blockPosition,
@NotNull Player pl) {
return getBlockId(); return getBlockId();
} }

View File

@ -82,6 +82,8 @@ public class BlockPlacementListener {
final Chunk chunk = instance.getChunkAt(blockPosition); final Chunk chunk = instance.getChunkAt(blockPosition);
// The concerned chunk will be send to the player if an error occur // The concerned chunk will be send to the player if an error occur
// This will ensure that the player has the correct version of the chunk // This will ensure that the player has the correct version of the chunk
boolean refreshChunk = false; boolean refreshChunk = false;
@ -101,26 +103,33 @@ public class BlockPlacementListener {
} }
if (!intersect) { if (!intersect) {
// BlockPlacementRule check
final BlockManager blockManager = MinecraftServer.getBlockManager();
final BlockPlacementRule blockPlacementRule = blockManager.getBlockPlacementRule(block);
final short blockStateId = blockPlacementRule == null ? block.getBlockId() :
blockPlacementRule.blockPlace(instance, block, blockFace, player);
PlayerBlockPlaceEvent playerBlockPlaceEvent = new PlayerBlockPlaceEvent(player, blockStateId, (short) 0, blockPosition, packet.hand); // BlockPlaceEvent check
PlayerBlockPlaceEvent playerBlockPlaceEvent = new PlayerBlockPlaceEvent(player, block, blockPosition, packet.hand);
playerBlockPlaceEvent.consumeBlock(player.getGameMode() != GameMode.CREATIVE); playerBlockPlaceEvent.consumeBlock(player.getGameMode() != GameMode.CREATIVE);
// BlockPlacementRule check
final boolean canPlace = blockPlacementRule == null || blockPlacementRule.canPlace(instance, blockPosition);
player.callEvent(PlayerBlockPlaceEvent.class, playerBlockPlaceEvent); player.callEvent(PlayerBlockPlaceEvent.class, playerBlockPlaceEvent);
if (!playerBlockPlaceEvent.isCancelled() && canPlace) { if (!playerBlockPlaceEvent.isCancelled()) {
// BlockPlacementRule check
final Block resultBlock = Block.fromStateId(playerBlockPlaceEvent.getBlockStateId());
final BlockManager blockManager = MinecraftServer.getBlockManager();
final BlockPlacementRule blockPlacementRule = blockManager.getBlockPlacementRule(resultBlock);
final short blockStateId = blockPlacementRule == null ? resultBlock.getBlockId() :
blockPlacementRule.blockPlace(instance, resultBlock, blockFace, blockPosition, player);
final boolean placementRuleCheck = blockStateId != BlockPlacementRule.CANCEL_CODE;
if (placementRuleCheck) {
// Place the block
final short customBlockId = playerBlockPlaceEvent.getCustomBlockId(); final short customBlockId = playerBlockPlaceEvent.getCustomBlockId();
if (customBlockId != 0) { if (customBlockId != 0) {
instance.setSeparateBlocks(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), playerBlockPlaceEvent.getBlockStateId(), playerBlockPlaceEvent.getCustomBlockId()); instance.setSeparateBlocks(blockPosition, playerBlockPlaceEvent.getBlockStateId(), customBlockId);
} else { } else {
instance.setBlockStateId(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), playerBlockPlaceEvent.getBlockStateId()); instance.setBlockStateId(blockPosition, playerBlockPlaceEvent.getBlockStateId());
} }
// Block consuming
if (playerBlockPlaceEvent.doesConsumeBlock()) { if (playerBlockPlaceEvent.doesConsumeBlock()) {
// Consume the block in the player's hand // Consume the block in the player's hand
final ItemStack newUsedItem = usedItem.consume(1); final ItemStack newUsedItem = usedItem.consume(1);
@ -138,6 +147,9 @@ public class BlockPlacementListener {
} else { } else {
refreshChunk = true; refreshChunk = true;
} }
} else {
refreshChunk = true;
}
} else { } else {
// Player didn't try to place a block but interacted with one // Player didn't try to place a block but interacted with one
PlayerUseItemOnBlockEvent event = new PlayerUseItemOnBlockEvent(player, hand, usedItem, blockPosition, direction); PlayerUseItemOnBlockEvent event = new PlayerUseItemOnBlockEvent(player, hand, usedItem, blockPosition, direction);