diff --git a/src/main/java/com/wimbli/WorldBorder/Config.java b/src/main/java/com/wimbli/WorldBorder/Config.java index 33a495e..27bc89a 100644 --- a/src/main/java/com/wimbli/WorldBorder/Config.java +++ b/src/main/java/com/wimbli/WorldBorder/Config.java @@ -377,9 +377,9 @@ public class Config save(false); } - public static void RestoreFillTask(String world, int fillDistance, int chunksPerRun, int tickFrequency, int x, int z, int length, int total) + public static void RestoreFillTask(String world, int fillDistance, int chunksPerRun, int tickFrequency, int x, int z, int length, int total, boolean forceLoad) { - fillTask = new WorldFillTask(plugin.getServer(), null, world, fillDistance, chunksPerRun, tickFrequency); + fillTask = new WorldFillTask(plugin.getServer(), null, world, fillDistance, chunksPerRun, tickFrequency, forceLoad); if (fillTask.valid()) { fillTask.continueProgress(x, z, length, total); @@ -387,6 +387,11 @@ public class Config fillTask.setTaskID(task); } } + // for backwards compatibility + public static void RestoreFillTask(String world, int fillDistance, int chunksPerRun, int tickFrequency, int x, int z, int length, int total) + { + RestoreFillTask(world, fillDistance, chunksPerRun, tickFrequency, x, z, length, total, false); + } public static void StopTrimTask() @@ -517,7 +522,8 @@ public class Config int fillZ = storedFillTask.getInt("z", 0); int fillLength = storedFillTask.getInt("length", 0); int fillTotal = storedFillTask.getInt("total", 0); - RestoreFillTask(worldName, fillDistance, chunksPerRun, tickFrequency, fillX, fillZ, fillLength, fillTotal); + boolean forceLoad = storedFillTask.getBoolean("forceLoad", false); + RestoreFillTask(worldName, fillDistance, chunksPerRun, tickFrequency, fillX, fillZ, fillLength, fillTotal, forceLoad); save(false); } @@ -577,6 +583,7 @@ public class Config cfg.set("fillTask.z", fillTask.refZ()); cfg.set("fillTask.length", fillTask.refLength()); cfg.set("fillTask.total", fillTask.refTotal()); + cfg.set("fillTask.forceLoad", fillTask.refForceLoad()); } else cfg.set("fillTask", null); diff --git a/src/main/java/com/wimbli/WorldBorder/WBCommand.java b/src/main/java/com/wimbli/WorldBorder/WBCommand.java index ccc00a5..48de1c7 100644 --- a/src/main/java/com/wimbli/WorldBorder/WBCommand.java +++ b/src/main/java/com/wimbli/WorldBorder/WBCommand.java @@ -577,7 +577,7 @@ public class WBCommand implements CommandExecutor if (!Config.HasPermission(player, "fill")) return true; boolean cancel = false, confirm = false, pause = false; - String pad = "", frequency = ""; + String frequency = ""; if (split.length >= 3) { cancel = split[2].equalsIgnoreCase("cancel") || split[2].equalsIgnoreCase("stop"); @@ -586,12 +586,12 @@ public class WBCommand implements CommandExecutor if (!cancel && !confirm && !pause) frequency = split[2]; } - if (split.length >= 4) - pad = split[3]; + String pad = (split.length >= 4) ? split[3] : ""; + String forceLoad = (split.length >= 5) ? split[4] : ""; String world = split[0]; - cmdFill(sender, player, world, confirm, cancel, pause, pad, frequency); + cmdFill(sender, player, world, confirm, cancel, pause, pad, frequency, forceLoad); } // "fill" command from player (or from console solely if using cancel or confirm), using current world @@ -600,7 +600,7 @@ public class WBCommand implements CommandExecutor if (!Config.HasPermission(player, "fill")) return true; boolean cancel = false, confirm = false, pause = false; - String pad = "", frequency = ""; + String frequency = ""; if (split.length >= 2) { cancel = split[1].equalsIgnoreCase("cancel") || split[1].equalsIgnoreCase("stop"); @@ -609,8 +609,8 @@ public class WBCommand implements CommandExecutor if (!cancel && !confirm && !pause) frequency = split[1]; } - if (split.length >= 3) - pad = split[2]; + String pad = (split.length >= 3) ? split[2] : ""; + String forceLoad = (split.length >= 4) ? split[3] : ""; String world = ""; if (player != null && !cancel && !confirm && !pause) @@ -618,11 +618,11 @@ public class WBCommand implements CommandExecutor if (!cancel && !confirm && !pause && world.isEmpty()) { - sender.sendMessage("You must specify a world! Example: " + cmdW+" fill " + clrOpt + "[freq] [pad]"); + sender.sendMessage("You must specify a world! Example: " + cmdW + " fill " + clrOpt + "[freq] [pad] [force]"); return true; } - cmdFill(sender, player, world, confirm, cancel, pause, pad, frequency); + cmdFill(sender, player, world, confirm, cancel, pause, pad, frequency, forceLoad); } // "trim" command from player or console, world specified @@ -821,7 +821,7 @@ public class WBCommand implements CommandExecutor if (page == 0 || page == 2) { sender.sendMessage(cmd+" list" + clrDesc + " - show border information for all worlds."); - sender.sendMessage(cmdW+" fill " + clrOpt + "[freq] [pad]" + clrDesc + " - generate world out to border."); + sender.sendMessage(cmdW+" fill " + clrOpt + "[freq] [pad] [force]" + clrDesc + " - generate world to border."); sender.sendMessage(cmdW+" trim " + clrOpt + "[freq] [pad]" + clrDesc + " - trim world outside of border."); sender.sendMessage(cmd+" bypass " + ((player == null) ? clrReq + "" : clrOpt + "[player]") + clrOpt + " [on/off]" + clrDesc + " - let player go beyond border."); sender.sendMessage(cmd+" wshape " + ((player == null) ? clrReq + "" : clrOpt + "[world]") + clrReq + " " + clrDesc + " - shape override for this world."); @@ -905,6 +905,7 @@ public class WBCommand implements CommandExecutor private String fillWorld = ""; private int fillFrequency = 20; private int fillPadding = CoordXZ.chunkToBlock(13); + private boolean fillForceLoad = false; private void fillDefaults() { @@ -913,9 +914,10 @@ public class WBCommand implements CommandExecutor // with "view-distance=10" in server.properties and "Render Distance: Far" in client, hitting border during testing // was loading 11 chunks beyond the border in a couple of directions (10 chunks in the other two directions); thus: fillPadding = CoordXZ.chunkToBlock(13); + fillForceLoad = false; } - private boolean cmdFill(CommandSender sender, Player player, String world, boolean confirm, boolean cancel, boolean pause, String pad, String frequency) + private boolean cmdFill(CommandSender sender, Player player, String world, boolean confirm, boolean cancel, boolean pause, String pad, String frequency, String forceLoad) { if (cancel) { @@ -956,6 +958,8 @@ public class WBCommand implements CommandExecutor sender.sendMessage(clrErr + "The frequency and padding values must be integers."); return false; } + if (!forceLoad.isEmpty()) + fillForceLoad = strAsBool(forceLoad); // set world if it was specified if (!world.isEmpty()) @@ -978,7 +982,7 @@ public class WBCommand implements CommandExecutor else ticks = 20 / fillFrequency; - Config.fillTask = new WorldFillTask(plugin.getServer(), player, fillWorld, fillPadding, repeats, ticks); + Config.fillTask = new WorldFillTask(plugin.getServer(), player, fillWorld, fillPadding, repeats, ticks, fillForceLoad); if (Config.fillTask.valid()) { int task = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, Config.fillTask, ticks, ticks); @@ -999,7 +1003,7 @@ public class WBCommand implements CommandExecutor } String cmd = clrCmd + ((player == null) ? "wb" : "/wb"); - sender.sendMessage(clrHead + "World generation task is ready for world \"" + fillWorld + "\", padding the map out to " + fillPadding + " blocks beyond the border (default " + CoordXZ.chunkToBlock(13) + "), and the task will try to generate up to " + fillFrequency + " chunks per second (default 20)."); + sender.sendMessage(clrHead + "World generation task is ready for world \"" + fillWorld + "\", padding the map out to " + fillPadding + " blocks beyond the border (default " + CoordXZ.chunkToBlock(13) + "), and the task will try to generate up to " + fillFrequency + " chunks per second (default 20). Parts of the world which are already fully generated will be " + (fillForceLoad ? "loaded anyway." : "skipped.")); sender.sendMessage(clrHead + "This process can take a very long time depending on the world's border size. Also, depending on the chunk processing rate, players will likely experience severe lag for the duration."); sender.sendMessage(clrDesc + "You should now use " + cmd + " fill confirm" + clrDesc + " to start the process."); sender.sendMessage(clrDesc + "You can cancel at any time with " + cmd + " fill cancel" + clrDesc + ", or pause/unpause with " + cmd + " fill pause" + clrDesc + "."); diff --git a/src/main/java/com/wimbli/WorldBorder/WBListener.java b/src/main/java/com/wimbli/WorldBorder/WBListener.java index b72f2b1..4f48564 100644 --- a/src/main/java/com/wimbli/WorldBorder/WBListener.java +++ b/src/main/java/com/wimbli/WorldBorder/WBListener.java @@ -1,5 +1,6 @@ package com.wimbli.WorldBorder; +import org.bukkit.Chunk; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -41,6 +42,19 @@ public class WBListener implements Listener @EventHandler(priority = EventPriority.MONITOR) public void onChunkLoad(ChunkLoadEvent event) { +/* // tested, found to spam pretty rapidly as client repeatedly requests the same chunks since they're not being sent + // definitely too spammy at only 16 blocks outside border + // potentially useful at standard 208 block padding as it was triggering only occasionally while trying to get out all along edge of round border, though sometimes up to 3 triggers within a second corresponding to 3 adjacent chunks + // would of course need to be further worked on to have it only affect chunks outside a border, along with an option somewhere to disable it or even set specified distance outside border for it to take effect + + // method to prevent new chunks from being generated, core method courtesy of code from NoNewChunk plugin (http://dev.bukkit.org/bukkit-plugins/nonewchunk/) + if(event.isNewChunk()) + { + Chunk chunk = event.getChunk(); + chunk.unload(false, false); + Config.LogWarn("New chunk generation has been prevented at X " + chunk.getX() + ", Z " + chunk.getZ()); + } +*/ // make sure our border monitoring task is still running like it should if (Config.isBorderTimerRunning()) return; diff --git a/src/main/java/com/wimbli/WorldBorder/WorldFillTask.java b/src/main/java/com/wimbli/WorldBorder/WorldFillTask.java index 1886e41..68c5f32 100644 --- a/src/main/java/com/wimbli/WorldBorder/WorldFillTask.java +++ b/src/main/java/com/wimbli/WorldBorder/WorldFillTask.java @@ -25,6 +25,7 @@ public class WorldFillTask implements Runnable private transient Player notifyPlayer = null; private transient int chunksPerRun = 1; private transient boolean continueNotice = false; + private transient boolean forceLoad = false; // these are only stored for saving task to config private transient int fillDistance = 208; @@ -53,13 +54,14 @@ public class WorldFillTask implements Runnable private transient int reportNum = 0; - public WorldFillTask(Server theServer, Player player, String worldName, int fillDistance, int chunksPerRun, int tickFrequency) + public WorldFillTask(Server theServer, Player player, String worldName, int fillDistance, int chunksPerRun, int tickFrequency, boolean forceLoad) { this.server = theServer; this.notifyPlayer = player; this.fillDistance = fillDistance; this.tickFrequency = tickFrequency; this.chunksPerRun = chunksPerRun; + this.forceLoad = forceLoad; this.world = server.getWorld(worldName); if (this.world == null) @@ -112,6 +114,11 @@ public class WorldFillTask implements Runnable this.readyToGo = true; } + // for backwards compatibility + public WorldFillTask(Server theServer, Player player, String worldName, int fillDistance, int chunksPerRun, int tickFrequency) + { + this(theServer, player, worldName, fillDistance, chunksPerRun, tickFrequency, false); + } public void setTaskID(int ID) { @@ -175,12 +182,15 @@ public class WorldFillTask implements Runnable } insideBorder = true; - // skip past any chunks which are confirmed as fully generated using our super-special isChunkFullyGenerated routine - while (worldData.isChunkFullyGenerated(x, z)) + if (!forceLoad) { - insideBorder = true; - if (!moveToNext()) - return; + // skip past any chunks which are confirmed as fully generated using our super-special isChunkFullyGenerated routine + while (worldData.isChunkFullyGenerated(x, z)) + { + insideBorder = true; + if (!moveToNext()) + return; + } } // load the target chunk and generate it if necessary @@ -450,4 +460,8 @@ public class WorldFillTask implements Runnable { return world.getName(); } + public boolean refForceLoad() + { + return forceLoad; + } }