diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/BlockFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/BlockFactory.java index aab3504f4..dab0f3741 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/BlockFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/BlockFactory.java @@ -21,6 +21,7 @@ package com.sk89q.worldedit.extension.factory; import com.sk89q.util.StringUtil; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.factory.parser.DefaultBlockParser; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; @@ -47,7 +48,7 @@ public class BlockFactory extends AbstractFactory { public BlockFactory(WorldEdit worldEdit) { super(worldEdit); - parsers.add(new DefaultBlockParser(worldEdit)); + register(new DefaultBlockParser(worldEdit)); } /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/ItemFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/ItemFactory.java index 321fc6280..e2a2bee29 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/ItemFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/ItemFactory.java @@ -21,6 +21,7 @@ package com.sk89q.worldedit.extension.factory; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.blocks.BaseItem; +import com.sk89q.worldedit.extension.factory.parser.DefaultItemParser; import com.sk89q.worldedit.internal.registry.AbstractFactory; public class ItemFactory extends AbstractFactory { @@ -33,7 +34,7 @@ public class ItemFactory extends AbstractFactory { public ItemFactory(WorldEdit worldEdit) { super(worldEdit); - parsers.add(new DefaultItemParser(worldEdit)); + register(new DefaultItemParser(worldEdit)); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java index 01fef9803..0f9f04fde 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java @@ -20,8 +20,24 @@ package com.sk89q.worldedit.extension.factory; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.factory.parser.mask.BlockCategoryMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.DefaultMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.ExistingMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.LazyRegionMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.NegateMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.NoiseMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.RegionMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.SolidMaskParser; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.NoMatchException; +import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.MaskIntersection; import com.sk89q.worldedit.internal.registry.AbstractFactory; +import com.sk89q.worldedit.internal.registry.InputParser; + +import java.util.ArrayList; +import java.util.List; /** * A registry of known {@link Mask}s. Provides methods to instantiate @@ -40,7 +56,42 @@ public final class MaskFactory extends AbstractFactory { public MaskFactory(WorldEdit worldEdit) { super(worldEdit); - parsers.add(new DefaultMaskParser(worldEdit)); + register(new ExistingMaskParser(worldEdit)); + register(new SolidMaskParser(worldEdit)); + register(new LazyRegionMaskParser(worldEdit)); + register(new RegionMaskParser(worldEdit)); + register(new BlockCategoryMaskParser(worldEdit)); + register(new NoiseMaskParser(worldEdit)); + register(new NegateMaskParser(worldEdit)); + register(new DefaultMaskParser(worldEdit)); + } + + @Override + public Mask parseFromInput(String input, ParserContext context) throws InputParseException { + List masks = new ArrayList<>(); + + for (String component : input.split(" ")) { + if (component.isEmpty()) { + continue; + } + + for (InputParser parser : getParsers()) { + Mask match = parser.parseFromInput(component, context); + + if (match != null) { + masks.add(match); + } + } + } + + switch (masks.size()) { + case 0: + throw new NoMatchException("No match for '" + input + "'"); + case 1: + return masks.get(0); + default: + return new MaskIntersection(masks); + } } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/PatternFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/PatternFactory.java index 71225e7d1..cab4d8dee 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/PatternFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/PatternFactory.java @@ -20,6 +20,9 @@ package com.sk89q.worldedit.extension.factory; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.factory.parser.pattern.ClipboardPatternParser; +import com.sk89q.worldedit.extension.factory.parser.pattern.RandomPatternParser; +import com.sk89q.worldedit.extension.factory.parser.pattern.SingleBlockPatternParser; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.internal.registry.AbstractFactory; @@ -40,9 +43,9 @@ public final class PatternFactory extends AbstractFactory { public PatternFactory(WorldEdit worldEdit) { super(worldEdit); - parsers.add(new HashTagPatternParser(worldEdit)); - parsers.add(new SingleBlockPatternParser(worldEdit)); - parsers.add(new RandomPatternParser(worldEdit)); + register(new ClipboardPatternParser(worldEdit)); + register(new SingleBlockPatternParser(worldEdit)); + register(new RandomPatternParser(worldEdit)); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultBlockParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java similarity index 98% rename from worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultBlockParser.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java index d75b9c739..3b7635c91 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultBlockParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.extension.factory; +package com.sk89q.worldedit.extension.factory.parser; import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.NotABlockException; @@ -52,9 +52,9 @@ import java.util.Map; /** * Parses block input strings. */ -class DefaultBlockParser extends InputParser { +public class DefaultBlockParser extends InputParser { - protected DefaultBlockParser(WorldEdit worldEdit) { + public DefaultBlockParser(WorldEdit worldEdit) { super(worldEdit); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultItemParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultItemParser.java similarity index 95% rename from worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultItemParser.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultItemParser.java index d2319a609..f25bd86be 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultItemParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultItemParser.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.extension.factory; +package com.sk89q.worldedit.extension.factory.parser; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.blocks.BaseItem; @@ -30,7 +30,7 @@ import com.sk89q.worldedit.world.registry.LegacyMapper; public class DefaultItemParser extends InputParser { - protected DefaultItemParser(WorldEdit worldEdit) { + public DefaultItemParser(WorldEdit worldEdit) { super(worldEdit); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlockCategoryMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlockCategoryMaskParser.java new file mode 100644 index 000000000..478ba22e6 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlockCategoryMaskParser.java @@ -0,0 +1,55 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extension.factory.parser.mask; + +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.function.mask.BlockCategoryMask; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.internal.registry.InputParser; +import com.sk89q.worldedit.session.request.Request; +import com.sk89q.worldedit.world.block.BlockCategories; +import com.sk89q.worldedit.world.block.BlockCategory; + +public class BlockCategoryMaskParser extends InputParser { + + public BlockCategoryMaskParser(WorldEdit worldEdit) { + super(worldEdit); + } + + @Override + public Mask parseFromInput(String input, ParserContext context) throws InputParseException { + if (input.startsWith("##")) { + Extent extent = Request.request().getEditSession(); + + // This means it's a tag mask. + BlockCategory category = BlockCategories.get(input.substring(2).toLowerCase()); + if (category == null) { + throw new InputParseException("Unrecognised tag '" + input.substring(2) + '\''); + } else { + return new BlockCategoryMask(extent, category); + } + } + + return null; + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/DefaultMaskParser.java similarity index 53% rename from worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultMaskParser.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/DefaultMaskParser.java index 9fe9844ef..f8913a04d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultMaskParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/DefaultMaskParser.java @@ -17,43 +17,32 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.extension.factory; +package com.sk89q.worldedit.extension.factory.parser.mask; -import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.input.InputParseException; -import com.sk89q.worldedit.extension.input.NoMatchException; import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.mask.BiomeMask2D; -import com.sk89q.worldedit.function.mask.BlockCategoryMask; import com.sk89q.worldedit.function.mask.BlockMask; import com.sk89q.worldedit.function.mask.ExistingBlockMask; import com.sk89q.worldedit.function.mask.ExpressionMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.MaskIntersection; import com.sk89q.worldedit.function.mask.Masks; -import com.sk89q.worldedit.function.mask.NoiseFilter; import com.sk89q.worldedit.function.mask.OffsetMask; -import com.sk89q.worldedit.function.mask.RegionMask; -import com.sk89q.worldedit.function.mask.SolidBlockMask; import com.sk89q.worldedit.internal.expression.Expression; import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.internal.registry.InputParser; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; -import com.sk89q.worldedit.math.noise.RandomNoise; import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment; import com.sk89q.worldedit.session.request.Request; -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.block.BlockCategories; -import com.sk89q.worldedit.world.block.BlockCategory; import com.sk89q.worldedit.world.registry.BiomeRegistry; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -61,77 +50,22 @@ import java.util.Set; /** * Parses mask input strings. */ -class DefaultMaskParser extends InputParser { +public class DefaultMaskParser extends InputParser { - protected DefaultMaskParser(WorldEdit worldEdit) { + public DefaultMaskParser(WorldEdit worldEdit) { super(worldEdit); } - @Override - public Mask parseFromInput(String input, ParserContext context) throws InputParseException { - List masks = new ArrayList<>(); - - for (String component : input.split(" ")) { - if (component.isEmpty()) { - continue; - } - - Mask current = getBlockMaskComponent(masks, component, context); - - masks.add(current); - } - - switch (masks.size()) { - case 0: - return null; - - case 1: - return masks.get(0); - - default: - return new MaskIntersection(masks); - } - } - - private Mask getBlockMaskComponent(List masks, String component, ParserContext context) throws InputParseException { + public Mask parseFromInput(String component, ParserContext context) throws InputParseException { Extent extent = Request.request().getEditSession(); final char firstChar = component.charAt(0); switch (firstChar) { - case '#': - if (component.equalsIgnoreCase("#existing")) { - return new ExistingBlockMask(extent); - } else if (component.equalsIgnoreCase("#solid")) { - return new SolidBlockMask(extent); - } else if (component.equalsIgnoreCase("#dregion") - || component.equalsIgnoreCase("#dselection") - || component.equalsIgnoreCase("#dsel")) { - return new RegionMask(new RequestSelection()); - } else if (component.equalsIgnoreCase("#selection") - || component.equalsIgnoreCase("#region") - || component.equalsIgnoreCase("#sel")) { - try { - return new RegionMask(context.requireSession().getSelection(context.requireWorld()).clone()); - } catch (IncompleteRegionException e) { - throw new InputParseException("Please make a selection first."); - } - } else if (component.startsWith("##")) { - // This means it's a tag mask. - BlockCategory category = BlockCategories.get(component.substring(2).toLowerCase()); - if (category == null) { - throw new NoMatchException("Unrecognised tag '" + component.substring(2) + '\''); - } else { - return new BlockCategoryMask(extent, category); - } - } else { - throw new NoMatchException("Unrecognized mask '" + component + '\''); - } - case '>': case '<': Mask submask; if (component.length() > 1) { - submask = getBlockMaskComponent(masks, component.substring(1), context); + submask = worldEdit.getMaskFactory().parseFromInput(component.substring(1), context); } else { submask = new ExistingBlockMask(extent); } @@ -141,8 +75,7 @@ class DefaultMaskParser extends InputParser { case '$': Set biomes = new HashSet<>(); String[] biomesList = component.substring(1).split(","); - BiomeRegistry biomeRegistry = WorldEdit.getInstance().getPlatformManager() - .queryCapability(Capability.GAME_HOOKS).getRegistries().getBiomeRegistry(); + BiomeRegistry biomeRegistry = worldEdit.getPlatformManager().queryCapability(Capability.GAME_HOOKS).getRegistries().getBiomeRegistry(); List knownBiomes = biomeRegistry.getBiomes(); for (String biomeName : biomesList) { BaseBiome biome = Biomes.findBiomeByName(knownBiomes, biomeName, biomeRegistry); @@ -154,10 +87,6 @@ class DefaultMaskParser extends InputParser { return Masks.asMask(new BiomeMask2D(context.requireExtent(), biomes)); - case '%': - int i = Integer.parseInt(component.substring(1)); - return new NoiseFilter(new RandomNoise(), ((double) i) / 100); - case '=': try { Expression exp = Expression.compile(component.substring(1), "x", "y", "z"); @@ -169,11 +98,6 @@ class DefaultMaskParser extends InputParser { throw new InputParseException("Invalid expression: " + e.getMessage()); } - case '!': - if (component.length() > 1) { - return Masks.negate(getBlockMaskComponent(masks, component.substring(1), context)); - } - default: ParserContext tempContext = new ParserContext(context); tempContext.setRestricted(false); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExistingMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExistingMaskParser.java new file mode 100644 index 000000000..a1dea6f48 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExistingMaskParser.java @@ -0,0 +1,51 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extension.factory.parser.mask; + +import com.google.common.collect.Lists; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.function.mask.ExistingBlockMask; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.internal.registry.SimpleInputParser; +import com.sk89q.worldedit.session.request.Request; + +import java.util.List; + +public class ExistingMaskParser extends SimpleInputParser { + + public ExistingMaskParser(WorldEdit worldEdit) { + super(worldEdit); + } + + @Override + public List getMatchedAliases() { + return Lists.newArrayList("#existing"); + } + + @Override + public Mask parseFromSimpleInput(String input, ParserContext context) throws InputParseException { + Extent extent = Request.request().getEditSession(); + + return new ExistingBlockMask(extent); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/LazyRegionMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/LazyRegionMaskParser.java new file mode 100644 index 000000000..82bc14d2b --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/LazyRegionMaskParser.java @@ -0,0 +1,48 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extension.factory.parser.mask; + +import com.google.common.collect.Lists; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.RegionMask; +import com.sk89q.worldedit.internal.registry.SimpleInputParser; +import com.sk89q.worldedit.session.request.RequestSelection; + +import java.util.List; + +public class LazyRegionMaskParser extends SimpleInputParser { + + public LazyRegionMaskParser(WorldEdit worldEdit) { + super(worldEdit); + } + + @Override + public List getMatchedAliases() { + return Lists.newArrayList("#dregion", "#dselection", "#dsel"); + } + + @Override + public Mask parseFromSimpleInput(String input, ParserContext context) throws InputParseException { + return new RegionMask(new RequestSelection()); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/NegateMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/NegateMaskParser.java new file mode 100644 index 000000000..9e1c2e9df --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/NegateMaskParser.java @@ -0,0 +1,47 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extension.factory.parser.mask; + +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.Masks; +import com.sk89q.worldedit.internal.registry.InputParser; + +public class NegateMaskParser extends InputParser { + + public NegateMaskParser(WorldEdit worldEdit) { + super(worldEdit); + } + + @Override + public Mask parseFromInput(String input, ParserContext context) throws InputParseException { + if (!input.startsWith("!")) { + return null; + } + + if (input.length() > 1) { + return Masks.negate(worldEdit.getMaskFactory().parseFromInput(input.substring(1), context)); + } else { + throw new InputParseException("Can't negate nothing!"); + } + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/NoiseMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/NoiseMaskParser.java new file mode 100644 index 000000000..0cb1a85e8 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/NoiseMaskParser.java @@ -0,0 +1,45 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extension.factory.parser.mask; + +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.NoiseFilter; +import com.sk89q.worldedit.internal.registry.InputParser; +import com.sk89q.worldedit.math.noise.RandomNoise; + +public class NoiseMaskParser extends InputParser { + + public NoiseMaskParser(WorldEdit worldEdit) { + super(worldEdit); + } + + @Override + public Mask parseFromInput(String input, ParserContext context) throws InputParseException { + if (!input.startsWith("%")) { + return null; + } + + int i = Integer.parseInt(input.substring(1)); + return new NoiseFilter(new RandomNoise(), ((double) i) / 100); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/RegionMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/RegionMaskParser.java new file mode 100644 index 000000000..21963835d --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/RegionMaskParser.java @@ -0,0 +1,52 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extension.factory.parser.mask; + +import com.google.common.collect.Lists; +import com.sk89q.worldedit.IncompleteRegionException; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.RegionMask; +import com.sk89q.worldedit.internal.registry.SimpleInputParser; + +import java.util.List; + +public class RegionMaskParser extends SimpleInputParser { + + public RegionMaskParser(WorldEdit worldEdit) { + super(worldEdit); + } + + @Override + public List getMatchedAliases() { + return Lists.newArrayList("#region", "#selection", "#sel"); + } + + @Override + public Mask parseFromSimpleInput(String input, ParserContext context) throws InputParseException { + try { + return new RegionMask(context.requireSession().getSelection(context.requireWorld()).clone()); + } catch (IncompleteRegionException e) { + throw new InputParseException("Please make a selection first."); + } + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/SolidMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/SolidMaskParser.java new file mode 100644 index 000000000..84df2fec8 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/SolidMaskParser.java @@ -0,0 +1,51 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extension.factory.parser.mask; + +import com.google.common.collect.Lists; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.SolidBlockMask; +import com.sk89q.worldedit.internal.registry.SimpleInputParser; +import com.sk89q.worldedit.session.request.Request; + +import java.util.List; + +public class SolidMaskParser extends SimpleInputParser { + + public SolidMaskParser(WorldEdit worldEdit) { + super(worldEdit); + } + + @Override + public List getMatchedAliases() { + return Lists.newArrayList("#solid"); + } + + @Override + public Mask parseFromSimpleInput(String input, ParserContext context) throws InputParseException { + Extent extent = Request.request().getEditSession(); + + return new SolidBlockMask(extent); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/HashTagPatternParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/ClipboardPatternParser.java similarity index 53% rename from worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/HashTagPatternParser.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/ClipboardPatternParser.java index fe28aafe8..9bf102f32 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/HashTagPatternParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/ClipboardPatternParser.java @@ -17,8 +17,9 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.extension.factory; +package com.sk89q.worldedit.extension.factory.parser.pattern; +import com.google.common.collect.Lists; import com.sk89q.worldedit.EmptyClipboardException; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; @@ -27,37 +28,36 @@ import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.function.pattern.ClipboardPattern; import com.sk89q.worldedit.function.pattern.Pattern; -import com.sk89q.worldedit.internal.registry.InputParser; +import com.sk89q.worldedit.internal.registry.SimpleInputParser; import com.sk89q.worldedit.session.ClipboardHolder; -class HashTagPatternParser extends InputParser { +import java.util.List; - HashTagPatternParser(WorldEdit worldEdit) { +public class ClipboardPatternParser extends SimpleInputParser { + + public ClipboardPatternParser(WorldEdit worldEdit) { super(worldEdit); } @Override - public Pattern parseFromInput(String input, ParserContext context) throws InputParseException { - if (input.charAt(0) == '#') { - if (!input.equals("#clipboard") && !input.equals("#copy")) { - throw new InputParseException("#clipboard or #copy is acceptable for patterns starting with #"); - } + public List getMatchedAliases() { + return Lists.newArrayList("#clipboard", "#copy"); + } - LocalSession session = context.requireSession(); + @Override + public Pattern parseFromSimpleInput(String input, ParserContext context) throws InputParseException { + LocalSession session = context.requireSession(); - if (session != null) { - try { - ClipboardHolder holder = session.getClipboard(); - Clipboard clipboard = holder.getClipboard(); - return new ClipboardPattern(clipboard); - } catch (EmptyClipboardException e) { - throw new InputParseException("To use #clipboard, please first copy something to your clipboard"); - } - } else { - throw new InputParseException("No session is available, so no clipboard is available"); + if (session != null) { + try { + ClipboardHolder holder = session.getClipboard(); + Clipboard clipboard = holder.getClipboard(); + return new ClipboardPattern(clipboard); + } catch (EmptyClipboardException e) { + throw new InputParseException("To use #clipboard, please first copy something to your clipboard"); } } else { - return null; + throw new InputParseException("No session is available, so no clipboard is available"); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/RandomPatternParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/RandomPatternParser.java similarity index 91% rename from worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/RandomPatternParser.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/RandomPatternParser.java index 010a6f01f..0cfdebb42 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/RandomPatternParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/RandomPatternParser.java @@ -17,10 +17,11 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.extension.factory; +package com.sk89q.worldedit.extension.factory.parser.pattern; import com.sk89q.util.StringUtil; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.factory.BlockFactory; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.function.pattern.BlockPattern; @@ -29,9 +30,9 @@ import com.sk89q.worldedit.function.pattern.RandomPattern; import com.sk89q.worldedit.internal.registry.InputParser; import com.sk89q.worldedit.world.block.BlockStateHolder; -class RandomPatternParser extends InputParser { +public class RandomPatternParser extends InputParser { - RandomPatternParser(WorldEdit worldEdit) { + public RandomPatternParser(WorldEdit worldEdit) { super(worldEdit); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/SingleBlockPatternParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/SingleBlockPatternParser.java similarity index 89% rename from worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/SingleBlockPatternParser.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/SingleBlockPatternParser.java index cd3adb5e7..960983780 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/SingleBlockPatternParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/pattern/SingleBlockPatternParser.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.extension.factory; +package com.sk89q.worldedit.extension.factory.parser.pattern; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.input.InputParseException; @@ -26,9 +26,9 @@ import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.internal.registry.InputParser; -class SingleBlockPatternParser extends InputParser { +public class SingleBlockPatternParser extends InputParser { - SingleBlockPatternParser(WorldEdit worldEdit) { + public SingleBlockPatternParser(WorldEdit worldEdit) { super(worldEdit); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/AbstractFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/AbstractFactory.java index 506663a81..bdd40c104 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/AbstractFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/AbstractFactory.java @@ -21,12 +21,14 @@ package com.sk89q.worldedit.internal.registry; import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.collect.Lists; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.NoMatchException; import com.sk89q.worldedit.extension.input.ParserContext; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -38,7 +40,7 @@ import java.util.List; public abstract class AbstractFactory { protected final WorldEdit worldEdit; - protected final List> parsers = new ArrayList<>(); + private final List> parsers = new ArrayList<>(); /** * Create a new factory. @@ -50,6 +52,17 @@ public abstract class AbstractFactory { this.worldEdit = worldEdit; } + /** + * Gets an immutable list of parsers. + * + * To add parsers, use the register method. + * + * @return the parsers + */ + public List> getParsers() { + return Collections.unmodifiableList(parsers); + } + public E parseFromInput(String input, ParserContext context) throws InputParseException { E match; @@ -64,4 +77,14 @@ public abstract class AbstractFactory { throw new NoMatchException("No match for '" + input + "'"); } + /** + * Registers an InputParser to this factory + * + * @param inputParser The input parser + */ + public void register(InputParser inputParser) { + checkNotNull(inputParser); + + parsers.add(inputParser); + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/InputParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/InputParser.java index 77c05c2e3..ee40fa3b9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/InputParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/InputParser.java @@ -19,10 +19,13 @@ package com.sk89q.worldedit.internal.registry; +import com.google.common.collect.Lists; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; +import java.util.List; + /** * Input parser interface for {@link AbstractFactory}. * @@ -33,10 +36,18 @@ public abstract class InputParser { protected final WorldEdit worldEdit; - protected InputParser(WorldEdit worldEdit) { + public InputParser(WorldEdit worldEdit) { this.worldEdit = worldEdit; } public abstract E parseFromInput(String input, ParserContext context) throws InputParseException; + /** + * Gets a list of suggestions of input to this parser. + * + * @return a list of suggestions + */ + public List getSuggestions() { + return Lists.newArrayList(); + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/SimpleInputParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/SimpleInputParser.java new file mode 100644 index 000000000..d0647f9cc --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/registry/SimpleInputParser.java @@ -0,0 +1,71 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.internal.registry; + +import com.google.common.collect.Lists; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; + +import java.util.List; + +/** + * An input parser that only performs a single function from aliases. + * + * @param the element + */ +public abstract class SimpleInputParser extends InputParser { + + public SimpleInputParser(WorldEdit worldEdit) { + super(worldEdit); + } + + /** + * The strings this parser matches + * + * @return the matching aliases + */ + public abstract List getMatchedAliases(); + + @Override + public E parseFromInput(String input, ParserContext context) throws InputParseException { + if (!getMatchedAliases().contains(input)) { + return null; + } + + return parseFromSimpleInput(input, context); + } + + public abstract E parseFromSimpleInput(String input, ParserContext context) throws InputParseException; + + /** + * Gets the primary name of this matcher + * + * @return the primary match + */ + public String getPrimaryMatcher() { + return getMatchedAliases().get(0); + } + + @Override + public List getSuggestions() { + return Lists.newArrayList(getPrimaryMatcher()); + } +}