2020-04-24 03:25:58 +02:00
|
|
|
package net.minestom.server.listener;
|
2019-08-20 17:41:07 +02:00
|
|
|
|
2020-04-24 03:25:58 +02:00
|
|
|
import net.minestom.server.MinecraftServer;
|
|
|
|
import net.minestom.server.data.Data;
|
|
|
|
import net.minestom.server.entity.Entity;
|
|
|
|
import net.minestom.server.entity.GameMode;
|
|
|
|
import net.minestom.server.entity.Player;
|
2020-05-07 15:46:21 +02:00
|
|
|
import net.minestom.server.event.player.PlayerBlockInteractEvent;
|
|
|
|
import net.minestom.server.event.player.PlayerBlockPlaceEvent;
|
|
|
|
import net.minestom.server.event.player.PlayerUseItemOnBlockEvent;
|
2020-04-24 03:25:58 +02:00
|
|
|
import net.minestom.server.instance.Chunk;
|
|
|
|
import net.minestom.server.instance.Instance;
|
|
|
|
import net.minestom.server.instance.block.Block;
|
|
|
|
import net.minestom.server.instance.block.BlockManager;
|
|
|
|
import net.minestom.server.instance.block.CustomBlock;
|
|
|
|
import net.minestom.server.instance.block.rule.BlockPlacementRule;
|
|
|
|
import net.minestom.server.inventory.PlayerInventory;
|
|
|
|
import net.minestom.server.item.ItemStack;
|
|
|
|
import net.minestom.server.item.Material;
|
|
|
|
import net.minestom.server.item.StackingRule;
|
|
|
|
import net.minestom.server.network.packet.client.play.ClientPlayerBlockPlacementPacket;
|
|
|
|
import net.minestom.server.network.packet.client.play.ClientPlayerDiggingPacket;
|
|
|
|
import net.minestom.server.utils.BlockPosition;
|
|
|
|
import net.minestom.server.utils.ChunkUtils;
|
2019-08-20 17:41:07 +02:00
|
|
|
|
2020-04-21 15:31:41 +02:00
|
|
|
import java.util.Set;
|
|
|
|
|
2019-08-20 17:41:07 +02:00
|
|
|
public class BlockPlacementListener {
|
|
|
|
|
|
|
|
public static void listener(ClientPlayerBlockPlacementPacket packet, Player player) {
|
2019-08-29 02:15:52 +02:00
|
|
|
PlayerInventory playerInventory = player.getInventory();
|
|
|
|
Player.Hand hand = packet.hand;
|
2019-08-20 17:41:07 +02:00
|
|
|
ClientPlayerDiggingPacket.BlockFace blockFace = packet.blockFace;
|
2019-08-21 16:50:52 +02:00
|
|
|
BlockPosition blockPosition = packet.blockPosition;
|
2019-08-20 17:41:07 +02:00
|
|
|
|
|
|
|
Instance instance = player.getInstance();
|
|
|
|
if (instance == null)
|
|
|
|
return;
|
|
|
|
|
2020-04-21 15:31:41 +02:00
|
|
|
// Interact at block
|
2020-03-30 19:48:25 +02:00
|
|
|
PlayerBlockInteractEvent playerBlockInteractEvent = new PlayerBlockInteractEvent(blockPosition, hand);
|
|
|
|
player.callCancellableEvent(PlayerBlockInteractEvent.class, playerBlockInteractEvent, () -> {
|
|
|
|
CustomBlock customBlock = instance.getCustomBlock(blockPosition);
|
|
|
|
if (customBlock != null) {
|
|
|
|
Data data = instance.getBlockData(blockPosition);
|
2020-04-28 18:12:06 +02:00
|
|
|
boolean blocksItem = customBlock.onInteract(player, hand, blockPosition, data);
|
|
|
|
if(blocksItem) {
|
|
|
|
playerBlockInteractEvent.setBlockingItemUse(true);
|
|
|
|
}
|
2020-03-30 19:48:25 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-04-28 18:12:06 +02:00
|
|
|
if(playerBlockInteractEvent.isBlockingItemUse()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-04-21 15:31:41 +02:00
|
|
|
// Check if item at hand is a block
|
2019-08-29 02:15:52 +02:00
|
|
|
ItemStack usedItem = hand == Player.Hand.MAIN ? playerInventory.getItemInMainHand() : playerInventory.getItemInOffHand();
|
2020-03-29 20:58:30 +02:00
|
|
|
Material material = Material.fromId(usedItem.getMaterialId());
|
2020-05-03 22:44:38 +02:00
|
|
|
if(material == Material.AIR) {
|
2019-08-29 02:15:52 +02:00
|
|
|
return;
|
2019-09-01 06:18:41 +02:00
|
|
|
}
|
2019-08-29 02:15:52 +02:00
|
|
|
|
2020-04-21 15:31:41 +02:00
|
|
|
// Get the newly placed block position
|
2019-08-20 17:41:07 +02:00
|
|
|
int offsetX = blockFace == ClientPlayerDiggingPacket.BlockFace.WEST ? -1 : blockFace == ClientPlayerDiggingPacket.BlockFace.EAST ? 1 : 0;
|
|
|
|
int offsetY = blockFace == ClientPlayerDiggingPacket.BlockFace.BOTTOM ? -1 : blockFace == ClientPlayerDiggingPacket.BlockFace.TOP ? 1 : 0;
|
|
|
|
int offsetZ = blockFace == ClientPlayerDiggingPacket.BlockFace.NORTH ? -1 : blockFace == ClientPlayerDiggingPacket.BlockFace.SOUTH ? 1 : 0;
|
|
|
|
|
2019-08-22 14:52:32 +02:00
|
|
|
blockPosition.add(offsetX, offsetY, offsetZ);
|
2020-04-21 15:31:41 +02:00
|
|
|
|
|
|
|
|
2020-04-25 20:40:08 +02:00
|
|
|
Chunk chunk = instance.getChunkAt(blockPosition);
|
2020-04-21 15:31:41 +02:00
|
|
|
boolean refreshChunk = false;
|
|
|
|
|
2020-04-25 20:40:08 +02:00
|
|
|
if (material.isBlock()) {
|
2020-04-17 15:58:07 +02:00
|
|
|
Block block = material.getBlock();
|
2020-04-25 20:40:08 +02:00
|
|
|
|
|
|
|
Set<Entity> entities = instance.getChunkEntities(chunk);
|
|
|
|
boolean intersect = false;
|
|
|
|
if (block.isSolid()) {
|
|
|
|
for (Entity entity : entities) {
|
|
|
|
intersect = entity.getBoundingBox().intersect(blockPosition);
|
|
|
|
if (intersect)
|
|
|
|
break;
|
|
|
|
}
|
2020-04-17 15:58:07 +02:00
|
|
|
}
|
|
|
|
|
2020-04-25 20:40:08 +02:00
|
|
|
if (!intersect) {
|
2020-04-28 21:52:06 +02:00
|
|
|
PlayerBlockPlaceEvent playerBlockPlaceEvent = new PlayerBlockPlaceEvent(player, block.getBlockId(), (short) 0, blockPosition, packet.hand);
|
2020-04-25 20:40:08 +02:00
|
|
|
playerBlockPlaceEvent.consumeBlock(player.getGameMode() != GameMode.CREATIVE);
|
|
|
|
|
|
|
|
// BlockPlacementRule check
|
|
|
|
BlockManager blockManager = MinecraftServer.getBlockManager();
|
|
|
|
BlockPlacementRule blockPlacementRule = blockManager.getBlockPlacementRule(block);
|
|
|
|
boolean canPlace = true;
|
|
|
|
if (blockPlacementRule != null) {
|
|
|
|
canPlace = blockPlacementRule.canPlace(instance, blockPosition);
|
|
|
|
}
|
|
|
|
|
|
|
|
player.callEvent(PlayerBlockPlaceEvent.class, playerBlockPlaceEvent);
|
|
|
|
if (!playerBlockPlaceEvent.isCancelled() && canPlace) {
|
2020-04-28 13:47:41 +02:00
|
|
|
short customBlockId = playerBlockPlaceEvent.getCustomBlockId();
|
|
|
|
if(customBlockId != 0) {
|
2020-04-29 00:42:18 +02:00
|
|
|
instance.setSeparateBlocks(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), playerBlockPlaceEvent.getBlockId(), playerBlockPlaceEvent.getCustomBlockId());
|
2020-04-28 13:47:41 +02:00
|
|
|
} else {
|
|
|
|
instance.setBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), playerBlockPlaceEvent.getBlockId());
|
|
|
|
}
|
2020-04-25 20:40:08 +02:00
|
|
|
if (playerBlockPlaceEvent.doesConsumeBlock()) {
|
2020-02-17 17:33:53 +01:00
|
|
|
|
2020-04-25 20:40:08 +02:00
|
|
|
StackingRule stackingRule = usedItem.getStackingRule();
|
|
|
|
ItemStack newUsedItem = stackingRule.apply(usedItem, stackingRule.getAmount(usedItem) - 1);
|
2020-02-17 17:33:53 +01:00
|
|
|
|
2020-04-25 20:40:08 +02:00
|
|
|
if (hand == Player.Hand.OFF) {
|
|
|
|
playerInventory.setItemInOffHand(newUsedItem);
|
|
|
|
} else { // Main
|
|
|
|
playerInventory.setItemInMainHand(newUsedItem);
|
|
|
|
}
|
2019-08-31 07:54:53 +02:00
|
|
|
}
|
2020-04-25 20:40:08 +02:00
|
|
|
} else {
|
|
|
|
refreshChunk = true;
|
2019-08-29 02:15:52 +02:00
|
|
|
}
|
2019-08-31 07:54:53 +02:00
|
|
|
} else {
|
2020-04-21 15:31:41 +02:00
|
|
|
refreshChunk = true;
|
2019-08-29 02:15:52 +02:00
|
|
|
}
|
2020-04-20 18:46:39 +02:00
|
|
|
} else {
|
2020-05-03 22:44:38 +02:00
|
|
|
PlayerUseItemOnBlockEvent event = new PlayerUseItemOnBlockEvent(hand, usedItem, blockPosition, blockFace.toDirection());
|
|
|
|
player.callEvent(PlayerUseItemOnBlockEvent.class, event);
|
2020-04-21 15:31:41 +02:00
|
|
|
refreshChunk = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Refresh chunk section if needed
|
|
|
|
if (refreshChunk) {
|
2020-04-20 18:46:39 +02:00
|
|
|
instance.sendChunkSectionUpdate(chunk, ChunkUtils.getSectionAt(blockPosition.getY()), player);
|
2019-08-20 17:41:07 +02:00
|
|
|
}
|
2020-04-21 15:31:41 +02:00
|
|
|
|
2019-08-20 17:41:07 +02:00
|
|
|
player.getInventory().refreshSlot(player.getHeldSlot());
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|