From 0ebfda6ab139b0f6887fff7e60efc6c0eecbc537 Mon Sep 17 00:00:00 2001 From: totemo Date: Mon, 13 Jun 2016 12:31:37 +0930 Subject: [PATCH] Suppress ender crystal drops in a radius around the end portal (end side) to prevent their recovery when the dragon has already started spawning. --- config.yml | 10 +++++ pom.xml | 3 +- src/nu/nerd/safecrystals/Configuration.java | 30 +++++++++++++ src/nu/nerd/safecrystals/SafeCrystals.java | 47 ++++++++++++++++++++- 4 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 config.yml create mode 100644 src/nu/nerd/safecrystals/Configuration.java diff --git a/config.yml b/config.yml new file mode 100644 index 0000000..a1b4489 --- /dev/null +++ b/config.yml @@ -0,0 +1,10 @@ +end-portal: + radius: 7.0 + location: + ==: org.bukkit.Location + world: world_the_end + x: 0.0 + y: 62.0 + z: 0.0 + pitch: 0.0 + yaw: 0.0 diff --git a/pom.xml b/pom.xml index 0323d90..b002e68 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ nu.nerd SafeCrystals ${project.name} - 0.1.0 + 1.0.0 jar Prevent Ender Crystals from exploding and breaking blocks or damaging entities. https://github.com/totemo/${project.name} @@ -48,6 +48,7 @@ ${basedir} plugin.yml + config.yml diff --git a/src/nu/nerd/safecrystals/Configuration.java b/src/nu/nerd/safecrystals/Configuration.java new file mode 100644 index 0000000..fee0c78 --- /dev/null +++ b/src/nu/nerd/safecrystals/Configuration.java @@ -0,0 +1,30 @@ +package nu.nerd.safecrystals; + +import org.bukkit.Location; + +// ---------------------------------------------------------------------------- +/** + * Configuration wrapper. + */ +public class Configuration { + /** + * Radius around END_PORTAL_LOCATION where broken ender crystals don't drop. + */ + public double END_PORTAL_RADIUS; + + /** + * Location of the (assumed only) end-side end portal. + */ + public Location END_PORTAL_LOCATION; + + // ------------------------------------------------------------------------ + /** + * Reload the configuration. + */ + public void reload() { + SafeCrystals.PLUGIN.reloadConfig(); + + END_PORTAL_RADIUS = SafeCrystals.PLUGIN.getConfig().getDouble("end-portal.radius"); + END_PORTAL_LOCATION = (Location) SafeCrystals.PLUGIN.getConfig().get("end-portal.location"); + } +} // class Configuration \ No newline at end of file diff --git a/src/nu/nerd/safecrystals/SafeCrystals.java b/src/nu/nerd/safecrystals/SafeCrystals.java index 64a952b..9f5e06d 100644 --- a/src/nu/nerd/safecrystals/SafeCrystals.java +++ b/src/nu/nerd/safecrystals/SafeCrystals.java @@ -32,6 +32,15 @@ * Ender Crystal in a region. */ public class SafeCrystals extends JavaPlugin implements Listener { + /** + * Singleton-like reference to this plugin. + */ + public static SafeCrystals PLUGIN; + + /** + * Configuration instance. + */ + public static Configuration CONFIG = new Configuration(); // ------------------------------------------------------------------------ /** @@ -39,6 +48,10 @@ public class SafeCrystals extends JavaPlugin implements Listener { */ @Override public void onEnable() { + PLUGIN = this; + saveDefaultConfig(); + CONFIG.reload(); + _worldGuard = (WorldGuardPlugin) getServer().getPluginManager().getPlugin("WorldGuard"); Bukkit.getPluginManager().registerEvents(this, this); } @@ -110,13 +123,43 @@ protected void tryBreakEnderCrystal(Entity crystal, Player player) { Location loc = crystal.getLocation(); if (_worldGuard.canBuild(player, loc)) { crystal.remove(); - loc.getWorld().dropItemNaturally(loc, new ItemStack(Material.END_CRYSTAL)); + String suppressed; + if (isDragonSpawningCrystal(loc)) { + suppressed = " - drop suppressed because dragon may spawn"; + } else { + loc.getWorld().dropItemNaturally(loc, new ItemStack(Material.END_CRYSTAL)); + suppressed = ""; + } getLogger().info(player.getName() + " broke an Ender Crystal at " + loc.getWorld().getName() + ", " + - loc.getBlockX() + ", " + loc.getBlockY() + ", " + loc.getBlockZ()); + loc.getBlockX() + ", " + loc.getBlockY() + ", " + loc.getBlockZ() + suppressed); } } + // ------------------------------------------------------------------------ + /** + * Return true if the crystal is in a position that can be used to summon + * the dragon. + * + * When summoning the dragon, players can break the crystals on the frame + * before the dragon CreatureSpawnEvent (reason DEFAULT) occurs, and + * potentially recover them, if they don't burn up in the fire underneath. + * This method is used to detect that situation and prevent recovery of the + * crystals. + * + * Getting delicate about the exact coordinates of the crystal won't work + * because a determined player will move the crystals with pistons + * (verified). Any crystals too close to the portal would normally be blown + * up by the explosion when the dragon spawns, anyway. + * + * @param loc the location of the crystal. + * @return true if the crystal is in a position that can be used to summon + * the dragon. + */ + protected boolean isDragonSpawningCrystal(Location loc) { + return (loc.distance(CONFIG.END_PORTAL_LOCATION) < CONFIG.END_PORTAL_RADIUS); + } + // ------------------------------------------------------------------------ /** * Reference to WorldGuard.