Re-implement richer mask and transform parsing (#1223)

Co-authored-by: dordsor21 <dordsor21@gmail.com>
Co-authored-by: Hannes Greule <SirYwell@users.noreply.github.com>
This commit is contained in:
dordsor21
2021-08-16 10:03:06 +01:00
committed by GitHub
parent 50137b31c4
commit d4d98708f9
109 changed files with 4068 additions and 2414 deletions

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.extension.factory;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.extension.factory.parser.mask.AdjacentMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.AngleMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.RichMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.ExtremaMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.FalseMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.LiquidMaskParser;
@ -71,6 +72,10 @@ import java.util.stream.Collectors;
*/
public final class MaskFactory extends AbstractFactory<Mask> {
//FAWE start - rich mask parsing
private final RichMaskParser richMaskParser;
//FAWE end
/**
* Create a new mask registry.
*
@ -79,6 +84,10 @@ public final class MaskFactory extends AbstractFactory<Mask> {
public MaskFactory(WorldEdit worldEdit) {
super(worldEdit, new BlocksMaskParser(worldEdit));
//FAWE start - rich mask parsing
richMaskParser = new RichMaskParser(worldEdit);
//FAWE end
register(new ExistingMaskParser(worldEdit));
register(new AirMaskParser(worldEdit));
register(new SolidMaskParser(worldEdit));
@ -133,20 +142,63 @@ public final class MaskFactory extends AbstractFactory<Mask> {
continue;
}
Mask match = null;
for (InputParser<Mask> parser : getParsers()) {
match = parser.parseFromInput(component, context);
if (match != null) {
break;
}
//FAWE start - rich mask parsing
Mask match = richMaskParser.parseFromInput(component, context);
if (match != null) {
masks.add(match);
continue;
}
if (match == null) {
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(component)));
}
masks.add(match);
parseFromParsers(context, masks, component);
//FAWE end
}
return getMask(input, masks);
}
//FAWE start - rich mask parsing
private void parseFromParsers(
final ParserContext context,
final List<Mask> masks,
final String component
) {
Mask match = null;
for (InputParser<Mask> parser : getParsers()) {
match = parser.parseFromInput(component, context);
if (match != null) {
break;
}
}
if (match == null) {
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(component)));
}
masks.add(match);
}
/**
* Parses a mask without considering parsing through the {@link RichMaskParser}, therefore not accepting
* "richer" parsing where & and , are used. Exists to prevent stack overflows.
*
* @param input input string
* @param context input context
* @return parsed result
* @throws InputParseException if no result found
*/
public Mask parseWithoutRich(String input, ParserContext context) throws InputParseException {
List<Mask> masks = new ArrayList<>();
for (String component : input.split(" ")) {
if (component.isEmpty()) {
continue;
}
parseFromParsers(context, masks, component);
}
return getMask(input, masks);
}
private Mask getMask(final String input, final List<Mask> masks) {
switch (masks.size()) {
case 0:
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input)));
@ -156,5 +208,6 @@ public final class MaskFactory extends AbstractFactory<Mask> {
return new MaskIntersection(masks).optimize();
}
}
//FAWE end
}

View File

@ -19,24 +19,56 @@
package com.sk89q.worldedit.extension.factory;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.AngleColorPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.AverageColorPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.BiomePatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.BufferedPattern2DParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.BufferedPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.ColorPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.DarkenPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.DesaturatePatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.ExistingPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.ExpressionPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.LightenPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.Linear2DPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.Linear3DPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.LinearPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.MaskedPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.NoXPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.NoYPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.NoZPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.OffsetPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.PerlinPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RandomFullClipboardPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RandomOffsetPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RandomPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RelativePatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RichPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RidgedMultiFractalPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.SaturatePatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.SimplexPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.SolidRandomOffsetPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.SurfaceRandomOffsetPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.VoronoiPatternParser;
import com.fastasyncworldedit.core.math.random.TrueRandom;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.factory.parser.pattern.BlockCategoryPatternParser;
import com.sk89q.worldedit.extension.factory.parser.pattern.ClipboardPatternParser;
import com.sk89q.worldedit.extension.factory.parser.pattern.RandomStatePatternParser;
import com.sk89q.worldedit.extension.factory.parser.pattern.SingleBlockPatternParser;
import com.sk89q.worldedit.extension.factory.parser.pattern.TypeOrStateApplyingPatternParser;
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.pattern.Pattern;
import com.sk89q.worldedit.function.pattern.RandomPattern;
import com.sk89q.worldedit.internal.registry.AbstractFactory;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import java.util.ArrayList;
import java.util.List;
/**
* A registry of known {@link Pattern}s. Provides methods to instantiate
@ -47,6 +79,10 @@ import com.sk89q.worldedit.internal.registry.AbstractFactory;
*/
public final class PatternFactory extends AbstractFactory<Pattern> {
//FAWE start - rich pattern parsing
private final RichPatternParser richPatternParser;
//FAWE end
/**
* Create a new instance.
*
@ -55,6 +91,10 @@ public final class PatternFactory extends AbstractFactory<Pattern> {
public PatternFactory(WorldEdit worldEdit) {
super(worldEdit, new SingleBlockPatternParser(worldEdit));
//FAWE start - rich pattern parsing
richPatternParser = new RichPatternParser(worldEdit);
//FAWE end
// split and parse each sub-pattern
register(new RandomPatternParser(worldEdit));
@ -65,16 +105,117 @@ public final class PatternFactory extends AbstractFactory<Pattern> {
register(new BlockCategoryPatternParser(worldEdit));
//FAWE start
register(new SimplexPatternParser(worldEdit));
register(new VoronoiPatternParser(worldEdit));
register(new PerlinPatternParser(worldEdit));
register(new RidgedMultiFractalPatternParser(worldEdit));
register(new AngleColorPatternParser(worldEdit));
register(new AverageColorPatternParser(worldEdit));
register(new BiomePatternParser(worldEdit));
register(new BufferedPatternParser(worldEdit));
register(new BufferedPattern2DParser(worldEdit));
register(new ColorPatternParser(worldEdit));
register(new DarkenPatternParser(worldEdit));
register(new DesaturatePatternParser(worldEdit));
register(new ExistingPatternParser(worldEdit));
register(new ExpressionPatternParser(worldEdit));
register(new LightenPatternParser(worldEdit));
register(new Linear2DPatternParser(worldEdit));
register(new Linear3DPatternParser(worldEdit));
register(new BufferedPatternParser(worldEdit));
register(new ExistingPatternParser(worldEdit));
register(new LinearPatternParser(worldEdit));
register(new MaskedPatternParser(worldEdit));
register(new NoXPatternParser(worldEdit));
register(new NoYPatternParser(worldEdit));
register(new NoZPatternParser(worldEdit));
register(new OffsetPatternParser(worldEdit));
register(new PerlinPatternParser(worldEdit));
register(new RandomFullClipboardPatternParser(worldEdit));
register(new RandomOffsetPatternParser(worldEdit));
register(new RelativePatternParser(worldEdit));
register(new RidgedMultiFractalPatternParser(worldEdit));
register(new SaturatePatternParser(worldEdit));
register(new SimplexPatternParser(worldEdit));
register(new SolidRandomOffsetPatternParser(worldEdit));
register(new SurfaceRandomOffsetPatternParser(worldEdit));
register(new VoronoiPatternParser(worldEdit));
//FAWE end
}
@Override
public Pattern parseFromInput(String input, ParserContext context) throws InputParseException {
List<Pattern> patterns = new ArrayList<>();
for (String component : input.split(" ")) {
if (component.isEmpty()) {
continue;
}
//FAWE start - rich pattern parsing
Pattern match = richPatternParser.parseFromInput(component, context);
if (match != null) {
patterns.add(match);
continue;
}
parseFromParsers(context, patterns, component);
//FAWE end
}
return getPattern(input, patterns);
}
//FAWE start - rich pattern parsing
private void parseFromParsers(
final ParserContext context,
final List<Pattern> patterns,
final String component
) {
Pattern match = null;
for (InputParser<Pattern> parser : getParsers()) {
match = parser.parseFromInput(component, context);
if (match != null) {
break;
}
}
if (match == null) {
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(component)));
}
patterns.add(match);
}
/**
* Parses a pattern without considering parsing through the {@link RichPatternParser}, therefore not accepting
* "richer" parsing where & and , are used. Exists to prevent stack overflows.
*
* @param input input string
* @param context input context
* @return parsed result
* @throws InputParseException if no result found
*/
public Pattern parseWithoutRich(String input, ParserContext context) throws InputParseException {
List<Pattern> patterns = new ArrayList<>();
for (String component : input.split(" ")) {
if (component.isEmpty()) {
continue;
}
parseFromParsers(context, patterns, component);
}
return getPattern(input, patterns);
}
private Pattern getPattern(final String input, final List<Pattern> patterns) {
switch (patterns.size()) {
case 0:
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input)));
case 1:
return patterns.get(0);
default:
RandomPattern randomPattern = new RandomPattern(new TrueRandom());
for (Pattern pattern : patterns) {
randomPattern.add(pattern, 1d);
}
return randomPattern;
}
}
//FAWE end
}

View File

@ -354,6 +354,7 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
throw new InputParseException(Caption.of("worldedit.error.incomplete-region"));
}
state = world.getBlock(primaryPosition);
nbt = state.getNbtData();
//FAWE start
} else if (typeString.matches("slot[0-9]+")) {
int slot = Integer.parseInt(typeString.substring(4)) - 1;
@ -384,9 +385,6 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
throw new NoMatchException(Caption.of("fawe.error.invalid-block-type", TextComponent.of(input)));
}
}
if (nbt == null) {
nbt = state.getNbtData();
}
//FAWE end
blockStates.putAll(parseProperties(state.getBlockType(), stateProperties, context));
@ -477,7 +475,17 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
return validate(context, new SkullBlock(state, type.replace(" ", "_"))); // valid MC usernames
} else {
return validate(context, state.toBaseBlock());
//FAWE start
nbt = state.getNbtData();
BaseBlock result;
if (nbt != null) {
WorldEdit.logger.info(blockStates.size());
result = blockStates.size() > 0 ? state.toBaseBlock(nbt) : new BlanketBaseBlock(state, nbt);
} else {
result = state.toBaseBlock();
}
return validate(context, result);
//FAWE end
}
}

View File

@ -20,6 +20,7 @@
package com.sk89q.worldedit.extension.factory.parser.pattern;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.extension.factory.parser.AliasedParser;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.SuggestionHelper;
import com.sk89q.worldedit.extension.input.InputParseException;
@ -31,11 +32,15 @@ import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.world.block.BlockCategory;
import com.sk89q.worldedit.world.block.BlockType;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Stream;
public class BlockCategoryPatternParser extends InputParser<Pattern> {
//FAWE start - aliased
public class BlockCategoryPatternParser extends InputParser<Pattern> implements AliasedParser {
//FAWE end
public BlockCategoryPatternParser(WorldEdit worldEdit) {
super(worldEdit);
@ -81,4 +86,11 @@ public class BlockCategoryPatternParser extends InputParser<Pattern> {
return randomPattern;
}
//FAWE start - aliased
@Override
public List<String> getMatchedAliases() {
return Collections.singletonList("##");
}
//FAWE end
}

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.extension.factory.parser.pattern;
import com.fastasyncworldedit.core.extension.factory.parser.AliasedParser;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
@ -28,9 +29,13 @@ import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.FuzzyBlockState;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
public class RandomStatePatternParser extends InputParser<Pattern> {
//FAWE start - aliased
public class RandomStatePatternParser extends InputParser<Pattern> implements AliasedParser {
//FAWE end
public RandomStatePatternParser(WorldEdit worldEdit) {
super(worldEdit);
@ -68,4 +73,11 @@ public class RandomStatePatternParser extends InputParser<Pattern> {
}
}
//FAWE start - aliased
@Override
public List<String> getMatchedAliases() {
return Collections.singletonList("*");
}
//FAWE end
}

View File

@ -20,6 +20,7 @@
package com.sk89q.worldedit.extension.factory.parser.pattern;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.extension.factory.parser.AliasedParser;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.SuggestionHelper;
import com.sk89q.worldedit.extension.input.InputParseException;
@ -33,12 +34,15 @@ import com.sk89q.worldedit.function.pattern.TypeApplyingPattern;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
public class TypeOrStateApplyingPatternParser extends InputParser<Pattern> {
//FAWE start - aliased
public class TypeOrStateApplyingPatternParser extends InputParser<Pattern> implements AliasedParser {
//FAWE end
public TypeOrStateApplyingPatternParser(WorldEdit worldEdit) {
super(worldEdit);
@ -128,4 +132,11 @@ public class TypeOrStateApplyingPatternParser extends InputParser<Pattern> {
}
}
//FAWE start - aliased
@Override
public List<String> getMatchedAliases() {
return Collections.singletonList("^");
}
//FAWE end
}