Improve BlockHanlder placement listener

This commit is contained in:
TheMode 2021-06-23 20:18:34 +02:00
parent af9e102ec1
commit 48b1aa90db
5 changed files with 50 additions and 23 deletions

View File

@ -22,10 +22,7 @@ import net.minestom.server.event.instance.AddEntityToInstanceEvent;
import net.minestom.server.event.instance.InstanceTickEvent;
import net.minestom.server.event.instance.RemoveEntityFromInstanceEvent;
import net.minestom.server.event.trait.InstanceEvent;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockGetter;
import net.minestom.server.instance.block.BlockManager;
import net.minestom.server.instance.block.BlockSetter;
import net.minestom.server.instance.block.*;
import net.minestom.server.network.packet.server.play.BlockActionPacket;
import net.minestom.server.network.packet.server.play.TimeUpdatePacket;
import net.minestom.server.storage.StorageLocation;
@ -145,7 +142,9 @@ public abstract class Instance implements BlockGetter, BlockSetter, Tickable, Ev
this.nextTick.add(callback);
}
public abstract boolean placeBlock(@NotNull Player player, @NotNull Block block, @NotNull BlockPosition blockPosition);
@ApiStatus.Internal
public abstract boolean placeBlock(@NotNull Player player, @NotNull Block block, @NotNull BlockPosition blockPosition,
@NotNull BlockFace blockFace, float cursorX, float cursorY, float cursorZ);
/**
* Does call {@link net.minestom.server.event.player.PlayerBlockBreakEvent}
@ -155,6 +154,7 @@ public abstract class Instance implements BlockGetter, BlockSetter, Tickable, Ev
* @param blockPosition the {@link BlockPosition} of the broken block
* @return true if the block has been broken, false if it has been cancelled
*/
@ApiStatus.Internal
public abstract boolean breakBlock(@NotNull Player player, @NotNull BlockPosition blockPosition);
/**

View File

@ -10,6 +10,7 @@ import net.minestom.server.event.instance.InstanceChunkUnloadEvent;
import net.minestom.server.event.player.PlayerBlockBreakEvent;
import net.minestom.server.instance.batch.ChunkGenerationBatch;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockFace;
import net.minestom.server.instance.block.BlockHandler;
import net.minestom.server.instance.block.rule.BlockPlacementRule;
import net.minestom.server.network.packet.server.play.BlockChangePacket;
@ -106,13 +107,13 @@ public class InstanceContainer extends Instance {
public synchronized void setBlock(int x, int y, int z, @NotNull Block block) {
final Chunk chunk = getChunkAt(x, z);
if (ChunkUtils.isLoaded(chunk)) {
UNSAFE_setBlock(chunk, x, y, z, block, null);
UNSAFE_setBlock(chunk, x, y, z, block, null, null);
} else {
Check.stateCondition(!hasEnabledAutoChunkLoad(),
"Tried to set a block to an unloaded chunk with auto chunk load disabled");
final int chunkX = ChunkUtils.getChunkCoordinate(x);
final int chunkZ = ChunkUtils.getChunkCoordinate(z);
loadChunk(chunkX, chunkZ, c -> UNSAFE_setBlock(c, x, y, z, block, null));
loadChunk(chunkX, chunkZ, c -> UNSAFE_setBlock(c, x, y, z, block, null, null));
}
}
@ -128,7 +129,7 @@ public class InstanceContainer extends Instance {
* @param block the block to place
*/
private void UNSAFE_setBlock(@NotNull Chunk chunk, int x, int y, int z, @NotNull Block block,
@Nullable Player player) {
@Nullable BlockHandler.Placement placement, @Nullable BlockHandler.Destroy destroy) {
// Cannot place block in a read-only chunk
if (chunk.isReadOnly()) {
return;
@ -161,28 +162,27 @@ public class InstanceContainer extends Instance {
if (previousHandler != null) {
// Previous destroy
final var destroy = player != null ?
new BlockHandler.PlayerDestroy(previousBlock, this, blockPosition, player) :
BlockHandler.Destroy.from(previousBlock, this, blockPosition);
previousHandler.onDestroy(destroy);
previousHandler.onDestroy(Objects.requireNonNullElseGet(destroy,
() -> BlockHandler.Destroy.from(previousBlock, this, blockPosition)));
}
final BlockHandler handler = block.handler();
if (handler != null) {
// New placement
final var placement = player != null ?
new BlockHandler.PlayerPlacement(block, this, blockPosition, player) :
BlockHandler.Placement.from(block, this, blockPosition);
handler.onPlace(placement);
final Block finalBlock = block;
handler.onPlace(Objects.requireNonNullElseGet(placement,
() -> BlockHandler.Placement.from(finalBlock, this, blockPosition)));
}
}
}
@Override
public boolean placeBlock(@NotNull Player player, @NotNull Block block, @NotNull BlockPosition blockPosition) {
public boolean placeBlock(@NotNull Player player, @NotNull Block block, @NotNull BlockPosition blockPosition,
@NotNull BlockFace blockFace, float cursorX, float cursorY, float cursorZ) {
final Chunk chunk = getChunkAt(blockPosition);
if (!ChunkUtils.isLoaded(chunk))
return false;
UNSAFE_setBlock(chunk, blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), block, player);
UNSAFE_setBlock(chunk, blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), block,
new BlockHandler.PlayerPlacement(block, this, blockPosition, player, blockFace, cursorX, cursorY, cursorZ), null);
return true;
}
@ -215,7 +215,8 @@ public class InstanceContainer extends Instance {
if (allowed) {
// Break or change the broken block based on event result
final Block resultBlock = blockBreakEvent.getResultBlock();
UNSAFE_setBlock(chunk, x, y, z, resultBlock, player);
UNSAFE_setBlock(chunk, x, y, z, resultBlock, null,
new BlockHandler.PlayerDestroy(block, this, blockPosition, player));
// Send the block break effect packet
{

View File

@ -2,6 +2,7 @@ package net.minestom.server.instance;
import net.minestom.server.entity.Player;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockFace;
import net.minestom.server.storage.StorageLocation;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.Position;
@ -31,8 +32,9 @@ public class SharedInstance extends Instance {
}
@Override
public boolean placeBlock(@NotNull Player player, @NotNull Block block, @NotNull BlockPosition blockPosition) {
return instanceContainer.placeBlock(player, block, blockPosition);
public boolean placeBlock(@NotNull Player player, @NotNull Block block, @NotNull BlockPosition blockPosition,
@NotNull BlockFace blockFace, float cursorX, float cursorY, float cursorZ) {
return instanceContainer.placeBlock(player, block, blockPosition, blockFace, cursorX, cursorY, cursorZ);
}
@Override

View File

@ -117,12 +117,19 @@ public interface BlockHandler {
private final Instance instance;
private final BlockPosition blockPosition;
private final Player player;
private final BlockFace blockFace;
private final float cursorX, cursorY, cursorZ;
public PlayerPlacement(Block block, Instance instance, BlockPosition blockPosition, Player player) {
public PlayerPlacement(Block block, Instance instance, BlockPosition blockPosition, Player player,
BlockFace blockFace, float cursorX, float cursorY, float cursorZ) {
this.block = block;
this.instance = instance;
this.blockPosition = blockPosition;
this.player = player;
this.blockFace = blockFace;
this.cursorX = cursorX;
this.cursorY = cursorY;
this.cursorZ = cursorZ;
}
@Override
@ -143,6 +150,22 @@ public interface BlockHandler {
public @NotNull Player player() {
return player;
}
public @NotNull BlockFace blockFace() {
return blockFace;
}
public float cursorX() {
return cursorX;
}
public float cursorY() {
return cursorY;
}
public float cursorZ() {
return cursorZ;
}
}
@ApiStatus.NonExtendable

View File

@ -142,7 +142,8 @@ public class BlockPlacementListener {
final boolean placementRuleCheck = resultBlock != null;
if (placementRuleCheck) {
// Place the block
instance.placeBlock(player, resultBlock, blockPosition);
instance.placeBlock(player, resultBlock, blockPosition,
blockFace, packet.cursorPositionX, packet.cursorPositionY, packet.cursorPositionZ);
// Block consuming
if (playerBlockPlaceEvent.doesConsumeBlock()) {
// Consume the block in the player's hand