From 1320215c3f92a1d6960632e99d039c1fc06dca15 Mon Sep 17 00:00:00 2001 From: Roy Curtis Date: Mon, 18 May 2015 12:18:36 +0100 Subject: [PATCH] Proposed & implemented feature: prevent mob spawns outside of border, including: - command `/we preventmobspawn` - permission `worldborder.preventmobspawn` - MobSpawnListener for cancelling spawns outside border Changes outside of scope: - prevent potential NPEs whilst disabling already-disabled preventblockplace and preventmobspawn - added intelliJ IDE files to gitignore --- .gitignore | 2 + .../java/com/wimbli/WorldBorder/Config.java | 15 +++++++ .../wimbli/WorldBorder/MobSpawnListener.java | 35 +++++++++++++++ .../com/wimbli/WorldBorder/WBCommand.java | 3 +- .../com/wimbli/WorldBorder/WorldBorder.java | 19 +++++++- .../WorldBorder/cmd/CmdPreventSpawn.java | 44 +++++++++++++++++++ src/main/resources/plugin.yml | 5 +++ 7 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/wimbli/WorldBorder/MobSpawnListener.java create mode 100644 src/main/java/com/wimbli/WorldBorder/cmd/CmdPreventSpawn.java diff --git a/.gitignore b/.gitignore index dc0d833..bdcf9f4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ target/ +.idea/ +*.iml diff --git a/src/main/java/com/wimbli/WorldBorder/Config.java b/src/main/java/com/wimbli/WorldBorder/Config.java index 5a6216a..ed3f047 100644 --- a/src/main/java/com/wimbli/WorldBorder/Config.java +++ b/src/main/java/com/wimbli/WorldBorder/Config.java @@ -55,6 +55,7 @@ public class Config private static int fillAutosaveFrequency = 30; private static int fillMemoryTolerance = 500; private static boolean preventBlockPlace = false; + private static boolean preventMobSpawn = false; // for monitoring plugin efficiency // public static long timeUsed = 0; @@ -268,11 +269,23 @@ public class Config save(true); } + public static void setPreventMobSpawn(boolean enable) + { + preventMobSpawn = enable; + log("prevent mob spawn " + (enable ? "enabled" : "disabled") + "."); + save(true); + } + public static boolean preventBlockPlace() { return preventBlockPlace; } + public static boolean preventMobSpawn() + { + return preventMobSpawn; + } + public static boolean getIfPlayerKill() { return killPlayer; @@ -580,6 +593,7 @@ public class Config importBypassStringList(cfg.getStringList("bypass-list-uuids")); fillMemoryTolerance = cfg.getInt("fill-memory-tolerance", 500); preventBlockPlace = cfg.getBoolean("prevent-block-place"); + preventMobSpawn = cfg.getBoolean("prevent-mob-spawn"); StartBorderTimer(); @@ -687,6 +701,7 @@ public class Config cfg.set("bypass-list-uuids", exportBypassStringList()); cfg.set("fill-memory-tolerance", fillMemoryTolerance); cfg.set("prevent-block-place", preventBlockPlace); + cfg.set("prevent-mob-spawn", preventMobSpawn); cfg.set("worlds", null); for(Entry stringBorderDataEntry : borders.entrySet()) diff --git a/src/main/java/com/wimbli/WorldBorder/MobSpawnListener.java b/src/main/java/com/wimbli/WorldBorder/MobSpawnListener.java new file mode 100644 index 0000000..43ae846 --- /dev/null +++ b/src/main/java/com/wimbli/WorldBorder/MobSpawnListener.java @@ -0,0 +1,35 @@ +package com.wimbli.WorldBorder; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.CreatureSpawnEvent; + + +public class MobSpawnListener implements Listener +{ + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onCreatureSpawn(CreatureSpawnEvent event) + { + Location loc = event.getEntity().getLocation(); + if (loc == null) return; + + World world = loc.getWorld(); + if (world == null) return; + BorderData border = Config.Border(world.getName()); + if (border == null) return; + + if (!border.insideBorder(loc.getX(), loc.getZ(), Config.ShapeRound())) + { + event.setCancelled(true); + } + } + + public void unregister() + { + HandlerList.unregisterAll(this); + } +} diff --git a/src/main/java/com/wimbli/WorldBorder/WBCommand.java b/src/main/java/com/wimbli/WorldBorder/WBCommand.java index 57ad7e1..c004b62 100644 --- a/src/main/java/com/wimbli/WorldBorder/WBCommand.java +++ b/src/main/java/com/wimbli/WorldBorder/WBCommand.java @@ -47,14 +47,15 @@ public class WBCommand implements CommandExecutor addCmd(new CmdWshape()); // 3 //----- addCmd(new CmdPreventPlace()); // 1 + addCmd(new CmdPreventSpawn()); // 1 addCmd(new CmdDelay()); // 1 addCmd(new CmdDynmap()); // 1 addCmd(new CmdDynmapmsg()); // 1 addCmd(new CmdRemount()); // 1 addCmd(new CmdFillautosave()); // 1 addCmd(new CmdPortal()); // 1 - addCmd(new CmdDenypearl()); // 1 //----- + addCmd(new CmdDenypearl()); // 1 addCmd(new CmdReload()); // 1 addCmd(new CmdDebug()); // 1 diff --git a/src/main/java/com/wimbli/WorldBorder/WorldBorder.java b/src/main/java/com/wimbli/WorldBorder/WorldBorder.java index 3e63da4..39b9c47 100644 --- a/src/main/java/com/wimbli/WorldBorder/WorldBorder.java +++ b/src/main/java/com/wimbli/WorldBorder/WorldBorder.java @@ -9,6 +9,7 @@ public class WorldBorder extends JavaPlugin public static volatile WorldBorder plugin = null; public static volatile WBCommand wbCommand = null; private BlockPlaceListener blockPlaceListener = null; + private MobSpawnListener mobSpawnListener = null; @Override public void onEnable() @@ -32,6 +33,11 @@ public class WorldBorder extends JavaPlugin enableBlockPlaceListener(true); } + if (Config.preventMobSpawn()) + { + enableMobSpawnListener(true); + } + // integrate with DynMap if it's available DynMapFeatures.setup(); @@ -69,9 +75,20 @@ public class WorldBorder extends JavaPlugin { getServer().getPluginManager().registerEvents(this.blockPlaceListener = new BlockPlaceListener(), this); } - else + else if (blockPlaceListener != null) { blockPlaceListener.unregister(); } } + + public void enableMobSpawnListener(boolean enable) { + if (enable) + { + getServer().getPluginManager().registerEvents(this.mobSpawnListener = new MobSpawnListener(), this); + } + else if (mobSpawnListener != null) + { + mobSpawnListener.unregister(); + } + } } diff --git a/src/main/java/com/wimbli/WorldBorder/cmd/CmdPreventSpawn.java b/src/main/java/com/wimbli/WorldBorder/cmd/CmdPreventSpawn.java new file mode 100644 index 0000000..953f4ac --- /dev/null +++ b/src/main/java/com/wimbli/WorldBorder/cmd/CmdPreventSpawn.java @@ -0,0 +1,44 @@ +package com.wimbli.WorldBorder.cmd; + +import com.wimbli.WorldBorder.Config; +import com.wimbli.WorldBorder.WorldBorder; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.List; + +public class CmdPreventSpawn extends WBCmd { + + public CmdPreventSpawn() { + name = permission = "preventmobspawn"; + minParams = 0; + maxParams = 1; + + addCmdExample(nameEmphasized() + " - stop mob spawning past border."); + helpText = "Default value: off. When enabled, this setting will prevent mobs from naturally spawning outside the world's border."; + } + + @Override + public void cmdStatus(CommandSender sender) + { + sender.sendMessage(C_HEAD + "Prevention of mob spawning outside the border is " + enabledColored(Config.preventMobSpawn()) + C_HEAD + "."); + } + + @Override + public void execute(CommandSender sender, Player player, List params, String worldName) + { + if (params.size() == 1) { + boolean previousSetting = Config.preventMobSpawn(); + Config.setPreventMobSpawn(strAsBool(params.get(0))); + if (previousSetting != Config.preventMobSpawn()) { + WorldBorder.plugin.enableMobSpawnListener(Config.preventMobSpawn()); + } + } + + if (player != null) + { + Config.log((Config.preventMobSpawn() ? "Enabled" : "Disabled") + " preventmobspawn at the command of player \"" + player.getName() + "\"."); + cmdStatus(sender); + } + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 0db4d5b..b7cb5ef 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -42,6 +42,7 @@ commands: / portal - turn portal redirection on or off. / denypearl - stop ender pearls thrown past the border. / preventblockplace - stop block placement past border. + / preventmobspawn - stop mob spawning past border. / reload - re-load data from config.yml. / debug - turn debug mode on or off. permissions: @@ -64,6 +65,7 @@ permissions: worldborder.list: true worldborder.portal: true worldborder.preventblockplace: true + worldborder.preventmobspawn: true worldborder.radius: true worldborder.reload: true worldborder.remount: true @@ -122,6 +124,9 @@ permissions: worldborder.preventblockplace: description: Can prevent placement of blocks outside the border default: op + worldborder.preventmobspawn: + description: Can prevent spawning of mobs outside the border + default: op worldborder.radius: description: Can set the radius of an existing border default: op