Allow non-custom block in PlayerStartDiggingEvent

This commit is contained in:
themode 2020-10-10 13:46:41 +02:00
parent 98ac2d9717
commit 739c3f1d7d
5 changed files with 80 additions and 40 deletions

View File

@ -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);
}
}

View File

@ -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
* <p>
* 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;
}
}

View File

@ -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<SharedInstance> 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<Long, Chunk> chunks = new ConcurrentHashMap<>();
// contains all the chunks to remove during the next instance tick
protected final Set<Chunk> scheduledChunksToRemove = new HashSet<>();
private ReadWriteLock changingBlockLock = new ReentrantReadWriteLock();
private Map<BlockPosition, Block> 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)

View File

@ -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<Player> viewers = new CopyOnWriteArraySet<>();
// (player -> cursor item) map, used by the click listeners
private final ConcurrentHashMap<Player, ItemStack> cursorPlayersItem = new ConcurrentHashMap<>();
// list of conditions/callbacks assigned to this inventory
private final List<InventoryCondition> 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;

View File

@ -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<Player> 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();