I have made a plugin that allows me to configure the mining speed of blocks by simulating the block breaking animation whilst preventing the player from mining the block, however I need a way to make the player mine the block after the block breaking animation has finished. I don't mean to break the block naturally or call the event after the block is broken, I mean to make EVERYTHING be as if the player has broken the block. Particles, events, packets, everything. Any help? (I need everything for additional plugins I am creating in the future which require that compatibility) Also any additional suggestions to my code would be greatly appreciated! Code: Code: package me.BaddCamden.MainSkyblock; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.logging.Logger; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockDamageEvent; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import org.bukkit.scheduler.BukkitScheduler; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.ProtocolManager; import com.comphenix.protocol.events.ListenerPriority; import com.comphenix.protocol.events.PacketAdapter; import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.events.PacketEvent; import com.comphenix.protocol.wrappers.EnumWrappers; import com.comphenix.protocol.wrappers.EnumWrappers.PlayerDigType; import net.minecraft.server.v1_16_R3.PacketPlayInBlockDig; import net.minecraft.server.v1_16_R3.BlockPosition; import net.minecraft.server.v1_16_R3.Packet; import net.minecraft.server.v1_16_R3.PacketPlayOutBlockBreakAnimation; public class MiningSpeed implements Listener{ //Configure this code to change speeds which blocks are mined! I will later add this to the config... ArrayList<Material> configurableBlocks = new ArrayList<Material>(Arrays.asList(Material.DIRT,Material.GRASS_BLOCK,Material.OAK_LOG,Material.STONE,Material.BIRCH_LOG,Material.SPRUCE_LOG,Material.ACACIA_LOG,Material.JUNGLE_LOG,Material.DARK_OAK_LOG)); ArrayList<Integer> configurableBreakTime = new ArrayList<Integer>(Arrays.asList(60, 90, 600, 500, 60, 90, 120, 60, 150)); //Arrays that tell whether a player is mining a block ArrayList<Player> playerMiningBlock = new ArrayList<Player>(); ArrayList<Block> blockBeingMined = new ArrayList<Block>(); Logger onLog = Bukkit.getLogger(); private ProtocolManager protocolManager; Main mainPlugin; public MiningSpeed(Main main) { mainPlugin = main; protocolManager = ProtocolLibrary.getProtocolManager(); interceptPackets(); } private void interceptPackets(){ onLog.info("as"); protocolManager.addPacketListener(new PacketAdapter(mainPlugin, ListenerPriority.NORMAL, PacketType.Play.Client.BLOCK_DIG) { @Override public void onPacketReceiving(PacketEvent event){ PacketContainer packet = event.getPacket(); EnumWrappers.PlayerDigType digType = packet.getPlayerDigTypes().getValues().get(0); System.out.println("DigType: "+digType.name()); if(digType.equals(PlayerDigType.START_DESTROY_BLOCK)) { playerMiningBlock.add(event.getPlayer()); blockBeingMined.add(null); } else { for(int i = 0; i < playerMiningBlock.size(); i++) { if(playerMiningBlock.get(i) == event.getPlayer()) { playerMiningBlock.remove(i); blockBeingMined.remove(i); break; } } } } }); } @EventHandler public void OnBlockHit(BlockDamageEvent event) { for(int i = 0; i < playerMiningBlock.size(); i++) { if(playerMiningBlock.get(i) == event.getPlayer()) { playerMiningBlock.remove(i); blockBeingMined.remove(i); break; } } if(!event.getInstaBreak()) { playerMiningBlock.add(event.getPlayer()); blockBeingMined.add(event.getBlock()); for(int i = 0; i < configurableBlocks.size(); i++) { if(event.getBlock().getType().equals(configurableBlocks.get(i))) { MiningBlock(event, i); } } } } public void MiningBlock(BlockDamageEvent event, int i) { CraftPlayer p = (CraftPlayer) event.getPlayer(); for(int a = 0; a < playerMiningBlock.size(); a++) { if(playerMiningBlock.get(a) == event.getPlayer()) { ((Player)p).addPotionEffect(new PotionEffect(PotionEffectType.SLOW_DIGGING, 1000, 100, true)); blockBreakingStages(event, p, i, 0, blockBeingMined.get(a)); } } } public void SendPacket(CraftPlayer p, Packet packet) { try { Field field = packet.getClass().getDeclaredField("a"); field.setAccessible(true);// allows us to access the field field.setInt(packet, 123);// sets the field to an integer field.setAccessible(!field.isAccessible());//we want to stop accessing this now } catch(Exception x) { x.printStackTrace(); } p.getHandle().playerConnection.sendPacket(packet); } public void blockBreakingStages(BlockDamageEvent event, CraftPlayer p, int a, int stage, Block block) { int temporaryBreakTime = ((Integer)configurableBreakTime.get(a) / 9); onLog.info(""+temporaryBreakTime); BukkitScheduler scheduler = mainPlugin.getServer().getScheduler(); scheduler.scheduleSyncDelayedTask(mainPlugin, new Runnable() { public void run() { boolean foundPlayer = false; for(int i = 0; i < playerMiningBlock.size(); i++) { if(playerMiningBlock.get(i) == event.getPlayer() ) { foundPlayer = true; if(blockBeingMined.get(i) == block) { onLog.info("It works, yes inded, please sand halp"); PacketPlayOutBlockBreakAnimation packet = new PacketPlayOutBlockBreakAnimation(event.getPlayer().getEntityId(), new BlockPosition(event.getBlock().getX(), event.getBlock().getY(), event.getBlock().getZ()), stage); SendPacket(p, packet); if(stage < 9) { blockBreakingStages(event, p, a, stage + 1, block); onLog.info("WHY"); } else { PacketPlayInBlockDig packetBreak = new PacketPlayInBlockDig(); mainPlugin.getServer().getPluginManager().callEvent(new BlockBreakEvent((Block) event.getBlock(), event.getPlayer())); //This is where I need your help event.getBlock().breakNaturally(event.getPlayer().getItemInHand()); //This is where I need your help if(p.hasPotionEffect(PotionEffectType.SLOW_DIGGING)) { p.removePotionEffect(PotionEffectType.SLOW_DIGGING); } } } break; } } if(p.hasPotionEffect(PotionEffectType.SLOW_DIGGING) && !foundPlayer) { p.removePotionEffect(PotionEffectType.SLOW_DIGGING); } } }, temporaryBreakTime); } } Just so you don't have to read ALL of that code, here is just my code that I need help with: Code: public void blockBreakingStages(BlockDamageEvent event, CraftPlayer p, int a, int stage, Block block) { int temporaryBreakTime = ((Integer)configurableBreakTime.get(a) / 9); onLog.info(""+temporaryBreakTime); BukkitScheduler scheduler = mainPlugin.getServer().getScheduler(); scheduler.scheduleSyncDelayedTask(mainPlugin, new Runnable() { public void run() { boolean foundPlayer = false; for(int i = 0; i < playerMiningBlock.size(); i++) { if(playerMiningBlock.get(i) == event.getPlayer() ) { foundPlayer = true; if(blockBeingMined.get(i) == block) { onLog.info("It works, yes inded, please sand halp"); PacketPlayOutBlockBreakAnimation packet = new PacketPlayOutBlockBreakAnimation(event.getPlayer().getEntityId(), new BlockPosition(event.getBlock().getX(), event.getBlock().getY(), event.getBlock().getZ()), stage); SendPacket(p, packet); if(stage < 9) { blockBreakingStages(event, p, a, stage + 1, block); onLog.info("WHY"); } else { PacketPlayInBlockDig packetBreak = new PacketPlayInBlockDig(); mainPlugin.getServer().getPluginManager().callEvent(new BlockBreakEvent((Block) event.getBlock(), event.getPlayer())); event.getBlock().breakNaturally(event.getPlayer().getItemInHand()); if(p.hasPotionEffect(PotionEffectType.SLOW_DIGGING)) { p.removePotionEffect(PotionEffectType.SLOW_DIGGING); } } } break; } } if(p.hasPotionEffect(PotionEffectType.SLOW_DIGGING) && !foundPlayer) { p.removePotionEffect(PotionEffectType.SLOW_DIGGING); } } }, temporaryBreakTime); } EDIT by Moderator: merged posts, please use the edit button instead of double posting.
I do not understand whether you are asking for help about detecting when the block has been broken or not? You can call Bukkit events using PluginManager#callEvent(Event). Also, I noticed that you are not following the Java naming conventions.
Yes, I want to be able to detect whether the player has broken the block, however I explicitly need that the block be broken as if the player did it. I have already assigned an event to be called whenever the block is broken for debugging and for some compatibility. Also when you say I am not following the Java Naming Conventions, I am assuming you mean that my variables are not named properly. I agree, however I will say that I have too specific scenarios for my variables to be any shorter. I usually try to make it at most 3 words per variable. Also when a variable is abbreviated, a majority of the time I don't know what it is, unless it is i (index/integer) or something universal like that