From 28190d1c770e453416fa26375fd0bd48b8b8416b Mon Sep 17 00:00:00 2001 From: mcmonkey4eva Date: Sat, 13 Jun 2015 19:17:22 -0700 Subject: [PATCH] Allow schematic pastes to be delayed, fixes #1054 --- .../commands/BukkitCommandRegistry.java | 4 +- .../commands/world/SchematicCommand.java | 66 ++++++++++++------- .../denizen/utilities/blocks/BlockSet.java | 2 + .../utilities/blocks/CuboidBlockSet.java | 35 +++++++++- 4 files changed, 80 insertions(+), 27 deletions(-) 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 89ae8de36d..20390bf130 100644 --- a/src/main/java/net/aufdemrand/denizen/scripts/commands/BukkitCommandRegistry.java +++ b/src/main/java/net/aufdemrand/denizen/scripts/commands/BukkitCommandRegistry.java @@ -2120,7 +2120,7 @@ public void registerCoreMembers() { // <--[command] // @Name Schematic - // @Syntax schematic [create/load/unload/rotate/paste/save] [name:] (angle:<#>) () () + // @Syntax schematic [create/load/unload/rotate/paste/save] [name:] (angle:<#>) () () (delayed) // @Group World // @Required 2 // @Stable unstable @@ -2164,7 +2164,7 @@ public void registerCoreMembers() { // --> registerCoreMember(SchematicCommand.class, - "SCHEMATIC", "schematic [create/load/unload/rotate/paste/save] [name:] (angle:<#>) () ()", 2); + "SCHEMATIC", "schematic [create/load/unload/rotate/paste/save] [name:] (angle:<#>) () () (delayed)", 2); // <--[command] diff --git a/src/main/java/net/aufdemrand/denizen/scripts/commands/world/SchematicCommand.java b/src/main/java/net/aufdemrand/denizen/scripts/commands/world/SchematicCommand.java index c13d7e7c55..c487a359d6 100644 --- a/src/main/java/net/aufdemrand/denizen/scripts/commands/world/SchematicCommand.java +++ b/src/main/java/net/aufdemrand/denizen/scripts/commands/world/SchematicCommand.java @@ -4,6 +4,7 @@ import net.aufdemrand.denizen.utilities.blocks.CuboidBlockSet; import net.aufdemrand.denizencore.scripts.ScriptHelper; import net.aufdemrand.denizencore.scripts.commands.AbstractCommand; +import net.aufdemrand.denizencore.scripts.commands.Holdable; import net.aufdemrand.denizencore.tags.ReplaceableTagEvent; import net.aufdemrand.denizencore.tags.TagManager; import net.aufdemrand.denizencore.exceptions.CommandExecutionException; @@ -24,7 +25,7 @@ import java.util.HashMap; import java.util.Map; -public class SchematicCommand extends AbstractCommand { +public class SchematicCommand extends AbstractCommand implements Holdable { @Override public void onEnable() { @@ -42,27 +43,32 @@ public void parseArgs(ScriptEntry scriptEntry) throws InvalidArgumentsException for (aH.Argument arg : aH.interpret(scriptEntry.getArguments())) { if (!scriptEntry.hasObject("type") - && arg.matchesEnum(Type.values())) + && arg.matchesEnum(Type.values())) { scriptEntry.addObject("type", new Element(arg.raw_value.toUpperCase())); - + } else if (!scriptEntry.hasObject("name") - && arg.matchesPrefix("name")) + && arg.matchesPrefix("name")) { scriptEntry.addObject("name", arg.asElement()); - + } else if (!scriptEntry.hasObject("angle") - && arg.matchesPrimitive(aH.PrimitiveType.Integer)) + && arg.matchesPrimitive(aH.PrimitiveType.Integer)) { scriptEntry.addObject("angle", arg.asElement()); - + } else if (!scriptEntry.hasObject("location") - && arg.matchesArgumentType(dLocation.class)) + && arg.matchesArgumentType(dLocation.class)) { scriptEntry.addObject("location", arg.asType(dLocation.class)); - + } else if (!scriptEntry.hasObject("cuboid") - && arg.matchesArgumentType(dCuboid.class)) + && arg.matchesArgumentType(dCuboid.class)) { scriptEntry.addObject("cuboid", arg.asType(dCuboid.class)); - - else + } + else if (!scriptEntry.hasObject("delayed") + && arg.matches("delayed")) { + scriptEntry.addObject("delayed", new Element("true")); + } + else { arg.reportUnhandled(); + } } if (!scriptEntry.hasObject("type")) @@ -70,16 +76,16 @@ else if (!scriptEntry.hasObject("cuboid") if (!scriptEntry.hasObject("name")) throw new InvalidArgumentsException("Missing name argument!"); - } @Override - public void execute(ScriptEntry scriptEntry) throws CommandExecutionException { + public void execute(final ScriptEntry scriptEntry) throws CommandExecutionException { Element angle = scriptEntry.getElement("angle"); Element type = scriptEntry.getElement("type"); Element name = scriptEntry.getElement("name"); + Element delayed = scriptEntry.getElement("delayed"); dLocation location = scriptEntry.getdObject("location"); dCuboid cuboid = scriptEntry.getdObject("cuboid"); @@ -87,10 +93,15 @@ public void execute(ScriptEntry scriptEntry) throws CommandExecutionException { + name.debug() + (location != null ? location.debug(): "") + (cuboid != null ? cuboid.debug(): "") - + (angle != null ? angle.debug(): "")); + + (angle != null ? angle.debug(): "") + + (delayed != null ? delayed.debug(): "")); CuboidBlockSet set; - switch (Type.valueOf(type.asString())) { + Type ttype = Type.valueOf(type.asString()); + if (scriptEntry.shouldWaitFor() && ttype != Type.PASTE) { + scriptEntry.setFinished(true); + } + switch (ttype) { case CREATE: if (schematics.containsKey(name.asString().toUpperCase())) { dB.echoError(scriptEntry.getResidingQueue(), "Schematic file " + name.asString() + " is already loaded."); @@ -105,6 +116,7 @@ public void execute(ScriptEntry scriptEntry) throws CommandExecutionException { return; } try { + // TODO: Make me waitable! set = new CuboidBlockSet(cuboid, location); schematics.put(name.asString().toUpperCase(), set); } @@ -127,7 +139,7 @@ public void execute(ScriptEntry scriptEntry) throws CommandExecutionException { return; } InputStream fs = new FileInputStream(f); - //set = CuboidBlockSet.fromCompressedString(ScriptHelper.convertStreamToString(fs)); + // TODO: Make me waitable! set = CuboidBlockSet.fromMCEditStream(fs); fs.close(); schematics.put(name.asString().toUpperCase(), set); @@ -155,6 +167,7 @@ public void execute(ScriptEntry scriptEntry) throws CommandExecutionException { return; } dB.echoError(scriptEntry.getResidingQueue(), "Schematic rotation is TODO!"); + // TODO: Make me waitable! int ang = angle.asInt(); if (ang < 0) { ang = 360 + ang; @@ -163,7 +176,6 @@ public void execute(ScriptEntry scriptEntry) throws CommandExecutionException { ang -= 90; schematics.get(name.asString().toUpperCase()).rotateOne(); } - //schematics.get(name.asString().toUpperCase()).rotate2D(angle.asInt()); break; case PASTE: if (!schematics.containsKey(name.asString().toUpperCase())) { @@ -175,7 +187,17 @@ public void execute(ScriptEntry scriptEntry) throws CommandExecutionException { return; } try { - schematics.get(name.asString().toUpperCase()).setBlocks(location); + if (delayed != null && delayed.asBoolean()) { + schematics.get(name.asString().toUpperCase()).setBlocksDelayed(location, new Runnable() { + @Override + public void run() { + scriptEntry.setFinished(true); + } + }); + } + else { + schematics.get(name.asString().toUpperCase()).setBlocks(location); + } } catch (Exception ex) { dB.echoError(scriptEntry.getResidingQueue(), "Exception pasting schematic file " + name.asString() + "."); @@ -192,13 +214,9 @@ public void execute(ScriptEntry scriptEntry) throws CommandExecutionException { set = schematics.get(name.asString().toUpperCase()); String directory = URLDecoder.decode(System.getProperty("user.dir")); File f = new File(directory + "/plugins/Denizen/schematics/" + name.asString() + ".schematic"); - //String output = set.toCompressedFormat(); + // TODO: Make me waitable! FileOutputStream fs = new FileOutputStream(f); set.saveMCEditFormatToStream(fs); - /*OutputStreamWriter osw = new OutputStreamWriter(fs); - osw.write(output); - osw.flush(); - osw.close();*/ fs.flush(); fs.close(); } diff --git a/src/main/java/net/aufdemrand/denizen/utilities/blocks/BlockSet.java b/src/main/java/net/aufdemrand/denizen/utilities/blocks/BlockSet.java index 2390d1d184..f5d1cb7784 100644 --- a/src/main/java/net/aufdemrand/denizen/utilities/blocks/BlockSet.java +++ b/src/main/java/net/aufdemrand/denizen/utilities/blocks/BlockSet.java @@ -8,6 +8,8 @@ public interface BlockSet { public abstract List getBlocks(); + public abstract void setBlocksDelayed(Location loc, Runnable runme); + public abstract void setBlocks(Location loc); public abstract String toCompressedFormat(); diff --git a/src/main/java/net/aufdemrand/denizen/utilities/blocks/CuboidBlockSet.java b/src/main/java/net/aufdemrand/denizen/utilities/blocks/CuboidBlockSet.java index e7c8f6d037..cf6c7d780e 100644 --- a/src/main/java/net/aufdemrand/denizen/utilities/blocks/CuboidBlockSet.java +++ b/src/main/java/net/aufdemrand/denizen/utilities/blocks/CuboidBlockSet.java @@ -2,10 +2,13 @@ import net.aufdemrand.denizen.objects.dCuboid; import net.aufdemrand.denizen.objects.dLocation; +import net.aufdemrand.denizen.utilities.DenizenAPI; import net.aufdemrand.denizen.utilities.debugging.dB; import net.aufdemrand.denizencore.utilities.CoreUtilities; import net.aufdemrand.denizen.utilities.jnbt.*; +import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.*; import org.bukkit.util.Vector; @@ -63,6 +66,36 @@ public dCuboid getCuboid(Location loc) { return new dCuboid(low, high); } + public class IntHolder { + public long theInt = 0; + } + + @Override + public void setBlocksDelayed(final Location loc, final Runnable runme) { + final IntHolder index = new IntHolder(); + final long goal = (long)(x_width * y_length * z_height); + + new BukkitRunnable() { + @Override + public void run() { + long start = System.currentTimeMillis(); + while (index.theInt < goal) { + long z = index.theInt % ((long)(z_height)); + long y = ((index.theInt - z) % ((long)(y_length * z_height))) / ((long)z_height); + long x = (index.theInt - y - z) / ((long)(y_length * z_height)); + blocks.get((int)index.theInt).setBlock(loc.clone().add(x, y, z).getBlock()); + index.theInt++; + if (System.currentTimeMillis() - start > 50) { + return; + } + } + runme.run(); + cancel(); + + } + }.runTaskTimer(DenizenAPI.getCurrentInstance(), 1, 1); + } + @Override public void setBlocks(Location loc) { int index = 0; @@ -77,7 +110,7 @@ public void setBlocks(Location loc) { } public CuboidBlockSet rotateOne() { - // TODO + // TODO: IMPLEMENT ME! return new CuboidBlockSet(); }