From 3e2cd71859ef97ad6c894b17afbfea4cf0235a4e Mon Sep 17 00:00:00 2001 From: mcmonkey4eva Date: Thu, 13 Nov 2014 13:11:40 -0800 Subject: [PATCH] Add a 'delayed' argument to modifyblock Safe massive-area editing? Hell yes! --- .../net/aufdemrand/denizen/objects/aH.java | 1 - .../commands/BukkitCommandRegistry.java | 5 +- .../commands/world/ModifyBlockCommand.java | 141 ++++++++++++------ 3 files changed, 99 insertions(+), 48 deletions(-) diff --git a/src/main/java/net/aufdemrand/denizen/objects/aH.java b/src/main/java/net/aufdemrand/denizen/objects/aH.java index 02e73d2f7d..782520cc82 100644 --- a/src/main/java/net/aufdemrand/denizen/objects/aH.java +++ b/src/main/java/net/aufdemrand/denizen/objects/aH.java @@ -133,7 +133,6 @@ public Argument getPrefix() { // TODO: REMOVE IN 1.0 - @Deprecated public boolean matches(String values) { for (String value : StringUtils.split(values, ',')) { if (CoreUtilities.toLowerCase(value.trim()).equals(lower_value)) diff --git a/src/main/java/net/aufdemrand/denizen/scripts/commands/BukkitCommandRegistry.java b/src/main/java/net/aufdemrand/denizen/scripts/commands/BukkitCommandRegistry.java index f92a309068..fd8c614de2 100644 --- a/src/main/java/net/aufdemrand/denizen/scripts/commands/BukkitCommandRegistry.java +++ b/src/main/java/net/aufdemrand/denizen/scripts/commands/BukkitCommandRegistry.java @@ -1706,7 +1706,7 @@ public void registerCoreMembers() { // <--[command] // @Name ModifyBlock - // @Syntax modifyblock [|...] [|...] (radius:<#>) (height:<#>) (depth:<#>) (no_physics/naturally) + // @Syntax modifyblock [|...] [|...] (radius:<#>) (height:<#>) (depth:<#>) (no_physics/naturally) (delayed) // @Required 2 // @Stable stable // @Short Modifies blocks. @@ -1718,13 +1718,14 @@ public void registerCoreMembers() { // physics taking over the modified blocks. This is useful for block types such as portals. This does NOT // control physics for an extended period of time. // Use 'naturally' when setting a block to air to break it naturally, meaning that it will drop items. + // Use 'delayed' to make the modifyblock slowly edit blocks at a time pace roughly equivalent to the server's limits. // @Tags // // @Usage // TODO: Document Command Details // --> registerCoreMember(ModifyBlockCommand.class, - "MODIFYBLOCK", "modifyblock [] [|...] (radius:<#>) (height:<#>) (depth:<#>) (no_physics/naturally)", 2); + "MODIFYBLOCK", "modifyblock [] [|...] (radius:<#>) (height:<#>) (depth:<#>) (no_physics/naturally) (delayed)", 2); // <--[command] diff --git a/src/main/java/net/aufdemrand/denizen/scripts/commands/world/ModifyBlockCommand.java b/src/main/java/net/aufdemrand/denizen/scripts/commands/world/ModifyBlockCommand.java index 15cfefb1c7..4cd6adc322 100644 --- a/src/main/java/net/aufdemrand/denizen/scripts/commands/world/ModifyBlockCommand.java +++ b/src/main/java/net/aufdemrand/denizen/scripts/commands/world/ModifyBlockCommand.java @@ -31,6 +31,10 @@ public class ModifyBlockCommand extends AbstractCommand implements Listener { + public class IntHolder { + public int MyInteger = 0; + } + @Override public void parseArgs(ScriptEntry scriptEntry)throws InvalidArgumentsException { @@ -70,6 +74,9 @@ else if (arg.matches("no_physics")) else if (arg.matches("naturally")) scriptEntry.addObject("natural", new Element(true)); + else if (arg.matches("delayed")) + scriptEntry.addObject("delayed", new Element(true)); + else arg.reportUnhandled(); } @@ -87,7 +94,8 @@ else if (arg.matches("naturally")) .defaultObject("height", new Element(0)) .defaultObject("depth", new Element(0)) .defaultObject("physics", new Element(true)) - .defaultObject("natural", new Element(false)); + .defaultObject("natural", new Element(false)) + .defaultObject("delayed", new Element(false)); } @@ -95,14 +103,15 @@ else if (arg.matches("naturally")) @Override public void execute(ScriptEntry scriptEntry) throws CommandExecutionException { - dList materials = (dList) scriptEntry.getObject("materials"); - List locations = (List) scriptEntry.getObject("locations"); - Element physics = scriptEntry.getElement("physics"); - Element natural = scriptEntry.getElement("natural"); - Element radiusElement = scriptEntry.getElement("radius"); - Element heightElement = scriptEntry.getElement("height"); - Element depthElement = scriptEntry.getElement("depth"); - List materialList = materials.filter(dMaterial.class); + final dList materials = (dList) scriptEntry.getObject("materials"); + final List locations = (List) scriptEntry.getObject("locations"); + final Element physics = scriptEntry.getElement("physics"); + final Element natural = scriptEntry.getElement("natural"); + final Element delayed = scriptEntry.getElement("delayed"); + final Element radiusElement = scriptEntry.getElement("radius"); + final Element heightElement = scriptEntry.getElement("height"); + final Element depthElement = scriptEntry.getElement("depth"); + final List materialList = materials.filter(dMaterial.class); dB.report(scriptEntry, getName(), aH.debugList("locations", locations) + materials.debug() @@ -110,66 +119,108 @@ public void execute(ScriptEntry scriptEntry) throws CommandExecutionException { + radiusElement.debug() + heightElement.debug() + depthElement.debug() - + natural.debug()); + + natural.debug() + + delayed.debug()); - boolean doPhysics = physics.asBoolean(); - boolean isNatural = natural.asBoolean(); - int radius = radiusElement.asInt(); - int height = heightElement.asInt(); - int depth = depthElement.asInt(); + final boolean doPhysics = physics.asBoolean(); + final boolean isNatural = natural.asBoolean(); + final int radius = radiusElement.asInt(); + final int height = heightElement.asInt(); + final int depth = depthElement.asInt(); no_physics = !doPhysics; + if (delayed.asBoolean()) { + final IntHolder myint = new IntHolder(); + myint.MyInteger = Bukkit.getScheduler().scheduleSyncRepeatingTask(DenizenAPI.getCurrentInstance(), new Runnable() { + @Override + public void run() { + boolean was_static = preSetup(locations); + int index = 0; + long start = System.currentTimeMillis(); + Location loc = (dLocation)locations.get(0); + while (locations.size() > 0) { + handleLocation((dLocation) locations.get(0), index, materialList, doPhysics, isNatural, radius, height, depth); + locations.remove(0); + if (System.currentTimeMillis() - start > 50) { + break; + } + } + postComplete(loc, was_static); + if (locations.size() == 0) { + Bukkit.getScheduler().cancelTask(myint.MyInteger); + } + } + }, 1, 1); + } + else { + boolean was_static = preSetup(locations); + Location loc = (dLocation)locations.get(0); + int index = 0; + for (dObject obj : locations) { + handleLocation((dLocation) obj, index, materialList, doPhysics, isNatural, radius, height, depth); + } + postComplete(loc, was_static); + } + } + boolean preSetup(List locations) { + if (locations.size() == 0) + return false; // Freeze the first world in the list. CraftWorld craftWorld = (CraftWorld)((dLocation)locations.get(0)).getWorld(); boolean was_static = craftWorld.getHandle().isStatic; if (no_physics) craftWorld.getHandle().isStatic = true; + return was_static; + } - int index = 0; - for (dObject obj : locations) { + void postComplete(Location loc, boolean was_static) { + // Unfreeze the first world in the list. + CraftWorld craftWorld = (CraftWorld)loc.getWorld(); + if (no_physics) + craftWorld.getHandle().isStatic = was_static; + no_physics = false; + } - dMaterial material = materialList.get(index % materialList.size()); - index++; - dLocation location = (dLocation) obj; - World world = location.getWorld(); + void handleLocation(dLocation location, int index, List materialList, boolean doPhysics, + boolean isNatural, int radius, int height, int depth) { - location.setX(location.getBlockX()); - location.setY(location.getBlockY()); - location.setZ(location.getBlockZ()); - setBlock(location, material, doPhysics, isNatural); + dMaterial material = materialList.get(index % materialList.size()); + index++; + World world = location.getWorld(); - if (radius != 0){ - for (int x = 0; x < 2 * radius + 1; x++) { - for (int z = 0; z < 2 * radius + 1; z++) { - setBlock(new Location(world, location.getX() + x - radius, location.getY(), location.getZ() + z - radius), material, doPhysics, isNatural); - } + location.setX(location.getBlockX()); + location.setY(location.getBlockY()); + location.setZ(location.getBlockZ()); + setBlock(location, material, doPhysics, isNatural); + + if (radius != 0){ + for (int x = 0; x < 2 * radius + 1; x++) { + for (int z = 0; z < 2 * radius + 1; z++) { + setBlock(new Location(world, location.getX() + x - radius, location.getY(), location.getZ() + z - radius), material, doPhysics, isNatural); } } + } - if (height != 0){ - for (int x = 0; x < 2 * radius + 1; x++) { - for (int z = 0; z < 2 * radius + 1; z++) { - for (int y = 1; y < height + 1; y++) { - setBlock(new Location(world, location.getX() + x - radius, location.getY() + y, location.getZ() + z - radius), material, doPhysics, isNatural); - } + if (height != 0){ + for (int x = 0; x < 2 * radius + 1; x++) { + for (int z = 0; z < 2 * radius + 1; z++) { + for (int y = 1; y < height + 1; y++) { + setBlock(new Location(world, location.getX() + x - radius, location.getY() + y, location.getZ() + z - radius), material, doPhysics, isNatural); } } } + } - if (depth != 0){ - for (int x = 0; x < 2 * radius + 1; x++) { - for (int z = 0; z < 2 * radius + 1; z++) { - for (int y = 1; y < depth + 1; y++) { - setBlock(new Location(world, location.getX() + x - radius, location.getY() - y, location.getZ() + z - radius), material, doPhysics, isNatural); - } + if (depth != 0){ + for (int x = 0; x < 2 * radius + 1; x++) { + for (int z = 0; z < 2 * radius + 1; z++) { + for (int y = 1; y < depth + 1; y++) { + setBlock(new Location(world, location.getX() + x - radius, location.getY() - y, location.getZ() + z - radius), material, doPhysics, isNatural); } } } } - if (no_physics) - craftWorld.getHandle().isStatic = was_static; - no_physics = false; } void setBlock(Location location, dMaterial material, boolean physics, boolean natural) {