mirror of
https://github.com/Minestom/Minestom.git
synced 2025-02-06 15:31:43 +01:00
Fix BlockHandler#onInteract return, simplify block placement code
This commit is contained in:
parent
518aab3a44
commit
ac3cbce278
@ -1,11 +1,11 @@
|
|||||||
package net.minestom.server.instance.block;
|
package net.minestom.server.instance.block;
|
||||||
|
|
||||||
|
import net.minestom.server.coordinate.Point;
|
||||||
import net.minestom.server.entity.Entity;
|
import net.minestom.server.entity.Entity;
|
||||||
import net.minestom.server.entity.Player;
|
import net.minestom.server.entity.Player;
|
||||||
import net.minestom.server.instance.Instance;
|
import net.minestom.server.instance.Instance;
|
||||||
import net.minestom.server.tag.Tag;
|
import net.minestom.server.tag.Tag;
|
||||||
import net.minestom.server.utils.NamespaceID;
|
import net.minestom.server.utils.NamespaceID;
|
||||||
import net.minestom.server.coordinate.Point;
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@ -42,10 +42,10 @@ public interface BlockHandler {
|
|||||||
* menu, this prevents the player from placing a block when opening it for instance).
|
* menu, this prevents the player from placing a block when opening it for instance).
|
||||||
*
|
*
|
||||||
* @param interaction the interaction details
|
* @param interaction the interaction details
|
||||||
* @return true if this block blocks normal item use, false otherwise
|
* @return true to let the block interaction happens, false to cancel
|
||||||
*/
|
*/
|
||||||
default boolean onInteract(@NotNull Interaction interaction) {
|
default boolean onInteract(@NotNull Interaction interaction) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,7 +2,6 @@ package net.minestom.server.listener;
|
|||||||
|
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.coordinate.Point;
|
import net.minestom.server.coordinate.Point;
|
||||||
import net.minestom.server.coordinate.Vec;
|
|
||||||
import net.minestom.server.entity.Entity;
|
import net.minestom.server.entity.Entity;
|
||||||
import net.minestom.server.entity.EntityType;
|
import net.minestom.server.entity.EntityType;
|
||||||
import net.minestom.server.entity.GameMode;
|
import net.minestom.server.entity.GameMode;
|
||||||
@ -31,7 +30,6 @@ import net.minestom.server.utils.validate.Check;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class BlockPlacementListener {
|
public class BlockPlacementListener {
|
||||||
|
|
||||||
private static final BlockManager BLOCK_MANAGER = MinecraftServer.getBlockManager();
|
private static final BlockManager BLOCK_MANAGER = MinecraftServer.getBlockManager();
|
||||||
|
|
||||||
public static void listener(ClientPlayerBlockPlacementPacket packet, Player player) {
|
public static void listener(ClientPlayerBlockPlacementPacket packet, Player player) {
|
||||||
@ -58,61 +56,57 @@ public class BlockPlacementListener {
|
|||||||
// FIXME: onUseOnBlock
|
// FIXME: onUseOnBlock
|
||||||
PlayerBlockInteractEvent playerBlockInteractEvent = new PlayerBlockInteractEvent(player, hand, interactedBlock, blockPosition, blockFace);
|
PlayerBlockInteractEvent playerBlockInteractEvent = new PlayerBlockInteractEvent(player, hand, interactedBlock, blockPosition, blockFace);
|
||||||
EventDispatcher.call(playerBlockInteractEvent);
|
EventDispatcher.call(playerBlockInteractEvent);
|
||||||
|
boolean blockUse = playerBlockInteractEvent.isBlockingItemUse();
|
||||||
if (!playerBlockInteractEvent.isCancelled()) {
|
if (!playerBlockInteractEvent.isCancelled()) {
|
||||||
final var handler = interactedBlock.handler();
|
final var handler = interactedBlock.handler();
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
handler.onInteract(new BlockHandler.Interaction(interactedBlock, instance, blockPosition, player, hand));
|
blockUse |= !handler.onInteract(new BlockHandler.Interaction(interactedBlock, instance, blockPosition, player, hand));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (playerBlockInteractEvent.isBlockingItemUse()) {
|
if (blockUse) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Material useMaterial = usedItem.getMaterial();
|
final Material useMaterial = usedItem.getMaterial();
|
||||||
|
if (!useMaterial.isBlock()) {
|
||||||
// Verify if the player can place the block
|
// Player didn't try to place a block but interacted with one
|
||||||
boolean canPlaceBlock = true;
|
PlayerUseItemOnBlockEvent event = new PlayerUseItemOnBlockEvent(player, hand, usedItem, blockPosition, direction);
|
||||||
{
|
EventDispatcher.call(event);
|
||||||
if (useMaterial == Material.AIR) { // Can't place air
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify if the player can place the block
|
||||||
|
boolean canPlaceBlock = true;
|
||||||
// Check if the player is allowed to place blocks based on their game mode
|
// Check if the player is allowed to place blocks based on their game mode
|
||||||
if (player.getGameMode() == GameMode.SPECTATOR) {
|
if (player.getGameMode() == GameMode.SPECTATOR) {
|
||||||
canPlaceBlock = false; // Spectators can't place blocks
|
canPlaceBlock = false; // Spectators can't place blocks
|
||||||
} else if (player.getGameMode() == GameMode.ADVENTURE) {
|
} else if (player.getGameMode() == GameMode.ADVENTURE) {
|
||||||
//Check if the block can placed on the block
|
//Check if the block can be placed on the block
|
||||||
canPlaceBlock = usedItem.getMeta().getCanPlaceOn().contains(interactedBlock);
|
canPlaceBlock = usedItem.getMeta().getCanPlaceOn().contains(interactedBlock);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Get the newly placed block position
|
// Get the newly placed block position
|
||||||
final int offsetX = blockFace == BlockFace.WEST ? -1 : blockFace == BlockFace.EAST ? 1 : 0;
|
final int offsetX = blockFace == BlockFace.WEST ? -1 : blockFace == BlockFace.EAST ? 1 : 0;
|
||||||
final int offsetY = blockFace == BlockFace.BOTTOM ? -1 : blockFace == BlockFace.TOP ? 1 : 0;
|
final int offsetY = blockFace == BlockFace.BOTTOM ? -1 : blockFace == BlockFace.TOP ? 1 : 0;
|
||||||
final int offsetZ = blockFace == BlockFace.NORTH ? -1 : blockFace == BlockFace.SOUTH ? 1 : 0;
|
final int offsetZ = blockFace == BlockFace.NORTH ? -1 : blockFace == BlockFace.SOUTH ? 1 : 0;
|
||||||
|
final Point placementPosition = blockPosition.add(offsetX, offsetY, offsetZ);
|
||||||
final Point placementPosition = new Vec(offsetX, offsetY, offsetZ).add(blockPosition);
|
|
||||||
|
|
||||||
if (!canPlaceBlock) {
|
if (!canPlaceBlock) {
|
||||||
if (useMaterial.isBlock()) {
|
|
||||||
// Send a block change with AIR as block to keep the client in sync,
|
// Send a block change with AIR as block to keep the client in sync,
|
||||||
// using refreshChunk results in the client not being in sync
|
// using refreshChunk results in the client not being in sync
|
||||||
// after rapid invalid block placements
|
// after rapid invalid block placements
|
||||||
player.getPlayerConnection().sendPacket(new BlockChangePacket(placementPosition, Block.AIR.stateId()));
|
player.getPlayerConnection().sendPacket(new BlockChangePacket(placementPosition, Block.AIR));
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Chunk chunk = instance.getChunkAt(placementPosition);
|
final Chunk chunk = instance.getChunkAt(placementPosition);
|
||||||
Check.stateCondition(!ChunkUtils.isLoaded(chunk),
|
Check.stateCondition(!ChunkUtils.isLoaded(chunk),
|
||||||
"A player tried to place a block in the border of a loaded chunk {0}", placementPosition);
|
"A player tried to place a block in the border of a loaded chunk {0}", placementPosition);
|
||||||
|
if (chunk.isReadOnly()) {
|
||||||
|
chunk.sendChunk(player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 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
|
|
||||||
boolean refreshChunk = false;
|
|
||||||
|
|
||||||
if (useMaterial.isBlock()) {
|
|
||||||
if (!chunk.isReadOnly()) {
|
|
||||||
final Block placedBlock = useMaterial.getBlock();
|
final Block placedBlock = useMaterial.getBlock();
|
||||||
final Set<Entity> entities = instance.getChunkEntities(chunk);
|
final Set<Entity> entities = instance.getChunkEntities(chunk);
|
||||||
// Check if the player is trying to place a block in an entity
|
// Check if the player is trying to place a block in an entity
|
||||||
@ -136,14 +130,18 @@ public class BlockPlacementListener {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (intersect) {
|
||||||
if (!intersect) {
|
chunk.sendChunk(player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// BlockPlaceEvent check
|
// BlockPlaceEvent check
|
||||||
PlayerBlockPlaceEvent playerBlockPlaceEvent = new PlayerBlockPlaceEvent(player, placedBlock, blockFace, placementPosition, packet.hand);
|
PlayerBlockPlaceEvent playerBlockPlaceEvent = new PlayerBlockPlaceEvent(player, placedBlock, blockFace, placementPosition, packet.hand);
|
||||||
playerBlockPlaceEvent.consumeBlock(player.getGameMode() != GameMode.CREATIVE);
|
playerBlockPlaceEvent.consumeBlock(player.getGameMode() != GameMode.CREATIVE);
|
||||||
|
|
||||||
EventDispatcher.call(playerBlockPlaceEvent);
|
EventDispatcher.call(playerBlockPlaceEvent);
|
||||||
if (!playerBlockPlaceEvent.isCancelled()) {
|
if (playerBlockPlaceEvent.isCancelled()) {
|
||||||
|
chunk.sendChunk(player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// BlockPlacementRule check
|
// BlockPlacementRule check
|
||||||
Block resultBlock = playerBlockPlaceEvent.getBlock();
|
Block resultBlock = playerBlockPlaceEvent.getBlock();
|
||||||
@ -152,8 +150,10 @@ public class BlockPlacementListener {
|
|||||||
// Get id from block placement rule instead of the event
|
// Get id from block placement rule instead of the event
|
||||||
resultBlock = blockPlacementRule.blockPlace(instance, resultBlock, blockFace, blockPosition, player);
|
resultBlock = blockPlacementRule.blockPlace(instance, resultBlock, blockFace, blockPosition, player);
|
||||||
}
|
}
|
||||||
final boolean placementRuleCheck = resultBlock != null;
|
if (resultBlock == null) {
|
||||||
if (placementRuleCheck) {
|
chunk.sendChunk(player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Place the block
|
// Place the block
|
||||||
instance.placeBlock(player, resultBlock, placementPosition,
|
instance.placeBlock(player, resultBlock, placementPosition,
|
||||||
blockFace, packet.cursorPositionX, packet.cursorPositionY, packet.cursorPositionZ);
|
blockFace, packet.cursorPositionX, packet.cursorPositionY, packet.cursorPositionZ);
|
||||||
@ -163,28 +163,5 @@ public class BlockPlacementListener {
|
|||||||
final ItemStack newUsedItem = usedItem.getStackingRule().apply(usedItem, usedItem.getAmount() - 1);
|
final ItemStack newUsedItem = usedItem.getStackingRule().apply(usedItem, usedItem.getAmount() - 1);
|
||||||
playerInventory.setItemInHand(hand, newUsedItem);
|
playerInventory.setItemInHand(hand, newUsedItem);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
refreshChunk = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
refreshChunk = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
refreshChunk = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
refreshChunk = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Player didn't try to place a block but interacted with one
|
|
||||||
PlayerUseItemOnBlockEvent event = new PlayerUseItemOnBlockEvent(player, hand, usedItem, blockPosition, direction);
|
|
||||||
EventDispatcher.call(event);
|
|
||||||
refreshChunk = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refresh chunk section if needed
|
|
||||||
if (refreshChunk) {
|
|
||||||
chunk.sendChunk(player);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package net.minestom.server.network.packet.server.play;
|
package net.minestom.server.network.packet.server.play;
|
||||||
|
|
||||||
|
import net.minestom.server.coordinate.Point;
|
||||||
|
import net.minestom.server.coordinate.Vec;
|
||||||
|
import net.minestom.server.instance.block.Block;
|
||||||
import net.minestom.server.network.packet.server.ServerPacket;
|
import net.minestom.server.network.packet.server.ServerPacket;
|
||||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||||
import net.minestom.server.utils.binary.BinaryReader;
|
import net.minestom.server.utils.binary.BinaryReader;
|
||||||
import net.minestom.server.utils.binary.BinaryWriter;
|
import net.minestom.server.utils.binary.BinaryWriter;
|
||||||
import net.minestom.server.coordinate.Point;
|
|
||||||
import net.minestom.server.coordinate.Vec;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class BlockChangePacket implements ServerPacket {
|
public class BlockChangePacket implements ServerPacket {
|
||||||
@ -18,6 +19,10 @@ public class BlockChangePacket implements ServerPacket {
|
|||||||
this.blockStateId = blockStateId;
|
this.blockStateId = blockStateId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BlockChangePacket(Point blockPosition, Block block) {
|
||||||
|
this(blockPosition, block.stateId());
|
||||||
|
}
|
||||||
|
|
||||||
public BlockChangePacket() {
|
public BlockChangePacket() {
|
||||||
this(Vec.ZERO, 0);
|
this(Vec.ZERO, 0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user