From d5b7605f5e64ad8beadace3aefbf10288226c874 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Sun, 25 Sep 2016 02:31:18 +1000 Subject: [PATCH] Allow third parties to register custom masks --- .../main/java/com/boydti/fawe/FaweAPI.java | 30 +++++++++++++++++-- .../boydti/fawe/object/mask/CustomMask.java | 19 ++++++++++++ .../extension/factory/DefaultMaskParser.java | 29 ++++++++++++++++++ 3 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 core/src/main/java/com/boydti/fawe/object/mask/CustomMask.java diff --git a/core/src/main/java/com/boydti/fawe/FaweAPI.java b/core/src/main/java/com/boydti/fawe/FaweAPI.java index f4492389..e77547d2 100644 --- a/core/src/main/java/com/boydti/fawe/FaweAPI.java +++ b/core/src/main/java/com/boydti/fawe/FaweAPI.java @@ -11,14 +11,13 @@ import com.boydti.fawe.object.PseudoRandom; import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.object.changeset.DiskStorageHistory; -import com.boydti.fawe.object.io.FastByteArrayOutputStream; +import com.boydti.fawe.object.mask.CustomMask; import com.boydti.fawe.object.schematic.Schematic; import com.boydti.fawe.regions.FaweMaskManager; import com.boydti.fawe.util.EditSessionBuilder; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MemUtil; import com.boydti.fawe.util.SetQueue; -import com.boydti.fawe.util.StringMan; import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.WEManager; import com.boydti.fawe.wrappers.WorldWrapper; @@ -31,10 +30,13 @@ import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.extension.factory.DefaultMaskParser; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; +import com.sk89q.worldedit.internal.registry.AbstractFactory; +import com.sk89q.worldedit.internal.registry.InputParser; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.AbstractWorld; import com.sk89q.worldedit.world.World; @@ -43,10 +45,10 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.lang.reflect.Field; import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; -import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -87,6 +89,28 @@ public class FaweAPI { return TaskManager.IMP; } + /** + * Add a custom mask for use in //mask [values...] + * @param mask + * @return true if the mask was registered + */ + public static boolean registerMask(CustomMask mask) { + try { + Field field = AbstractFactory.class.getDeclaredField("parsers"); + field.setAccessible(true); + List parsers = (List) field.get(WorldEdit.getInstance().getMaskFactory()); + for (InputParser parser : parsers) { + if (parser instanceof DefaultMaskParser) { + ((DefaultMaskParser) parser).addMask(mask); + return true; + } + } + } catch (Throwable e) { + throw new RuntimeException(e); + } + return false; + } + /** * Wrap some object into a FawePlayer
* - org.bukkit.entity.Player diff --git a/core/src/main/java/com/boydti/fawe/object/mask/CustomMask.java b/core/src/main/java/com/boydti/fawe/object/mask/CustomMask.java new file mode 100644 index 00000000..ad2b2580 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/mask/CustomMask.java @@ -0,0 +1,19 @@ +package com.boydti.fawe.object.mask; + +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.function.mask.Mask; +import java.util.List; + +public abstract class CustomMask implements Mask { + public CustomMask(List masks, String component, ParserContext context) { + try { + this.getClass(). getConstructor ( List.class, String.class, ParserContext.class ) ; + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException("Constructor for " + getClass() + " must be (List.class, String.class, ParserContext.class)"); + } + } + + public abstract String description(); + + public abstract boolean accepts(String input); +} diff --git a/core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultMaskParser.java b/core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultMaskParser.java index a316515b..d56ce180 100644 --- a/core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultMaskParser.java +++ b/core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultMaskParser.java @@ -1,6 +1,7 @@ package com.sk89q.worldedit.extension.factory; import com.boydti.fawe.object.mask.AngleMask; +import com.boydti.fawe.object.mask.CustomMask; import com.boydti.fawe.object.mask.DataMask; import com.boydti.fawe.object.mask.IdDataMask; import com.boydti.fawe.object.mask.IdMask; @@ -35,11 +36,15 @@ import com.sk89q.worldedit.session.request.RequestSelection; import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.biome.Biomes; import com.sk89q.worldedit.world.registry.BiomeRegistry; +import java.lang.reflect.Constructor; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; +import static com.google.common.base.Preconditions.checkNotNull; + /** * Parses mask input strings. */ @@ -49,6 +54,19 @@ public class DefaultMaskParser extends InputParser { super(worldEdit); } + private static CustomMask[] customMasks; + + public void addMask(CustomMask mask) { + checkNotNull(mask); + List list = new ArrayList<>(Arrays.asList(customMasks)); + list.add(mask); + customMasks = list.toArray(new CustomMask[list.size()]); + } + + public List getCustomMasks() { + return Arrays.asList(customMasks); + } + @Override public Mask parseFromInput(String input, ParserContext context) throws InputParseException { List masks = new ArrayList(); @@ -174,6 +192,17 @@ public class DefaultMaskParser extends InputParser { } default: + for (CustomMask mask : customMasks) { + if (mask.accepts(component)) { + try { + Constructor constructor = mask.getClass().getDeclaredConstructor(List.class, String.class, ParserContext.class); + return constructor.newInstance(masks, component, context); + } catch (Throwable e) { + e.printStackTrace(); + } + } + } + ParserContext tempContext = new ParserContext(context); tempContext.setRestricted(false); tempContext.setPreferringWildcard(true);