diff --git a/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java b/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java index 03c4a4799..027a53ee6 100644 --- a/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java @@ -37,7 +37,7 @@ import com.gmail.nossr50.party.Party; import com.gmail.nossr50.runnables.BleedTimer; import com.gmail.nossr50.skills.gathering.Fishing; import com.gmail.nossr50.skills.gathering.Herbalism; -import com.gmail.nossr50.skills.mining.BlastMining; +import com.gmail.nossr50.skills.mining.MiningManager; import com.gmail.nossr50.skills.repair.Salvage; import com.gmail.nossr50.skills.taming.TamingManager; import com.gmail.nossr50.util.BlockChecks; @@ -364,7 +364,8 @@ public class PlayerListener implements Listener { /* BLAST MINING CHECK */ if (player.isSneaking() && inHand.getTypeId() == Config.getInstance().getDetonatorItemID() && Permissions.blastMining(player)) { - BlastMining.detonate(event, player, plugin); + MiningManager miningManager = new MiningManager(player); + miningManager.detonate(event); } break; @@ -387,7 +388,8 @@ public class PlayerListener implements Listener { /* BLAST MINING CHECK */ if (player.isSneaking() && inHand.getTypeId() == Config.getInstance().getDetonatorItemID() && Permissions.blastMining(player)) { - BlastMining.detonate(event, player, plugin); + MiningManager miningManager = new MiningManager(player); + miningManager.detonate(event); } break; diff --git a/src/main/java/com/gmail/nossr50/skills/mining/BlastMining.java b/src/main/java/com/gmail/nossr50/skills/mining/BlastMining.java index 8c372c278..0f6ea5b92 100644 --- a/src/main/java/com/gmail/nossr50/skills/mining/BlastMining.java +++ b/src/main/java/com/gmail/nossr50/skills/mining/BlastMining.java @@ -1,24 +1,8 @@ package com.gmail.nossr50.skills.mining; -import java.util.HashSet; import java.util.Random; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.entity.Player; -import org.bukkit.entity.TNTPrimed; -import org.bukkit.event.player.PlayerInteractEvent; - -import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.config.AdvancedConfig; -import com.gmail.nossr50.datatypes.AbilityType; -import com.gmail.nossr50.datatypes.PlayerProfile; -import com.gmail.nossr50.datatypes.SkillType; -import com.gmail.nossr50.locale.LocaleLoader; -import com.gmail.nossr50.util.Misc; -import com.gmail.nossr50.util.Skills; -import com.gmail.nossr50.util.Users; public class BlastMining { private static AdvancedConfig advancedConfig = AdvancedConfig.getInstance(); @@ -33,81 +17,7 @@ public class BlastMining { public final static int BLAST_MINING_RANK_7 = advancedConfig.getBlastMiningRank7(); public final static int BLAST_MINING_RANK_8 = advancedConfig.getBlastMiningRank8(); - /** - * Detonate TNT for Blast Mining - * - * @param event The PlayerInteractEvent - * @param player Player detonating the TNT - * @param plugin mcMMO plugin instance - */ - public static void detonate(PlayerInteractEvent event, Player player, mcMMO plugin) { - if(player == null) - return; - - PlayerProfile profile = Users.getProfile(player); - - if (profile.getSkillLevel(SkillType.MINING) < 125) - return; - - Block block = event.getClickedBlock(); - - if (block == null || block.getType() != Material.TNT) { - final byte SNOW = 78; - final byte AIR = 0; - final int BLOCKS_AWAY = 100; - - HashSet transparent = new HashSet(); - - transparent.add(SNOW); - transparent.add(AIR); - - block = player.getTargetBlock(transparent, BLOCKS_AWAY); - - if (block.getType() != Material.TNT) { - return; - } - } - else if (block.getType() == Material.TNT) { - event.setCancelled(true); // This is the only way I know to avoid the original TNT to be triggered (in case the player is close to it) - } - - if (!Misc.blockBreakSimulate(block, player, true)) { - return; - } - - final double MAX_DISTANCE_AWAY = 10.0; - final int TIME_CONVERSION_FACTOR = 1000; - - AbilityType ability = AbilityType.BLAST_MINING; - - /* Check Cooldown */ - if (!Skills.cooldownOver(profile.getSkillDATS(ability) * TIME_CONVERSION_FACTOR, ability.getCooldown(), player)) { - player.sendMessage(LocaleLoader.getString("Skills.TooTired") + ChatColor.YELLOW + " (" + Skills.calculateTimeLeft(profile.getSkillDATS(ability) * TIME_CONVERSION_FACTOR, ability.getCooldown(), player) + "s)"); - - return; - } - - /* Send message to nearby players */ - for (Player y : player.getWorld().getPlayers()) { - if (y != player && Misc.isNear(player.getLocation(), y.getLocation(), MAX_DISTANCE_AWAY)) { - y.sendMessage(ability.getAbilityPlayer(player)); - } - } - - player.sendMessage(LocaleLoader.getString("Mining.Blast.Boom")); - - /* Create the TNT entity */ - // TNTPrimed tnt = (TNTPrimed) player.getWorld().spawnEntity(block.getLocation(), EntityType.PRIMED_TNT); - TNTPrimed tnt = player.getWorld().spawn(block.getLocation(), TNTPrimed.class); - plugin.addToTNTTracker(tnt.getEntityId(), player.getName()); - tnt.setFuseTicks(0); - - /* Disable the original one */ - block.setType(Material.AIR); - - profile.setSkillDATS(ability, System.currentTimeMillis()); //Save DATS for Blast Mining - profile.setAbilityInformed(ability, false); - } + public final static int MAXIMUM_REMOTE_DETONATION_DISTANCE = 100; protected static Random getRandom() { return random; diff --git a/src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java b/src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java index 68539882e..fadecb85c 100644 --- a/src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java +++ b/src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java @@ -1,10 +1,12 @@ package com.gmail.nossr50.skills.mining; +import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.event.entity.ExplosionPrimeEvent; +import org.bukkit.event.player.PlayerInteractEvent; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.datatypes.PlayerProfile; @@ -25,6 +27,42 @@ public class MiningManager { this.skillLevel = profile.getSkillLevel(SkillType.MINING); } + /** + * Detonate TNT for Blast Mining + * + * @param event The PlayerInteractEvent + * @param player Player detonating the TNT + * @param plugin mcMMO plugin instance + */ + public void detonate(PlayerInteractEvent event) { + if (Misc.isCitizensNPC(player)) { + return; + } + + if (skillLevel < BlastMining.BLAST_MINING_RANK_1) { + return; + } + + RemoteDetonationEventHandler eventHandler = new RemoteDetonationEventHandler(this, event); + + eventHandler.targetTNT(); + + if (eventHandler.block.getType() != Material.TNT) { + return; + } + + if (!Misc.blockBreakSimulate(eventHandler.block, player, true)) { + return; + } + + if (!eventHandler.cooldownOver()) { + return; + } + + eventHandler.sendMessages(); + eventHandler.handleDetonation(); + eventHandler.setProfileData(); + } /** * Handler for explosion drops and XP gain. diff --git a/src/main/java/com/gmail/nossr50/skills/mining/RemoteDetonationEventHandler.java b/src/main/java/com/gmail/nossr50/skills/mining/RemoteDetonationEventHandler.java new file mode 100644 index 000000000..bde7f900a --- /dev/null +++ b/src/main/java/com/gmail/nossr50/skills/mining/RemoteDetonationEventHandler.java @@ -0,0 +1,115 @@ +package com.gmail.nossr50.skills.mining; + +import java.util.HashSet; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.entity.TNTPrimed; +import org.bukkit.event.player.PlayerInteractEvent; + +import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.datatypes.AbilityType; +import com.gmail.nossr50.datatypes.PlayerProfile; +import com.gmail.nossr50.locale.LocaleLoader; +import com.gmail.nossr50.util.Misc; +import com.gmail.nossr50.util.Skills; + +public class RemoteDetonationEventHandler { + private Player player; + private PlayerProfile profile; + + private PlayerInteractEvent event; + protected Block block; + + private HashSet transparentBlocks = new HashSet(); + + public RemoteDetonationEventHandler(MiningManager manager, PlayerInteractEvent event) { + this.player = manager.getPlayer(); + this.profile = manager.getProfile(); + + this.event = event; + this.block = event.getClickedBlock(); + } + + protected void targetTNT() { + if (block == null || block.getType() != Material.TNT) { + generateTransparentBlockList(); + block = player.getTargetBlock(transparentBlocks, BlastMining.MAXIMUM_REMOTE_DETONATION_DISTANCE); + } + else { + event.setCancelled(true); // This is the only way I know to avoid the original TNT to be triggered (in case the player is close to it) + } + } + + protected boolean cooldownOver() { + if (!Skills.cooldownOver(profile.getSkillDATS(AbilityType.BLAST_MINING) * Misc.TIME_CONVERSION_FACTOR, AbilityType.BLAST_MINING.getCooldown(), player)) { + player.sendMessage(LocaleLoader.getString("Skills.TooTired") + ChatColor.YELLOW + " (" + Skills.calculateTimeLeft(profile.getSkillDATS(AbilityType.BLAST_MINING) * Misc.TIME_CONVERSION_FACTOR, AbilityType.BLAST_MINING.getCooldown(), player) + "s)"); + + return false; + } + + return true; + } + + protected void sendMessages() { + Misc.sendSkillMessage(player, AbilityType.BLAST_MINING.getAbilityPlayer(player)); + player.sendMessage(LocaleLoader.getString("Mining.Blast.Boom")); + } + + protected void handleDetonation() { + TNTPrimed tnt = player.getWorld().spawn(block.getLocation(), TNTPrimed.class); + mcMMO.p.addToTNTTracker(tnt.getEntityId(), player.getName()); + tnt.setFuseTicks(0); + + block.setType(Material.AIR); + } + + protected void setProfileData() { + profile.setSkillDATS(AbilityType.BLAST_MINING, System.currentTimeMillis()); + profile.setAbilityInformed(AbilityType.BLAST_MINING, false); + } + + private void generateTransparentBlockList() { + transparentBlocks.add((byte) Material.AIR.getId()); + transparentBlocks.add((byte) Material.SAPLING.getId()); + transparentBlocks.add((byte) Material.POWERED_RAIL.getId()); + transparentBlocks.add((byte) Material.DETECTOR_RAIL.getId()); + transparentBlocks.add((byte) Material.LONG_GRASS.getId()); + transparentBlocks.add((byte) Material.DEAD_BUSH.getId()); + transparentBlocks.add((byte) Material.YELLOW_FLOWER.getId()); + transparentBlocks.add((byte) Material.RED_ROSE.getId()); + transparentBlocks.add((byte) Material.BROWN_MUSHROOM.getId()); + transparentBlocks.add((byte) Material.RED_MUSHROOM.getId()); + transparentBlocks.add((byte) Material.TORCH.getId()); + transparentBlocks.add((byte) Material.FIRE.getId()); + transparentBlocks.add((byte) Material.REDSTONE_WIRE.getId()); + transparentBlocks.add((byte) Material.CROPS.getId()); + transparentBlocks.add((byte) Material.LADDER.getId()); + transparentBlocks.add((byte) Material.RAILS.getId()); + transparentBlocks.add((byte) Material.LEVER.getId()); + transparentBlocks.add((byte) Material.REDSTONE_TORCH_OFF.getId()); + transparentBlocks.add((byte) Material.REDSTONE_TORCH_ON.getId()); + transparentBlocks.add((byte) Material.STONE_BUTTON.getId()); + transparentBlocks.add((byte) Material.SNOW.getId()); + transparentBlocks.add((byte) Material.SUGAR_CANE_BLOCK.getId()); + transparentBlocks.add((byte) Material.PORTAL.getId()); + transparentBlocks.add((byte) Material.DIODE_BLOCK_OFF.getId()); + transparentBlocks.add((byte) Material.DIODE_BLOCK_ON.getId()); + transparentBlocks.add((byte) Material.PUMPKIN_STEM.getId()); + transparentBlocks.add((byte) Material.MELON_STEM.getId()); + transparentBlocks.add((byte) Material.VINE.getId()); + transparentBlocks.add((byte) Material.WATER_LILY.getId()); + transparentBlocks.add((byte) Material.NETHER_WARTS.getId()); + transparentBlocks.add((byte) Material.ENDER_PORTAL.getId()); + transparentBlocks.add((byte) Material.COCOA.getId()); + transparentBlocks.add((byte) Material.TRIPWIRE_HOOK.getId()); + transparentBlocks.add((byte) Material.TRIPWIRE.getId()); + transparentBlocks.add((byte) Material.FLOWER_POT.getId()); + transparentBlocks.add((byte) Material.CARROT.getId()); + transparentBlocks.add((byte) Material.POTATO.getId()); + transparentBlocks.add((byte) Material.WOOD_BUTTON.getId()); + transparentBlocks.add((byte) Material.SKULL.getId()); + } +} diff --git a/src/main/java/com/gmail/nossr50/util/Misc.java b/src/main/java/com/gmail/nossr50/util/Misc.java index 3bd6bb497..3ffab68b3 100644 --- a/src/main/java/com/gmail/nossr50/util/Misc.java +++ b/src/main/java/com/gmail/nossr50/util/Misc.java @@ -24,6 +24,8 @@ public class Misc { public static final int TOOL_DURABILITY_LOSS = Config.getInstance().getAbilityToolDamage(); public static final int PLAYER_RESPAWN_COOLDOWN_SECONDS = 5; + public static final int TIME_CONVERSION_FACTOR = 1000; + public static final double SKILL_MESSAGE_MAX_SENDING_DISTANCE = 10.0; public static boolean isCitizensNPC(Player player) { if (player == null || Users.getProfile(player) == null || player.hasMetadata("NPC")) { @@ -33,6 +35,14 @@ public class Misc { return false; } + public static void sendSkillMessage(Player player, String message) { + for (Player otherPlayer : player.getWorld().getPlayers()) { + if (otherPlayer != player && Misc.isNear(player.getLocation(), otherPlayer.getLocation(), Misc.SKILL_MESSAGE_MAX_SENDING_DISTANCE)) { + otherPlayer.sendMessage(message); + } + } + } + /** * Gets a capitalized version of the target string. *