This is basically two questions in one, so I'll split this post up into two parts.
I am trying to make a block breaking system that is almost identical to the one that Hypixel Skyblock uses, however with my current code I run into two problems.
Code:
With this code, it's supposed to take the custom breaking power and speed of the tool that you are using, and then compare that with the required breaking power and the "hardness" of the block that you are mining, while also playing the breaking animation on the block, and then also stop the mining process when it's broken (this is in the BlockDamageEvent event).
Inside of the BlockDamageAbort event it should cancel the mining process on that block if the process had existed.
However, (as I stated before) two things go wrong.
1. For the block breaking animation, I need the blockId. However,
2. The
How can I fix these bugs?
Edit: Yes, I referenced this class in my main class with this code:
I am trying to make a block breaking system that is almost identical to the one that Hypixel Skyblock uses, however with my current code I run into two problems.
Code:
package lollolcheese123.zenofgens.blocks;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.BlockPosition;
import lollolcheese123.zenofgens.items.itemInit;
import lollolcheese123.zenofgens.main;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockDamageAbortEvent;
import org.bukkit.event.block.BlockDamageEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.Random;
public class blockBreakHandler implements Listener {
private final ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager();
public HashMap<Location, Integer> blockBreakIDs = new HashMap<>();
public HashMap<Location, Integer> blockBreakStage = new HashMap<>();
public HashMap<Location, Integer> taskIDs = new HashMap<>();
public HashMap<Location, Integer> currentHardness = new HashMap<>();
@EventHandler
private void blockBreakStart(BlockDamageEvent event) {
if (event.getPlayer().getGameMode().equals(GameMode.CREATIVE))
return;
event.setCancelled(true);
// Check if the block is a custom block
if (!blockHandler.customBlockTypes.containsKey(event.getBlock().getLocation())) {
return;
}
// Set useful values
Location loc = event.getBlock().getLocation();
String blockType = blockHandler.customBlockTypes.get(loc);
ItemStack item = event.getItemInHand();
// Check if you are breaking the block with the right tool
if (!blockHandler.reqBreakingType.get(blockType).equalsIgnoreCase(itemInit.breakingType.get(item))) {
if (!event.getPlayer().getGameMode().equals(GameMode.CREATIVE)) {
event.setCancelled(true);
event.getPlayer().sendMessage("§cThis isn't the right tool!");
}
return;
}
// Check if the tool has enough breaking power
if (!(blockHandler.reqMinePower.get(blockType) <= itemInit.breakingPower.get(item))) {
if (!event.getPlayer().getGameMode().equals(GameMode.CREATIVE)) {
event.setCancelled(true);
event.getPlayer().sendMessage("§cThis tool isn't strong enough to break this block!");
event.getPlayer().sendMessage("§cYou need a breaking power of " + blockHandler.reqMinePower.get(blockType));
}
return;
}
// Register the block to be in progress of being broken
currentHardness.put(loc, blockHandler.blockHardness.get(blockType));
// Assign an EntityID for the block breaking animation
int entityID = new Random().nextInt(blockBreakIDs.size() + 1);
while (blockBreakIDs.containsValue(entityID))
entityID = new Random().nextInt(blockBreakIDs.size() + 1);
blockBreakIDs.put(loc, entityID);
// Start the breaking process
blockBreakStage.put(loc, 0);
taskIDs.put(loc, Bukkit.getScheduler().scheduleSyncRepeatingTask(main.getProvidingPlugin(main.class), () -> {
// Decrease the hardness
currentHardness.replace(loc, currentHardness.get(loc) - (itemInit.breakingSpeed.get(item) + itemInit.breakingSpeed.get(item) * (itemInit.breakingPower.get(item) - blockHandler.reqMinePower.get(blockType)) / 10));
// Update block break animation
if (currentHardness.get(loc) % (blockHandler.blockHardness.get(blockType) / 9) == 0) {
blockBreakStage.replace(loc, blockBreakStage.get(loc) + 1);
// Create the packet
PacketContainer minePacket = protocolManager.createPacket(PacketType.Play.Server.BLOCK_BREAK_ANIMATION);
minePacket.getIntegers().write(0, blockBreakIDs.get(loc));
BlockPosition blockPosition = new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
minePacket.getBlockPositionModifier().write(0, blockPosition);
minePacket.getIntegers().write(1, event.getBlock().getType().getId());
minePacket.getIntegers().write(2, blockBreakStage.get(loc));
// Send the packet
try {
protocolManager.sendServerPacket(event.getPlayer(), minePacket);
} catch (Exception e) {
e.printStackTrace();
}
}
// When block broken
if (currentHardness.get(loc) <= 0) {
event.getPlayer().getInventory().addItem(itemInit.itemDrop.get(blockType));
event.getBlock().setType(Material.AIR);
Bukkit.getScheduler().cancelTask(taskIDs.get(loc));
// Delete block breaking values
taskIDs.remove(loc);
currentHardness.remove(loc);
blockBreakIDs.remove(loc);
blockBreakStage.remove(loc);
}
}, 1, 1));
}
@EventHandler
private void blockBreakStop(BlockDamageAbortEvent event) {
// Check if the block has an EntityID
if (!blockBreakIDs.containsKey(event.getBlock().getLocation()))
return;
// Set useful values
Block block = event.getBlock();
Location loc = block.getLocation();
int breakerID = blockBreakIDs.get(loc);
BlockPosition blockPosition = new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
// Create the packet
PacketContainer minePacket = protocolManager.createPacket(PacketType.Play.Server.BLOCK_BREAK_ANIMATION);
minePacket.getIntegers().write(0, breakerID);
minePacket.getBlockPositionModifier().write(0, blockPosition);
minePacket.getIntegers().write(1, block.getType().getId());
minePacket.getIntegers().write(2, 0);
// Cancel the block breaking
Bukkit.getScheduler().cancelTask(taskIDs.get(loc));
// Send the packet
try {
protocolManager.sendServerPacket(event.getPlayer(), minePacket);
} catch (Exception e) {
e.printStackTrace();
}
// Delete block breaking values
taskIDs.remove(loc);
currentHardness.remove(loc);
blockBreakIDs.remove(loc);
blockBreakStage.remove(loc);
}
@EventHandler
private void blockBroken(BlockBreakEvent event) {
if (!event.getPlayer().getGameMode().equals(GameMode.CREATIVE))
event.setCancelled(true);
}
@EventHandler
private void blockPlaced(BlockPlaceEvent event) {
if (!event.getPlayer().getGameMode().equals(GameMode.CREATIVE))
event.setCancelled(true);
}
}
With this code, it's supposed to take the custom breaking power and speed of the tool that you are using, and then compare that with the required breaking power and the "hardness" of the block that you are mining, while also playing the breaking animation on the block, and then also stop the mining process when it's broken (this is in the BlockDamageEvent event).
Inside of the BlockDamageAbort event it should cancel the mining process on that block if the process had existed.
However, (as I stated before) two things go wrong.
1. For the block breaking animation, I need the blockId. However,
block.getType().getId()
doesn't work on modern materials, and I'll get an error message telling me so.2. The
Bukkit.getScheduler().cancelTask(taskIDs.get(loc));
code never actually cancels the scheduledSyncRepeatingTask that I created.How can I fix these bugs?
Edit: Yes, I referenced this class in my main class with this code:
Bukkit.getServer().getPluginManager().registerEvents(new blockBreakHandler(), this);