From 73eec190b236e9f4414fa9c27fa0ff888e7583f9 Mon Sep 17 00:00:00 2001 From: "Alex \"mcmonkey\" Goodwin" Date: Sun, 30 Oct 2022 19:58:52 -0700 Subject: [PATCH] schematic command: create with mask support --- .../commands/world/SchematicCommand.java | 39 ++++++++++++------- .../utilities/blocks/CuboidBlockSet.java | 17 +++++--- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/SchematicCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/SchematicCommand.java index 5bbb2ed220..e4a8f4ac3e 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/SchematicCommand.java +++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/SchematicCommand.java @@ -97,6 +97,7 @@ public void run(ReplaceableTagEvent event) { // The "noair" option skips air blocks in the pasted schematics- this means those air blocks will not replace any blocks in the target location. // // The "mask" option can be specified to limit what block types the schematic will be pasted over. + // When using "create" and "mask", any block that doesn't match the mask will become a structure void. // // The "fake_to" option can be specified to cause the schematic paste to be a fake (packet-based, see <@link command showfake>) // block set, instead of actually modifying the blocks in the world. @@ -226,6 +227,21 @@ public static void rotateSchem(CuboidBlockSet schematic, int angle, boolean dela } } + public static void parseMask(ScriptEntry scriptEntry, String maskText, HashSet mask) { + if (maskText.startsWith("li@")) { // Back-compat: input used to be a list of materials + for (MaterialTag material : ListTag.valueOf(maskText, scriptEntry.getContext()).filter(MaterialTag.class, scriptEntry)) { + mask.add(material.getMaterial()); + } + } + else { + for (Material material : Material.values()) { + if (MaterialTag.advancedMatchesInternal(material, maskText, true)) { + mask.add(material); + } + } + } + } + @Override public void execute(final ScriptEntry scriptEntry) { ElementTag angle = scriptEntry.argForPrefixAsElement("angle", null); @@ -289,9 +305,15 @@ public void execute(final ScriptEntry scriptEntry) { return; } try { + HashSet maskSet = new HashSet<>(); + if (mask != null) { + String maskText = mask.asString(); + maskSet = new HashSet<>(); + parseMask(scriptEntry, maskText, maskSet); + } set = new CuboidBlockSet(); if (delayed) { - set.buildDelayed(area, location, () -> { + set.buildDelayed(area, location, maskSet, () -> { if (copyEntities) { set.buildEntities(area, location); } @@ -301,7 +323,7 @@ public void execute(final ScriptEntry scriptEntry) { } else { scriptEntry.setFinished(true); - set.buildImmediate(area, location, flags); + set.buildImmediate(area, location, maskSet, flags); if (copyEntities) { set.buildEntities(area, location); } @@ -481,18 +503,7 @@ public void execute(final ScriptEntry scriptEntry) { if (mask != null) { String maskText = mask.asString(); input.mask = new HashSet<>(); - if (maskText.startsWith("li@")) { // Back-compat: input used to be a list of materials - for (MaterialTag material : ListTag.valueOf(maskText, scriptEntry.getContext()).filter(MaterialTag.class, scriptEntry)) { - input.mask.add(material.getMaterial()); - } - } - else { - for (Material material : Material.values()) { - if (MaterialTag.advancedMatchesInternal(material, maskText, true)) { - input.mask.add(material); - } - } - } + parseMask(scriptEntry, maskText, input.mask); } set = schematics.get(name.asString().toUpperCase()); if (set.isModifying) { diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/blocks/CuboidBlockSet.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/blocks/CuboidBlockSet.java index af15c10287..7bca418edc 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/blocks/CuboidBlockSet.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/blocks/CuboidBlockSet.java @@ -30,7 +30,7 @@ public class CuboidBlockSet implements BlockSet { public CuboidBlockSet() { } - public void buildImmediate(AreaContainmentObject area, Location center, boolean copyFlags) { + public void buildImmediate(AreaContainmentObject area, Location center, HashSet mask, boolean copyFlags) { hasFlags = copyFlags; CuboidTag boundary; if (area instanceof CuboidTag && ((CuboidTag) area).pairs.size() == 1) { @@ -58,13 +58,17 @@ public void buildImmediate(AreaContainmentObject area, Location center, boolean refLoc.setX(lowX + x); refLoc.setY(lowY + y); refLoc.setZ(lowZ + z); - blocks[index++] = (constraint == null || constraint.doesContainLocation(refLoc)) ? new FullBlockData(refLoc.getBlock(), copyFlags) : STRUCTURE_VOID; + FullBlockData block = (constraint == null || constraint.doesContainLocation(refLoc)) ? new FullBlockData(refLoc.getBlock(), copyFlags) : STRUCTURE_VOID; + if (block != STRUCTURE_VOID && mask != null && !mask.contains(block.data.getMaterial())) { + block = STRUCTURE_VOID; + } + blocks[index++] = block; } } } } - public void buildDelayed(AreaContainmentObject area, Location center, Runnable runme, long maxDelayMs, boolean copyFlags) { + public void buildDelayed(AreaContainmentObject area, Location center, HashSet mask, Runnable runme, long maxDelayMs, boolean copyFlags) { hasFlags = copyFlags; CuboidTag boundary; if (area instanceof CuboidTag && ((CuboidTag) area).pairs.size() == 1) { @@ -98,10 +102,13 @@ public void run() { refLoc.setX(lowX + x); refLoc.setY(lowY + y); refLoc.setZ(lowZ + z); - blocks[index] = (constraint == null || constraint.doesContainLocation(refLoc)) ? new FullBlockData(refLoc.getBlock(), copyFlags) : STRUCTURE_VOID; + FullBlockData block = (constraint == null || constraint.doesContainLocation(refLoc)) ? new FullBlockData(refLoc.getBlock(), copyFlags) : STRUCTURE_VOID; + if (block != STRUCTURE_VOID && mask != null && !mask.contains(block.data.getMaterial())) { + block = STRUCTURE_VOID; + } + blocks[index] = block; index++; if (CoreUtilities.monotonicMillis() - start > maxDelayMs) { - SchematicCommand.noPhys = false; return; } }