From 739c3f1d7dd4a86b9a180767c29f2912d56f702a Mon Sep 17 00:00:00 2001 From: themode Date: Sat, 10 Oct 2020 13:46:41 +0200 Subject: [PATCH] Allow non-custom block in PlayerStartDiggingEvent --- .../net/minestom/server/entity/Player.java | 11 ++-- .../event/player/PlayerStartDiggingEvent.java | 32 +++++++---- .../server/instance/InstanceContainer.java | 10 ++++ .../minestom/server/inventory/Inventory.java | 12 +++- .../listener/PlayerDiggingListener.java | 55 ++++++++++++------- 5 files changed, 80 insertions(+), 40 deletions(-) diff --git a/src/main/java/net/minestom/server/entity/Player.java b/src/main/java/net/minestom/server/entity/Player.java index d55b21dfb..510197058 100644 --- a/src/main/java/net/minestom/server/entity/Player.java +++ b/src/main/java/net/minestom/server/entity/Player.java @@ -25,13 +25,13 @@ import net.minestom.server.inventory.Inventory; import net.minestom.server.inventory.PlayerInventory; import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; +import net.minestom.server.listener.PlayerDiggingListener; import net.minestom.server.network.packet.client.ClientPlayPacket; import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.login.JoinGamePacket; import net.minestom.server.network.packet.server.play.*; import net.minestom.server.network.player.PlayerConnection; import net.minestom.server.permission.Permission; -import net.minestom.server.potion.PotionType; import net.minestom.server.recipe.Recipe; import net.minestom.server.recipe.RecipeManager; import net.minestom.server.resourcepack.ResourcePack; @@ -1946,6 +1946,9 @@ public class Player extends LivingEntity implements CommandSender { * If the currently mined block (or if there isn't any) is not a {@link CustomBlock}, nothing happen */ public void resetTargetBlock() { + // Remove effect + PlayerDiggingListener.removeEffect(this); + if (targetCustomBlock != null) { targetCustomBlock.stopDigging(instance, targetBlockPosition, this); this.targetCustomBlock = null; @@ -1953,12 +1956,6 @@ public class Player extends LivingEntity implements CommandSender { this.targetBreakDelay = 0; this.targetBlockBreakCount = 0; this.targetStage = 0; - - // Remove effect - RemoveEntityEffectPacket removeEntityEffectPacket = new RemoveEntityEffectPacket(); - removeEntityEffectPacket.entityId = getEntityId(); - removeEntityEffectPacket.effect = PotionType.AWKWARD; - playerConnection.sendPacket(removeEntityEffectPacket); } } diff --git a/src/main/java/net/minestom/server/event/player/PlayerStartDiggingEvent.java b/src/main/java/net/minestom/server/event/player/PlayerStartDiggingEvent.java index d01be0d1f..9f97e1eb2 100644 --- a/src/main/java/net/minestom/server/event/player/PlayerStartDiggingEvent.java +++ b/src/main/java/net/minestom/server/event/player/PlayerStartDiggingEvent.java @@ -2,25 +2,24 @@ package net.minestom.server.event.player; import net.minestom.server.entity.Player; import net.minestom.server.event.CancellableEvent; -import net.minestom.server.instance.block.CustomBlock; import net.minestom.server.utils.BlockPosition; /** - * Called when a player start digging a {@link CustomBlock}, - * can be used to forbid the player from mining a block - *

- * WARNING: this is not called for non-custom block + * Called when a player start digging a block, + * can be used to forbid the player from mining it. */ public class PlayerStartDiggingEvent extends CancellableEvent { private final Player player; private final BlockPosition blockPosition; - private final CustomBlock customBlock; + private final int blockStateId; + private final int customBlockId; - public PlayerStartDiggingEvent(Player player, BlockPosition blockPosition, CustomBlock customBlock) { + public PlayerStartDiggingEvent(Player player, BlockPosition blockPosition, int blockStateId, int customBlockId) { this.player = player; this.blockPosition = blockPosition; - this.customBlock = customBlock; + this.blockStateId = blockStateId; + this.customBlockId = customBlockId; } /** @@ -42,11 +41,20 @@ public class PlayerStartDiggingEvent extends CancellableEvent { } /** - * Get the custom block object that the player is trying to dig + * Get the block state id * - * @return the custom block + * @return the block state id */ - public CustomBlock getCustomBlock() { - return customBlock; + public int getBlockStateId() { + return blockStateId; + } + + /** + * Get the custom block id + * + * @return the custom block id + */ + public int getCustomBlockId() { + return customBlockId; } } diff --git a/src/main/java/net/minestom/server/instance/InstanceContainer.java b/src/main/java/net/minestom/server/instance/InstanceContainer.java index 6fb05eff2..3a5724cf5 100644 --- a/src/main/java/net/minestom/server/instance/InstanceContainer.java +++ b/src/main/java/net/minestom/server/instance/InstanceContainer.java @@ -46,20 +46,29 @@ public class InstanceContainer extends Instance { private static final String UUID_KEY = "uuid"; private static final String DATA_KEY = "data"; + // the storage location of this instance, can be null private StorageLocation storageLocation; + // the shared instances assigned to this instance private List sharedInstances = new CopyOnWriteArrayList<>(); + // the chunk generator used, can be null private ChunkGenerator chunkGenerator; + // (chunk index -> chunk) map, contains all the chunks in the instance private final ConcurrentHashMap chunks = new ConcurrentHashMap<>(); + // contains all the chunks to remove during the next instance tick protected final Set scheduledChunksToRemove = new HashSet<>(); private ReadWriteLock changingBlockLock = new ReentrantReadWriteLock(); private Map currentlyChangingBlocks = new HashMap<>(); + + // the chunk loader, used when trying to load/save a chunk from another source private IChunkLoader chunkLoader; + // used to automatically enable the chunk loading or not private boolean autoChunkLoad; + // used to supply a new chunk object at a position when requested private ChunkSupplier chunkSupplier; /** @@ -505,6 +514,7 @@ public class InstanceContainer extends Instance { protected void retrieveChunk(int chunkX, int chunkZ, ChunkCallback callback) { final boolean loaded = chunkLoader.loadChunk(this, chunkX, chunkZ, chunk -> { cacheChunk(chunk); + // FIXME: the event is not necessary called in the instance thread callChunkLoadEvent(chunkX, chunkZ); UPDATE_MANAGER.signalChunkLoad(this, chunkX, chunkZ); if (callback != null) diff --git a/src/main/java/net/minestom/server/inventory/Inventory.java b/src/main/java/net/minestom/server/inventory/Inventory.java index 6bfae55bd..08aaffce9 100644 --- a/src/main/java/net/minestom/server/inventory/Inventory.java +++ b/src/main/java/net/minestom/server/inventory/Inventory.java @@ -31,25 +31,33 @@ import java.util.concurrent.atomic.AtomicInteger; public class Inventory implements InventoryModifier, InventoryClickHandler, Viewable { + // incremented each time an inventory is created (used in the window packets) private static AtomicInteger lastInventoryId = new AtomicInteger(); + // the id of this inventory private final byte id; + // the type of this inventory private final InventoryType inventoryType; + // the title of this inventory) private String title; + // the size based on the inventory type private final int size; private final int offset; + // the items in this inventory private final ItemStack[] itemStacks; + // the players currently viewing this inventory private final Set viewers = new CopyOnWriteArraySet<>(); + // (player -> cursor item) map, used by the click listeners private final ConcurrentHashMap cursorPlayersItem = new ConcurrentHashMap<>(); + // list of conditions/callbacks assigned to this inventory private final List inventoryConditions = new CopyOnWriteArrayList<>(); + // the click processor which process all the clicks in the inventory private final InventoryClickProcessor clickProcessor = new InventoryClickProcessor(); - // Cached windows packet - public Inventory(InventoryType inventoryType, String title) { this.id = generateId(); this.inventoryType = inventoryType; diff --git a/src/main/java/net/minestom/server/listener/PlayerDiggingListener.java b/src/main/java/net/minestom/server/listener/PlayerDiggingListener.java index 888cab562..01206c80e 100644 --- a/src/main/java/net/minestom/server/listener/PlayerDiggingListener.java +++ b/src/main/java/net/minestom/server/listener/PlayerDiggingListener.java @@ -13,11 +13,17 @@ import net.minestom.server.item.StackingRule; import net.minestom.server.network.packet.client.play.ClientPlayerDiggingPacket; import net.minestom.server.network.packet.server.play.AcknowledgePlayerDiggingPacket; import net.minestom.server.network.packet.server.play.EntityEffectPacket; +import net.minestom.server.network.packet.server.play.RemoveEntityEffectPacket; import net.minestom.server.potion.PotionType; import net.minestom.server.utils.BlockPosition; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + public class PlayerDiggingListener { + private static final List playersEffect = new CopyOnWriteArrayList<>(); + public static void playerDiggingListener(ClientPlayerDiggingPacket packet, Player player) { final ClientPlayerDiggingPacket.Status status = packet.status; final BlockPosition blockPosition = packet.blockPosition; @@ -43,28 +49,26 @@ public class PlayerDiggingListener { breakBlock(instance, player, blockPosition, blockStateId); } else { final CustomBlock customBlock = instance.getCustomBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ()); - if (customBlock != null) { - // Custom block has a custom break time, allow for digging event - PlayerStartDiggingEvent playerStartDiggingEvent = new PlayerStartDiggingEvent(player, blockPosition, customBlock); - player.callEvent(PlayerStartDiggingEvent.class, playerStartDiggingEvent); - if (!playerStartDiggingEvent.isCancelled()) { + final int customBlockId = customBlock == null ? 0 : customBlock.getCustomBlockId(); - // Start digging the block - if (customBlock.enableCustomBreakDelay()) { - customBlock.startDigging(instance, blockPosition, player); - addEffect(player); - } + PlayerStartDiggingEvent playerStartDiggingEvent = new PlayerStartDiggingEvent(player, blockPosition, blockStateId, customBlockId); + player.callEvent(PlayerStartDiggingEvent.class, playerStartDiggingEvent); - sendAcknowledgePacket(player, blockPosition, customBlock.getDefaultBlockStateId(), - ClientPlayerDiggingPacket.Status.STARTED_DIGGING, true); - } else { - // Unsuccessful digging - sendAcknowledgePacket(player, blockPosition, customBlock.getDefaultBlockStateId(), - ClientPlayerDiggingPacket.Status.STARTED_DIGGING, false); + if (playerStartDiggingEvent.isCancelled()) { + addEffect(player); + + // Unsuccessful digging + sendAcknowledgePacket(player, blockPosition, blockStateId, + ClientPlayerDiggingPacket.Status.STARTED_DIGGING, false); + } else if (customBlock != null) { + // Start digging the custom block + if (customBlock.enableCustomBreakDelay()) { + customBlock.startDigging(instance, blockPosition, player); + addEffect(player); } - } else { - // Player is not mining a custom block, be sure that he doesn't have the effect - player.resetTargetBlock(); + + sendAcknowledgePacket(player, blockPosition, blockStateId, + ClientPlayerDiggingPacket.Status.STARTED_DIGGING, true); } } break; @@ -155,6 +159,8 @@ public class PlayerDiggingListener { } private static void addEffect(Player player) { + playersEffect.add(player); + EntityEffectPacket entityEffectPacket = new EntityEffectPacket(); entityEffectPacket.entityId = player.getEntityId(); entityEffectPacket.effect = PotionType.AWKWARD; @@ -164,6 +170,17 @@ public class PlayerDiggingListener { player.getPlayerConnection().sendPacket(entityEffectPacket); } + public static void removeEffect(Player player) { + if (playersEffect.contains(player)) { + playersEffect.remove(player); + + RemoveEntityEffectPacket removeEntityEffectPacket = new RemoveEntityEffectPacket(); + removeEntityEffectPacket.entityId = player.getEntityId(); + removeEntityEffectPacket.effect = PotionType.AWKWARD; + player.getPlayerConnection().sendPacket(removeEntityEffectPacket); + } + } + private static void sendAcknowledgePacket(Player player, BlockPosition blockPosition, int blockStateId, ClientPlayerDiggingPacket.Status status, boolean success) { AcknowledgePlayerDiggingPacket acknowledgePlayerDiggingPacket = new AcknowledgePlayerDiggingPacket();