Feature/propagate diff and object cleanup (#1190)

* Feature/main/propagate diff annotations (#1187)

* 25% done

* More work

* More work

* 50%

* More work

* 75%

* 100% & cleanup

* Update adapters

* Squish squash, applesauce

commit 275ba9bd84
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Sat Jul 17 01:10:20 2021 +0200

    Update dependency com.comphenix.protocol:ProtocolLib to v4.7.0 (#1173)

    Co-authored-by: Renovate Bot <bot@renovateapp.com>

commit 9fd8984804
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Sat Jul 17 01:09:29 2021 +0200

    Update dependency org.checkerframework:checker-qual to v3.16.0 (#1184)

    Co-authored-by: Renovate Bot <bot@renovateapp.com>

commit 861fb45e5c
Author: dordsor21 <dordsor21@gmail.com>
Date:   Fri Jul 16 19:07:02 2021 +0100

    Fix #1075

commit 420c45a29a
Author: dordsor21 <dordsor21@gmail.com>
Date:   Fri Jul 16 18:48:21 2021 +0100

    Entity removal should be on the main thread as we're just passing through rather than doing chunk operations
     - Fixes #1164
     - Not working: butcher/remove history

commit 4d4db7dcd0
Author: SirYwell <hannesgreule@outlook.de>
Date:   Fri Jul 16 17:52:44 2021 +0200

    Make sure leaves category is loaded for heightmaps (fixes #1176)

commit c98f6e4f37
Author: dordsor21 <dordsor21@gmail.com>
Date:   Fri Jul 16 10:44:52 2021 +0100

    Do not allow generation commands to generate outside selection

commit 2485f5eccc
Author: dordsor21 <dordsor21@gmail.com>
Date:   Fri Jul 16 10:43:15 2021 +0100

    EditSession needs to override some Extent methods to ensure block changes are correctly set through the various extents
    Fixes #1152

commit d9418ec8ae
Author: dordsor21 <dordsor21@gmail.com>
Date:   Fri Jul 16 09:52:44 2021 +0100

    Undo part of 41073bb1a0
    Fixes #1178

* Update Upstream

fb1fb84 Fixed typo and grammar

* We don't support custom heights yet

* Casing inconsistency

* Address a few comments

* Address comments

* Don't refactor to AP classpath

* Document annotation style

* Refactoring & shade cleanup

* Address a few comments

* More work

* Resolve comments not being resolved yet

* Feature/main/propagate diff annotations (#1187) (#1194)

* Remove beta package, fix history packages, move classes out of object package

* Resolve comments not being resolved yet

* Remove beta package, fix history packages, move classes out of object package

Co-authored-by: NotMyFault <mc.cache@web.de>

* brushes should be under brush

* More refactoring
 - Filters/processors should be in the same place and are related to extents
 - Transforms are in `extent.transform` in upstream

* Move history classes under history

* Update adapters

Co-authored-by: dordsor21 <dordsor21@gmail.com>
This commit is contained in:
NotMyFault
2021-07-23 17:48:51 +02:00
committed by GitHub
parent ad102ab7a9
commit 50ab8ad5c7
799 changed files with 4916 additions and 10589 deletions

View File

@ -0,0 +1,136 @@
// TODO: Ping @MattBDev to reimplement 2020-02-04
//package com.sk89q.worldedit.extension.factory;
//
//import com.boydti.fawe.command.FaweParser;
//import com.boydti.fawe.command.SuggestInputParseException;
//import com.boydti.fawe.object.extent.MultiTransform;
//import com.boydti.fawe.object.extent.RandomTransform;
//import com.boydti.fawe.object.extent.ResettableExtent;
//import com.boydti.fawe.object.random.TrueRandom;
//import com.boydti.fawe.util.StringMan;
//import com.google.common.collect.Iterables;
//import com.sk89q.minecraft.util.commands.CommandLocals;
//import com.sk89q.worldedit.WorldEdit;
////import com.sk89q.worldedit.command.TransformCommands;
//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.Actor;
//import com.sk89q.worldedit.internal.expression.Expression;
//import java.util.ArrayList;
//import java.util.List;
//import java.util.Map;
//
//public class DefaultTransformParser extends FaweParser<ResettableExtent> {
//
// public DefaultTransformParser(WorldEdit worldEdit) {
// super(worldEdit, "transforms");
// }
//
// @Override
// public ResettableExtent parseFromInput(String input, ParserContext context) throws InputParseException {
// if (input.isEmpty()) return null;
//
// List<Double> unionChances = new ArrayList<>();
// List<Double> intersectionChances = new ArrayList<>();
//
// List<ResettableExtent> intersection = new ArrayList<>();
// List<ResettableExtent> union = new ArrayList<>();
// final CommandLocals locals = new CommandLocals();
// Actor actor = context != null ? context.getActor() : null;
// if (actor != null) {
// locals.put(Actor.class, actor);
// }
// try {
// List<Map.Entry<ParseEntry, List<String>>> parsed = parse(input);
// for (Map.Entry<ParseEntry, List<String>> entry : parsed) {
// ParseEntry pe = entry.getKey();
// String command = pe.input;
// ResettableExtent transform;
// double chance = 1;
// if (command.isEmpty()) {
// transform = parseFromInput(StringMan.join(entry.getValue(), ','), context);
// } else {
// List<String> args = entry.getValue();
// String cmdArgs = ((args.isEmpty()) ? "" : " " + StringMan.join(args, " "));
// try {
// transform = parse(command + cmdArgs, context);
// } catch (SuggestInputParseException rethrow) {
// throw rethrow;
// } catch (Throwable e) {
// throw new NoMatchException("See: //transforms");
// }
// if (transform == null) {
// // Legacy syntax
// int percentIndex = command.indexOf('%');
// if (percentIndex != -1) { // Legacy percent pattern
// chance = Expression.compile(command.substring(0, percentIndex)).evaluate();
// command = command.substring(percentIndex + 1);
// if (!entry.getValue().isEmpty()) {
// if (!command.isEmpty()) command += " ";
// command += StringMan.join(entry.getValue(), " ");
// }
// transform = parseFromInput(command, context);
// } else {
// throw new NoMatchException("See: //transforms");
// }
// }
// if (pe.and) { // &
// intersectionChances.add(chance);
// intersection.add(transform);
// } else {
// if (!intersection.isEmpty()) {
// if (intersection.size() == 1) {
// throw new InputParseException("Error, floating &");
// }
// MultiTransform multi = new MultiTransform();
// double total = 0;
// for (int i = 0; i < intersection.size(); i++) {
// Double value = intersectionChances.get(i);
// total += value;
// multi.add(intersection.get(i), value);
// }
// union.add(multi);
// unionChances.add(total);
// intersection.clear();
// intersectionChances.clear();
// }
// unionChances.add(chance);
// union.add(transform);
// }
// }
// }
// } catch (Throwable e) {
// throw new InputParseException(e.getMessage(), e);
// }
// if (!intersection.isEmpty()) {
// if (intersection.size() == 1) {
// throw new InputParseException("Error, floating &");
// }
// MultiTransform multi = new MultiTransform();
// double total = 0;
// for (int i = 0; i < intersection.size(); i++) {
// Double value = intersectionChances.get(i);
// total += value;
// multi.add(intersection.get(i), value);
// }
// union.add(multi);
// unionChances.add(total);
// intersection.clear();
// intersectionChances.clear();
// }
// if (union.isEmpty()) {
// throw new NoMatchException("See: //transforms");
// } else if (union.size() == 1) {
// return union.get(0);
// } else {
// RandomTransform random = new RandomTransform(new TrueRandom());
// for (int i = 0; i < union.size(); i++) {
// random.add(union.get(i), unionChances.get(i));
// }
// return random;
// }
// }
//
//
//}

View File

@ -0,0 +1,150 @@
package com.fastasyncworldedit.core.extension.factory.parser;
import com.fastasyncworldedit.core.configuration.Caption;
import com.google.common.base.Preconditions;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
/**
* A rich parser allows parsing of patterns and masks with extra arguments,
* e.g. #simplex[scale][pattern].
*
* @param <E> the parse result.
*/
public abstract class RichParser<E> extends InputParser<E> {
private final String[] prefixes;
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
* @param aliases the prefix of this parser result.
*/
protected RichParser(WorldEdit worldEdit, String... aliases) {
super(worldEdit);
Preconditions.checkArgument(aliases.length >= 1, "Aliases may not be empty");
this.prefixes = aliases;
}
@NotNull
private static Predicate<String> validPrefix(String other) {
return prefix -> {
if (prefix.length() > other.length()) {
return prefix.startsWith(other);
}
return other.startsWith(prefix);
};
}
@NotNull
private Function<String, Stream<? extends String>> extractArguments(String input) {
return prefix -> {
if (input.length() > prefix.length()) {
// input already contains argument(s) -> extract them
String[] strings = extractArguments(input.substring(prefix.length()), false);
// rebuild the argument string without the last argument
StringBuilder builder = new StringBuilder();
for (int i = 0; i < strings.length - 1; i++) {
builder.append('[').append(strings[i]).append(']');
}
String previous = prefix + builder;
// read the suggestions for the last argument
return getSuggestions(strings[strings.length - 1], strings.length - 1)
.map(suggestion -> previous + "[" + suggestion);
} else {
return Stream.of(prefix);
}
};
}
public String getPrefix() {
return this.prefixes[0];
}
@Override
public Stream<String> getSuggestions(String input) {
return Arrays.stream(this.prefixes)
.filter(validPrefix(input))
.flatMap(extractArguments(input));
}
@Override
public E parseFromInput(String input, ParserContext context) throws InputParseException {
for (String prefix : this.prefixes) {
if (!input.startsWith(prefix)) {
continue;
}
if (input.length() < prefix.length()) {
continue;
}
String[] arguments = extractArguments(input.substring(prefix.length()), true);
return parseFromInput(arguments, context);
}
return null;
}
/**
* Returns a stream of suggestions for the argument at the given index.
*
* @param argumentInput the already provided input for the argument at the given index.
* @param index the index of the argument to get suggestions for.
* @return a stream of suggestions matching the given input for the argument at the given index.
*/
protected abstract Stream<String> getSuggestions(String argumentInput, int index);
/**
* Parses the already split arguments.
*
* @param arguments the array of arguments that were split (can be empty).
* @param context the context of this parsing process.
* @return the resulting parsed type.
* @throws InputParseException if the input couldn't be parsed correctly.
*/
protected abstract E parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException;
/**
* Extracts arguments enclosed by {@code []} into an array.
* Example: {@code [Hello][World]} results in a list containing {@code Hello} and {@code World}.
*
* @param input the input to extract arguments from.
* @param requireClosing whether or not the extraction requires valid bracketing.
* @return an array of extracted arguments.
* @throws InputParseException if {@code requireClosing == true} and the count of [ != the count of ]
*/
protected String[] extractArguments(String input, boolean requireClosing) throws InputParseException {
int open = 0; // the "level"
int openIndex = 0;
int i = 0;
List<String> arguments = new ArrayList<>();
for (; i < input.length(); i++) {
if (input.charAt(i) == '[') {
if (open++ == 0) {
openIndex = i;
}
}
if (input.charAt(i) == ']') {
if (--open == 0) {
arguments.add(input.substring(openIndex + 1, i));
}
}
}
if (!requireClosing && open > 0) {
arguments.add(input.substring(openIndex + 1));
}
if (requireClosing && open != 0) {
throw new InputParseException(Caption.of("fawe.error.invalid-bracketing", TextComponent.of("'[' or ']'?")));
}
return arguments.toArray(new String[0]);
}
}

View File

@ -0,0 +1,50 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.fastasyncworldedit.core.function.mask.AdjacentAnyMask;
import com.fastasyncworldedit.core.function.mask.AdjacentMask;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.SuggestionHelper;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask;
import org.jetbrains.annotations.NotNull;
import java.util.stream.Stream;
public class AdjacentMaskParser extends RichParser<Mask> {
public AdjacentMaskParser(WorldEdit worldEdit) {
super(worldEdit, "~");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index == 0) {
return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream();
} else if (index == 1 || index == 2) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
}
return Stream.empty();
}
@Override
protected Mask parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length == 0) {
return null;
}
Mask subMask = worldEdit.getMaskFactory().parseFromInput(arguments[0], context);
int min = arguments.length > 1 ? Integer.parseInt(arguments[1]) : -1;
int max = arguments.length > 2 ? Integer.parseInt(arguments[2]) : -1;
if (min == -1 && max == -1) {
min = 1;
max = 8;
} else if (max == -1) {
max = min;
}
if (max >= 8 && min == 1) {
return new AdjacentAnyMask(subMask);
}
return new AdjacentMask(subMask, min, max);
}
}

View File

@ -0,0 +1,71 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.function.mask.AngleMask;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.SuggestionHelper;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
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.util.formatting.text.TextComponent;
import org.jetbrains.annotations.NotNull;
import java.util.stream.Stream;
public class AngleMaskParser extends RichParser<Mask> {
private final String[] flags = new String[]{"-o"};
public AngleMaskParser(WorldEdit worldEdit) {
super(worldEdit, "/");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index == 0 || index == 1) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d"));
} else if (index > 1 && index <= 1 + flags.length) {
return Stream.of(flags);
}
return Stream.empty();
}
@Override
protected Mask parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length < 2 || arguments.length > 2 + flags.length) {
return null;
}
String minArg = arguments[0];
String maxArg = arguments[1];
boolean degree = minArg.endsWith("d");
if (degree ^ maxArg.endsWith("d")) {
throw new InputParseException(Caption.of("fawe.error.mask.angle"));
}
boolean overlay = false;
if (arguments.length > 2) {
for (int index = 2; index < 2 + flags.length; index++) {
String flag = arguments[index];
if (flag.equals("-o")) {
overlay = true;
} else {
throw new InputParseException(Caption.of("fawe.error.invalid-flag",
TextComponent.of(flag)));
}
}
}
double min;
double max;
if (degree) {
double minDeg = Double.parseDouble(minArg.substring(0, minArg.length() - 1));
double maxDeg = Double.parseDouble(maxArg.substring(0, maxArg.length() - 1));
min = (Math.tan(minDeg * (Math.PI / 180)));
max = (Math.tan(maxDeg * (Math.PI / 180)));
} else {
min = Double.parseDouble(minArg);
max = Double.parseDouble(maxArg);
}
return new AngleMask(context.getExtent(), min, max, overlay, 1);
}
}

View File

@ -0,0 +1,189 @@
// TODO: Ping @MattBDev to reimplement 2020-02-04
//*
//package com.fastasyncworldedit.core.extension.factory.parser.mask;
//
//import com.boydti.fawe.command.FaweParser;
//import com.boydti.fawe.command.SuggestInputParseException;
//import com.boydti.fawe.config.Caption;
//import com.boydti.fawe.util.StringMan;
//import com.sk89q.minecraft.util.commands.CommandLocals;
//import com.sk89q.worldedit.WorldEdit;
//import com.sk89q.worldedit.extension.input.InputParseException;
//import com.sk89q.worldedit.extension.input.ParserContext;
//import com.sk89q.worldedit.extension.platform.Actor;
//import com.sk89q.worldedit.extent.Extent;
//import com.sk89q.worldedit.function.mask.BlockMaskBuilder;
//import com.sk89q.worldedit.function.mask.Mask;
//import com.sk89q.worldedit.function.mask.MaskIntersection;
//import com.sk89q.worldedit.function.mask.MaskUnion;
//import com.sk89q.worldedit.session.request.Request;
//import com.sk89q.worldedit.world.block.BaseBlock;
//import com.sk89q.worldedit.world.block.BlockStateHolder;
//import com.sk89q.worldedit.world.block.BlockTypes;
//
//import java.util.ArrayList;
//import java.util.List;
//import java.util.Map;
//import java.util.stream.Collectors;
//import java.util.stream.Stream;
//
//public class DefaultMaskParser extends FaweParser<Mask> {
// public DefaultMaskParser(WorldEdit worldEdit) {
// super(worldEdit, "masks");
// }
//
// @Override
// public Mask parseFromInput(String input, ParserContext context) throws InputParseException {
// if (input.isEmpty()) {
// throw new SuggestInputParseException("No input provided", "", () -> Stream.concat(Stream.of("#", ",", "&"), BlockTypes.getNameSpaces().stream().map(n -> n + ":")).collect(Collectors.toList()));
// }
// Extent extent = Request.request().getExtent();
// if (extent == null) extent = context.getExtent();
// List<List<Mask>> masks = new ArrayList<>();
// masks.add(new ArrayList<>());
//
// final CommandLocals locals = new CommandLocals();
// Actor actor = context != null ? context.getActor() : null;
// if (actor != null) {
// locals.put(Actor.class, actor);
// }
// try {
// List<Map.Entry<ParseEntry, List<String>>> parsed = parse(input);
// for (Map.Entry<ParseEntry, List<String>> entry : parsed) {
// ParseEntry pe = entry.getKey();
// final String command = pe.input;
// String full = pe.full;
// Mask mask = null;
// if (command.isEmpty()) {
// mask = parseFromInput(StringMan.join(entry.getValue(), ','), context);
// } else {
// List<String> args = entry.getValue();
// String cmdArgs = ((args.isEmpty()) ? "" : " " + StringMan.join(args, " "));
// try {
// mask = parse(command + cmdArgs, context);
// } catch (SuggestInputParseException rethrow) {
// throw rethrow;
// } catch (Throwable e) {
// // TODO NOT IMPLEMENTED
//// throw SuggestInputParseException.of(e, full, () -> {
//// try {
//// List<String> suggestions = dispatcher.get(command).getCallable().getSuggestions(cmdArgs, locals);
//// if (suggestions.size() <= 2) {
//// for (int i = 0; i < suggestions.size(); i++) {
//// String suggestion = suggestions.get(i);
//// if (suggestion.indexOf(' ') != 0) {
//// String[] split = suggestion.split(" ");
//// suggestion = "[" + StringMan.join(split, "][") + "]";
//// suggestions.set(i, suggestion);
//// }
//// }
//// }
//// return suggestions;
//// } catch (CommandException e1) {
//// throw new InputParseException(e1.getMessage());
//// } catch (Throwable e2) {
//// e2.printStackTrace();
//// throw new InputParseException(e2.getMessage());
//// }
//// });
// }
// if (mask == null) {
// // Legacy patterns
// char char0 = command.charAt(0);
// boolean charMask = input.length() > 1 && input.charAt(1) != '[';
// if (charMask && input.charAt(0) == '=') {
// return parseFromInput(char0 + "[" + input.substring(1) + "]", context);
// }
// if (char0 == '#' || char0 == '?') {
// // TODO NOT IMPLEMENTED
//// throw new SuggestInputParseException(new NoMatchException("Unknown mask: " + full + ", See: //masks"), full,
//// () -> {
//// if (full.length() == 1) return new ArrayList<>(dispatcher.getPrimaryAliases());
//// return dispatcher.getAliases().stream().filter(
//// s -> s.startsWith(command.toLowerCase(Locale.ROOT))
//// ).collect(Collectors.toList());
//// }
//// );
// }
// // Legacy syntax
// if (charMask) {
// switch (char0) {
// case '\\': //
// case '/': //
// case '{': //
// case '$': //
// case '%': {
// String value = command.substring(1) + ((entry.getValue().isEmpty()) ? "" : "[" + StringMan.join(entry.getValue(), "][") + "]");
// if (value.contains(":")) {
// if (value.charAt(0) == ':') value.replaceFirst(":", "");
// value = value.replaceAll(":", "][");
// }
// mask = parseFromInput("#" + char0 + "[" + value + "]", context);
// break;
// }
// case '|':
// case '~':
// case '<':
// case '>':
// case '!':
// input = input.substring(input.indexOf(char0) + 1);
// mask = parseFromInput(char0 + "[" + input + "]", context);
// if (actor != null) {
// actor.print(Caption.of("fawe.worldedit.help.command.clarifying.bracket", char0 + "[" + input + "]"));
// }
// return mask;
// }
// }
// }
// if (mask == null) {
// if (command.startsWith("[")) {
// int end = command.lastIndexOf(']');
// mask = parseFromInput(command.substring(1, end == -1 ? command.length() : end), context);
// } else {
// List<String> entries = entry.getValue();
// BlockMaskBuilder builder = new BlockMaskBuilder();
//// if (StringMan.containsAny(full, "\\^$.|?+(){}<>~$!%^&*+-/"))
// {
// try {
// builder.addRegex(full);
// } catch (InputParseException ignored) {}
// }
// if (mask == null) {
// context.setPreferringWildcard(false);
// context.setRestricted(false);
// BaseBlock block = worldEdit.getBlockFactory().parseFromInput(full, context);
// builder.add(block);
// mask = builder.build(extent);
// }
// }
// }
// }
// if (pe.and) {
// masks.add(new ArrayList<>());
// }
// masks.get(masks.size() - 1).add(mask);
// }
// } catch (InputParseException rethrow) {
// throw rethrow;
// } catch (Throwable e) {
// e.printStackTrace();
// throw new InputParseException(e.getMessage(), e);
// }
// List<Mask> maskUnions = new ArrayList<>();
// for (List<Mask> maskList : masks) {
// if (maskList.size() == 1) {
// maskUnions.add(maskList.get(0));
// } else if (maskList.size() != 0) {
// maskUnions.add(new MaskUnion(maskList));
// }
// }
// if (maskUnions.size() == 1) {
// return maskUnions.get(0);
// } else if (maskUnions.size() != 0) {
// return new MaskIntersection(maskUnions);
// } else {
// return null;
// }
//
// }
//}

View File

@ -0,0 +1,71 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.function.mask.ExtremaMask;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.SuggestionHelper;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
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.util.formatting.text.TextComponent;
import org.jetbrains.annotations.NotNull;
import java.util.stream.Stream;
public class ExtremaMaskParser extends RichParser<Mask> {
private final String[] flags = new String[]{"-o"};
public ExtremaMaskParser(WorldEdit worldEdit) {
super(worldEdit, "#extrema");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index == 0 || index == 1) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d"));
} else if (index > 1 && index <= 1 + flags.length) {
return Stream.of(flags);
}
return Stream.empty();
}
@Override
protected Mask parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length < 2 || arguments.length > 2 + flags.length) {
return null;
}
String minArg = arguments[0];
String maxArg = arguments[1];
boolean degree = minArg.endsWith("d");
if (degree ^ maxArg.endsWith("d")) {
throw new InputParseException(Caption.of("fawe.error.mask.angle"));
}
double min;
double max;
boolean overlay = false;
if (arguments.length > 2) {
for (int index = 2; index < 2 + flags.length; index++) {
String flag = arguments[index];
if (flag.equals("-o")) {
overlay = true;
} else {
throw new InputParseException(Caption.of("fawe.error.invalid-flag",
TextComponent.of(flag)));
}
}
}
if (degree) {
double minDeg = Double.parseDouble(minArg.substring(0, minArg.length() - 1));
double maxDeg = Double.parseDouble(maxArg.substring(0, maxArg.length() - 1));
min = (Math.tan(minDeg * (Math.PI / 180)));
max = (Math.tan(maxDeg * (Math.PI / 180)));
} else {
min = Double.parseDouble(minArg);
max = Double.parseDouble(maxArg);
}
return new ExtremaMask(context.getExtent(), min, max, overlay, 4);
}
}

View File

@ -0,0 +1,29 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.google.common.collect.ImmutableList;
import com.sk89q.worldedit.WorldEdit;
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.SimpleInputParser;
import java.util.List;
public class FalseMaskParser extends SimpleInputParser<Mask> {
private final List<String> aliases = ImmutableList.of("#false");
public FalseMaskParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public List<String> getMatchedAliases() {
return aliases;
}
@Override
public Mask parseFromSimpleInput(String input, ParserContext context) {
return Masks.alwaysFalse();
}
}

View File

@ -0,0 +1,29 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.fastasyncworldedit.core.function.mask.LiquidMask;
import com.google.common.collect.ImmutableList;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.internal.registry.SimpleInputParser;
import java.util.List;
public class LiquidMaskParser extends SimpleInputParser<Mask> {
private final List<String> aliases = ImmutableList.of("#liquid");
public LiquidMaskParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public List<String> getMatchedAliases() {
return aliases;
}
@Override
public Mask parseFromSimpleInput(String input, ParserContext context) {
return new LiquidMask(context.getExtent());
}
}

View File

@ -0,0 +1,71 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.function.mask.ROCAngleMask;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.SuggestionHelper;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
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.util.formatting.text.TextComponent;
import org.jetbrains.annotations.NotNull;
import java.util.stream.Stream;
public class ROCAngleMaskParser extends RichParser<Mask> {
private final String[] flags = new String[]{"-o"};
public ROCAngleMaskParser(WorldEdit worldEdit) {
super(worldEdit, "#roc");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index == 0 || index == 1) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d"));
} else if (index > 1 && index <= 1 + flags.length) {
return Stream.of(flags);
}
return Stream.empty();
}
@Override
protected Mask parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length < 2 || arguments.length > 2 + flags.length) {
return null;
}
String minArg = arguments[0];
String maxArg = arguments[1];
boolean degree = minArg.endsWith("d");
if (degree ^ maxArg.endsWith("d")) {
throw new InputParseException(Caption.of("fawe.error.mask.angle"));
}
double min;
double max;
boolean overlay = false;
if (arguments.length > 2) {
for (int index = 2; index < 2 + flags.length; index++) {
String flag = arguments[index];
if (flag.equals("-o")) {
overlay = true;
} else {
throw new InputParseException(Caption.of("fawe.error.invalid-flag",
TextComponent.of(flag)));
}
}
}
if (degree) {
double minDeg = Double.parseDouble(minArg.substring(0, minArg.length() - 1));
double maxDeg = Double.parseDouble(maxArg.substring(0, maxArg.length() - 1));
min = (Math.tan(minDeg * (Math.PI / 180)));
max = (Math.tan(maxDeg * (Math.PI / 180)));
} else {
min = Double.parseDouble(minArg);
max = Double.parseDouble(maxArg);
}
return new ROCAngleMask(context.getExtent(), min, max, overlay, 4);
}
}

View File

@ -0,0 +1,37 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.fastasyncworldedit.core.function.mask.RadiusMask;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.SuggestionHelper;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask;
import org.jetbrains.annotations.NotNull;
import java.util.stream.Stream;
public class RadiusMaskParser extends RichParser<Mask> {
public RadiusMaskParser(WorldEdit worldEdit) {
super(worldEdit, "{");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index == 0 || index == 1) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
}
return Stream.empty();
}
@Override
protected Mask parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length < 2) {
return null;
}
int min = Integer.parseInt(arguments[0]);
int max = Integer.parseInt(arguments[1]);
return new RadiusMask(min, max);
}
}

View File

@ -0,0 +1,51 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.SuggestionHelper;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
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.MaskIntersection;
import com.sk89q.worldedit.function.mask.Masks;
import com.sk89q.worldedit.function.mask.OffsetMask;
import com.sk89q.worldedit.math.BlockVector3;
import org.jetbrains.annotations.NotNull;
import java.util.stream.Stream;
public class RichOffsetMaskParser extends RichParser<Mask> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public RichOffsetMaskParser(WorldEdit worldEdit) {
super(worldEdit, "#offset");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index < 3) {
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
}
if (index == 3) {
return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream();
}
return Stream.empty();
}
@Override
protected Mask parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length != 4) {
return null;
}
int x = Integer.parseInt(arguments[0]);
int y = Integer.parseInt(arguments[1]);
int z = Integer.parseInt(arguments[2]);
Mask submask = worldEdit.getMaskFactory().parseFromInput(arguments[3], context);
OffsetMask offsetMask = new OffsetMask(submask, BlockVector3.at(x, y, z));
return new MaskIntersection(offsetMask, Masks.negate(submask));
}
}

View File

@ -0,0 +1,42 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.fastasyncworldedit.core.function.mask.SimplexMask;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.SuggestionHelper;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask;
import org.jetbrains.annotations.NotNull;
import java.util.stream.Stream;
public class SimplexMaskParser extends RichParser<Mask> {
private static final String SIMPLEX_PREFIX = "#simplex";
public SimplexMaskParser(WorldEdit worldEdit) {
super(worldEdit, SIMPLEX_PREFIX);
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index < 3) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
}
return Stream.empty();
}
@Override
protected Mask parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length != 3) {
return null;
}
double scale = Double.parseDouble(arguments[0]);
double min = Double.parseDouble(arguments[1]);
double max = Double.parseDouble(arguments[2]);
scale = 1d / Math.max(1d, scale);
min = (min - 50d) / 50d;
max = (max - 50d) / 50d;
return new SimplexMask(scale, min, max);
}
}

View File

@ -0,0 +1,30 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.fastasyncworldedit.core.function.mask.SurfaceMask;
import com.google.common.collect.ImmutableList;
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.internal.registry.SimpleInputParser;
import java.util.List;
public class SurfaceMaskParser extends SimpleInputParser<Mask> {
private final List<String> aliases = ImmutableList.of("#surface");
public SurfaceMaskParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public List<String> getMatchedAliases() {
return aliases;
}
@Override
public Mask parseFromSimpleInput(String input, ParserContext context) throws InputParseException {
return new SurfaceMask(context.getExtent());
}
}

View File

@ -0,0 +1,29 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.google.common.collect.ImmutableList;
import com.sk89q.worldedit.WorldEdit;
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.SimpleInputParser;
import java.util.List;
public class TrueMaskParser extends SimpleInputParser<Mask> {
private final List<String> aliases = ImmutableList.of("#true");
public TrueMaskParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public List<String> getMatchedAliases() {
return aliases;
}
@Override
public Mask parseFromSimpleInput(String input, ParserContext context) {
return Masks.alwaysTrue();
}
}

View File

@ -0,0 +1,34 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.fastasyncworldedit.core.function.mask.WallMask;
import com.google.common.collect.ImmutableList;
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.BlockMask;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.MaskIntersection;
import com.sk89q.worldedit.internal.registry.SimpleInputParser;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.List;
public class WallMaskParser extends SimpleInputParser<Mask> {
private final List<String> aliases = ImmutableList.of("#wall");
public WallMaskParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public List<String> getMatchedAliases() {
return aliases;
}
@Override
public Mask parseFromSimpleInput(String input, ParserContext context) throws InputParseException {
return new MaskIntersection(new ExistingBlockMask(context.getExtent()), new WallMask(new BlockMask(context.getExtent(), BlockTypes.AIR.getDefaultState().toBaseBlock()), 1, 8));
}
}

View File

@ -0,0 +1,29 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.fastasyncworldedit.core.function.mask.XAxisMask;
import com.google.common.collect.ImmutableList;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.internal.registry.SimpleInputParser;
import java.util.List;
public class XAxisMaskParser extends SimpleInputParser<Mask> {
private final List<String> aliases = ImmutableList.of("#xaxis");
public XAxisMaskParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public List<String> getMatchedAliases() {
return aliases;
}
@Override
public Mask parseFromSimpleInput(String input, ParserContext context) {
return new XAxisMask(context.getExtent());
}
}

View File

@ -0,0 +1,29 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.fastasyncworldedit.core.function.mask.YAxisMask;
import com.google.common.collect.ImmutableList;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.internal.registry.SimpleInputParser;
import java.util.List;
public class YAxisMaskParser extends SimpleInputParser<Mask> {
private final List<String> aliases = ImmutableList.of("#yaxis");
public YAxisMaskParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public List<String> getMatchedAliases() {
return aliases;
}
@Override
public Mask parseFromSimpleInput(String input, ParserContext context) {
return new YAxisMask(context.getExtent());
}
}

View File

@ -0,0 +1,29 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.fastasyncworldedit.core.function.mask.ZAxisMask;
import com.google.common.collect.ImmutableList;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.internal.registry.SimpleInputParser;
import java.util.List;
public class ZAxisMaskParser extends SimpleInputParser<Mask> {
private final List<String> aliases = ImmutableList.of("#zaxis");
public ZAxisMaskParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public List<String> getMatchedAliases() {
return aliases;
}
@Override
public Mask parseFromSimpleInput(String input, ParserContext context) {
return new ZAxisMask();
}
}

View File

@ -0,0 +1,74 @@
package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.function.pattern.BiomeApplyingPattern;
import com.sk89q.worldedit.WorldEdit;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
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.util.formatting.text.TextComponent;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import org.jetbrains.annotations.NotNull;
import java.util.stream.Stream;
public class BiomePatternParser extends RichParser<Pattern> {
private final static String BIOME_PREFIX = "$";
/**
* Create a new biome pattern parser.
*
* @param worldEdit the worldedit instance.
*/
public BiomePatternParser(WorldEdit worldEdit) {
super(worldEdit, "#biome");
}
// overridden to provide $<biome> too
@Override
public Pattern parseFromInput(String input, ParserContext context) throws InputParseException {
if (input.startsWith(BIOME_PREFIX)) {
String biomeId = input.substring(1);
BiomeType biomeType = BiomeTypes.get(biomeId);
if (biomeType == null) {
throw new NoMatchException(Caption.of("worldedit.error.unknown-biome", TextComponent.of(biomeId)));
}
return new BiomeApplyingPattern(context.requireExtent(), biomeType);
} else {
return super.parseFromInput(input, context);
}
}
// overridden to provide $<biome> too
@Override
public Stream<String> getSuggestions(String input) {
if (input.startsWith(BIOME_PREFIX)) {
return BiomeType.REGISTRY.getSuggestions(input.substring(1)).map(biome -> BIOME_PREFIX + biome);
} else {
return super.getSuggestions(input);
}
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index == 0) {
return BiomeType.REGISTRY.getSuggestions(argumentInput);
}
return Stream.empty();
}
@Override
protected Pattern parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length != 1) {
throw new InputParseException(Caption.of("fawe.error.invalid-arguments", TextComponent.of("#biome[<biome>]")));
}
BiomeType biomeType = BiomeTypes.get(arguments[0]);
if (biomeType == null) {
throw new NoMatchException(Caption.of("worldedit.error.unknown-biome", TextComponent.of(arguments[0])));
}
return new BiomeApplyingPattern(context.requireExtent(), biomeType);
}
}

View File

@ -0,0 +1,43 @@
package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.function.pattern.BufferedPattern;
import com.sk89q.worldedit.WorldEdit;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import org.jetbrains.annotations.NotNull;
import java.util.stream.Stream;
public class BufferedPatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public BufferedPatternParser(WorldEdit worldEdit) {
super(worldEdit, "#buffer");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index == 0) {
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
}
return Stream.empty();
}
@Override
protected Pattern parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length != 1) {
throw new InputParseException(Caption.of("fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[pattern] (e.g. " + getPrefix() + "[stone,dirt])")));
}
Pattern inner = this.worldEdit.getPatternFactory().parseFromInput(arguments[0], context);
return new BufferedPattern(context.requireActor(), inner);
}
}

View File

@ -0,0 +1,167 @@
// TODO: Ping @MattBDev to reimplement (or remove because this class is stupid) 2020-02-04
///*
//package com.fastasyncworldedit.core.extension.factory.parser.pattern;
//
//import com.boydti.fawe.command.FaweParser;
//import com.boydti.fawe.command.SuggestInputParseException;
//import com.boydti.fawe.object.random.TrueRandom;
//import com.boydti.fawe.util.StringMan;
//import com.google.common.collect.Iterables;
//import com.sk89q.minecraft.util.commands.CommandLocals;
//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.Actor;
//import com.sk89q.worldedit.extension.platform.PlatformCommandManager;
//import com.sk89q.worldedit.function.pattern.Pattern;
//import com.sk89q.worldedit.function.pattern.RandomPattern;
//import com.sk89q.worldedit.internal.expression.Expression;
//import com.sk89q.worldedit.world.block.BlockTypes;
//
//import java.util.ArrayList;
//import java.util.List;
//import java.util.Map;
//import java.util.stream.Collectors;
//import java.util.stream.Stream;
//
//public class DefaultPatternParser extends FaweParser<Pattern> {
//
// public DefaultPatternParser(WorldEdit worldEdit) {
// super(worldEdit, "patterns");
// }
//
// @Override
// public Pattern parseFromInput(String input, ParserContext context) throws InputParseException {
// if (input.isEmpty()) {
// throw new SuggestInputParseException("No input provided", "", () -> Stream.concat(Stream.of("#", ",", "&"), BlockTypes.getNameSpaces().stream().map(n -> n + ":")).collect(Collectors.toList()));
// }
// List<Double> chances = new ArrayList<>();
// List<Pattern> patterns = new ArrayList<>();
// final CommandLocals locals = new CommandLocals();
// Actor actor = context != null ? context.getActor() : null;
// if (actor != null) {
// locals.put(Actor.class, actor);
// }
// try {
// for (Map.Entry<ParseEntry, List<String>> entry : parse(input)) {
// ParseEntry pe = entry.getKey();
// final String command = pe.input;
// String full = pe.full;
// Pattern pattern = null;
// double chance = 1;
// if (command.isEmpty()) {
// pattern = parseFromInput(StringMan.join(entry.getValue(), ','), context);
// } else {
// List<String> args = entry.getValue();
// String cmdArgs = ((args.isEmpty()) ? "" : " " + StringMan.join(args, " "));
// try {
// pattern = parse(command + cmdArgs, context);
// } catch (SuggestInputParseException rethrow) {
// throw rethrow;
// } catch (Throwable e) {
// // TODO NOT IMPLEMENTED
//// throw SuggestInputParseException.of(e, full, () -> {
//// try {
//// List<String> suggestions = dispatcher.get(command).getCallable().getSuggestions(cmdArgs, locals);
//// if (suggestions.size() <= 2) {
//// for (int i = 0; i < suggestions.size(); i++) {
//// String suggestion = suggestions.get(i);
//// if (suggestion.indexOf(' ') != 0) {
//// String[] split = suggestion.split(" ");
//// suggestion = "[" + StringMan.join(split, "][") + "]";
//// suggestions.set(i, suggestion);
//// }
//// }
//// }
//// return suggestions;
//// } catch (CommandException e1) {
//// throw new InputParseException(e1.getMessage());
//// } catch (Throwable e2) {
//// e2.printStackTrace();
//// throw new InputParseException(e2.getMessage());
//// }
//// });
// }
// if (pattern == null) {
// // Legacy patterns
// char char0 = command.charAt(0);
// boolean charMask = input.length() > 1 && input.charAt(1) != '[';
// if (charMask && input.charAt(0) == '=') {
// return parseFromInput(char0 + "[" + input.substring(1) + "]", context);
// }
// if (char0 == '#') {
// // TODO NOT IMPLEMENTED
//// throw new SuggestInputParseException(new NoMatchException("Unknown pattern: " + full + ", See: //patterns"), full,
//// () -> {
//// if (full.length() == 1) return new ArrayList<>(dispatcher.getPrimaryAliases());
//// return dispatcher.getAliases().stream().filter(
//// s -> s.startsWith(command.toLowerCase(Locale.ROOT))
//// ).collect(Collectors.toList());
//// }
//// );
// }
//
//
// if (charMask) {
// if (char0 == '$') {
// String value = command.substring(1) + ((entry.getValue().isEmpty()) ? ""
// : "[" + StringMan.join(entry.getValue(), "][") + "]");
// if (value.contains(":")) {
// if (value.charAt(0) == ':') {
// value.replaceFirst(":", "");
// }
// value = value.replaceAll(":", "][");
// }
// pattern = parseFromInput(char0 + "[" + value + "]", context);
// }
// }
// if (pattern == null) {
// if (command.startsWith("[")) {
// int end = command.lastIndexOf(']');
// pattern = parseFromInput(command.substring(1, end == -1 ? command.length() : end), context);
// } else {
// int percentIndex = command.indexOf('%');
// if (percentIndex != -1) { // Legacy percent pattern
// chance = Expression.compile(command.substring(0, percentIndex)).evaluate();
// String value = command.substring(percentIndex + 1);
// if (!entry.getValue().isEmpty()) {
// if (!value.isEmpty()) value += " ";
// value += StringMan.join(entry.getValue(), " ");
// }
// pattern = parseFromInput(value, context);
// } else { // legacy block pattern
// try {
// pattern = worldEdit.getBlockFactory().parseFromInput(pe.full, context);
// } catch (NoMatchException e) {
// throw new NoMatchException(e.getMessage() + " See: //patterns");
// }
// }
// }
// }
// }
// }
// if (pattern != null) {
// patterns.add(pattern);
// chances.add(chance);
// }
// }
// } catch (InputParseException rethrow) {
// throw rethrow;
// } catch (Throwable e) {
// e.printStackTrace();
// throw new InputParseException(e.getMessage(), e);
// }
// if (patterns.isEmpty()) {
// return null;
// }
// if (patterns.size() == 1) {
// return patterns.get(0);
// }
// RandomPattern random = new RandomPattern(new TrueRandom());
// for (int i = 0; i < patterns.size(); i++) {
// random.add(patterns.get(i), chances.get(i));
// }
// return random;
// }
//}

View File

@ -0,0 +1,29 @@
package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.fastasyncworldedit.core.function.pattern.ExistingPattern;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.registry.SimpleInputParser;
import java.util.Collections;
import java.util.List;
public class ExistingPatternParser extends SimpleInputParser<Pattern> {
private final List<String> aliases = Collections.singletonList("#existing");
public ExistingPatternParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public List<String> getMatchedAliases() {
return this.aliases;
}
@Override
public Pattern parseFromSimpleInput(String input, ParserContext context) throws InputParseException {
return new ExistingPattern(context.requireExtent());
}
}

View File

@ -0,0 +1,71 @@
package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.function.pattern.Linear2DBlockPattern;
import com.google.common.base.Preconditions;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.SuggestionHelper;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.sk89q.worldedit.extension.input.InputParseException;
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.util.formatting.text.TextComponent;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
import java.util.stream.Stream;
public class Linear2DPatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public Linear2DPatternParser(WorldEdit worldEdit) {
super(worldEdit, "#linear2d", "#l2d");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
switch (index) {
case 0:
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
case 1:
case 2:
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
default:
return Stream.empty();
}
}
@Override
protected Pattern parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length == 0 || arguments.length > 3) {
throw new InputParseException(Caption.of("fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[pattern] (e.g. " + getPrefix() + "[stone,dirt])")));
}
Pattern inner = this.worldEdit.getPatternFactory().parseFromInput(arguments[0], context);
if (inner instanceof BlockStateHolder) {
return inner;
}
int xScale = 1;
int zScale = 1;
if (arguments.length > 1) {
xScale = Integer.parseInt(arguments[1]);
Preconditions.checkArgument(xScale != 0);
}
if (arguments.length > 2) {
zScale = Integer.parseInt(arguments[2]);
Preconditions.checkArgument(zScale != 0);
}
if (inner instanceof RandomPattern) {
Set<Pattern> patterns = ((RandomPattern) inner).getPatterns();
return new Linear2DBlockPattern(patterns.toArray(new Pattern[0]), xScale, zScale);
}
throw new InputParseException(TextComponent.of("Pattern " + inner.getClass().getSimpleName()
+ " cannot be used with " + getPrefix()));
}
}

View File

@ -0,0 +1,77 @@
package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.function.pattern.Linear3DBlockPattern;
import com.google.common.base.Preconditions;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.SuggestionHelper;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.sk89q.worldedit.extension.input.InputParseException;
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.util.formatting.text.TextComponent;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
import java.util.stream.Stream;
public class Linear3DPatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public Linear3DPatternParser(WorldEdit worldEdit) {
super(worldEdit, "#linear3d", "#l3d");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
switch (index) {
case 0:
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
case 1:
case 2:
case 3:
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
default:
return Stream.empty();
}
}
@Override
protected Pattern parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length == 0 || arguments.length > 4) {
throw new InputParseException(Caption.of("fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[pattern] (e.g. " + getPrefix() + "[stone,dirt])")));
}
Pattern inner = this.worldEdit.getPatternFactory().parseFromInput(arguments[0], context);
if (inner instanceof BlockStateHolder) {
return inner;
}
int xScale = 1;
int yScale = 1;
int zScale = 1;
if (arguments.length > 1) {
xScale = Integer.parseInt(arguments[1]);
Preconditions.checkArgument(xScale != 0);
}
if (arguments.length > 2) {
yScale = Integer.parseInt(arguments[2]);
Preconditions.checkArgument(yScale != 0);
}
if (arguments.length > 3) {
zScale = Integer.parseInt(arguments[3]);
Preconditions.checkArgument(zScale != 0);
}
if (inner instanceof RandomPattern) {
Set<Pattern> patterns = ((RandomPattern) inner).getPatterns();
return new Linear3DBlockPattern(patterns.toArray(new Pattern[0]), xScale, yScale,zScale);
}
throw new InputParseException(TextComponent.of("Pattern " + inner.getClass().getSimpleName()
+ " cannot be used with " + getPrefix()));
}
}

View File

@ -0,0 +1,77 @@
package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.math.random.NoiseRandom;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.SuggestionHelper;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.sk89q.worldedit.extension.input.InputParseException;
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.math.noise.NoiseGenerator;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
import java.util.stream.Stream;
public abstract class NoisePatternParser extends RichParser<Pattern> {
private final String name;
private final Supplier<NoiseGenerator> generatorSupplier;
/**
* Create a new noise parser with a defined name, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
* @param name the name of this noise.
* @param generatorSupplier the supplier to get a {@link NoiseGenerator} instance from.
*/
protected NoisePatternParser(WorldEdit worldEdit, String name, Supplier<NoiseGenerator> generatorSupplier) {
super(worldEdit, '#' + name);
this.name = name;
this.generatorSupplier = generatorSupplier;
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index == 0) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
}
if (index == 1) {
return worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
}
return Stream.empty();
}
@Override
protected Pattern parseFromInput(@NotNull String[] arguments, ParserContext context) {
if (arguments.length != 2) {
throw new InputParseException(Caption.of("fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[scale][pattern] (e.g. " + getPrefix() + "[5][dirt,stone])")));
}
double scale = parseScale(arguments[0]);
Pattern inner = worldEdit.getPatternFactory().parseFromInput(arguments[1], context);
if (inner instanceof RandomPattern) {
return new RandomPattern(new NoiseRandom(this.generatorSupplier.get(), scale), (RandomPattern) inner);
} else if (inner instanceof BlockStateHolder) {
return inner; // single blocks won't have any impact on how a noise behaves
} else {
throw new InputParseException(TextComponent.of("Pattern " + inner.getClass().getSimpleName()
+ " cannot be used with #" + this.name));
}
}
/**
* Modifies the given argument to match the requirements of the noise generator.
*
* @param argument the parsed scale argument.
* @return the modified scale.
*/
protected double parseScale(String argument) {
double scale = Double.parseDouble(argument);
return 1d / Math.max(1, scale);
}
}

View File

@ -0,0 +1,17 @@
package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.math.noise.PerlinNoise;
public class PerlinPatternParser extends NoisePatternParser {
private static final String PERLIN_NAME = "perlin";
/**
* Create a new perlin noise parser.
*
* @param worldEdit the worldedit instance.
*/
public PerlinPatternParser(WorldEdit worldEdit) {
super(worldEdit, PERLIN_NAME, PerlinNoise::new);
}
}

View File

@ -0,0 +1,80 @@
package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.fastasyncworldedit.core.configuration.Caption;
import com.sk89q.util.StringUtil;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
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.InputParser;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import java.util.List;
import java.util.stream.Stream;
public class RandomPatternParser extends InputParser<Pattern> {
public RandomPatternParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public Stream<String> getSuggestions(String input) {
List<String> patterns = StringUtil.split(input, ',', '[', ']');
/*String[] splits = input.split(",", -1);
List<String> patterns = StringUtil.parseListInQuotes(splits, ',', '[', ']', true);*/
if (patterns.size() == 1) {
return Stream.empty();
}
// get suggestions for the last token only
String token = patterns.get(patterns.size() - 1);
String previous = String.join(",", patterns.subList(0, patterns.size() - 1));
if (token.matches("[0-9]+(\\.[0-9]*)?%.*")) {
String[] p = token.split("%");
if (p.length < 2) {
return Stream.empty();
} else {
token = p[1];
}
}
final List<String> innerSuggestions = worldEdit.getPatternFactory().getSuggestions(token);
return innerSuggestions.stream().map(s -> previous + "," + s);
}
@Override
public Pattern parseFromInput(String input, ParserContext context) throws InputParseException {
RandomPattern randomPattern = new RandomPattern();
List<String> patterns = StringUtil.split(input, ',', '[', ']');
/*String[] splits = input.split(",", -1);
List<String> patterns = StringUtil.parseListInQuotes(splits, ',', '[', ']', true);*/
if (patterns.size() == 1) {
return null; // let a 'single'-pattern parser handle it
}
for (String token : patterns) {
double chance;
Pattern innerPattern;
// Parse special percentage syntax
if (token.matches("[0-9]+(\\.[0-9]*)?%.*")) {
String[] p = token.split("%", 2);
if (p.length < 2) {
throw new InputParseException(Caption.of("worldedit.error.parser.missing-random-type", TextComponent.of(input)));
} else {
chance = Double.parseDouble(p[0]);
innerPattern = worldEdit.getPatternFactory().parseFromInput(p[1], context);
}
} else {
chance = 1;
innerPattern = worldEdit.getPatternFactory().parseFromInput(token, context);
}
randomPattern.add(innerPattern, chance);
}
return randomPattern;
}
}

View File

@ -0,0 +1,18 @@
package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.math.noise.RidgedMultiFractalNoise;
public class RidgedMultiFractalPatternParser extends NoisePatternParser {
private static final String RIDGED_MULTI_FRACTAL_NAME = "rmf";
/**
* Create a new ridged multi fractal noise parser.
*
* @param worldEdit the worldedit instance.
*/
public RidgedMultiFractalPatternParser(WorldEdit worldEdit) {
super(worldEdit, RIDGED_MULTI_FRACTAL_NAME, RidgedMultiFractalNoise::new);
}
}

View File

@ -0,0 +1,12 @@
package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.sk89q.worldedit.WorldEdit;
import com.fastasyncworldedit.core.math.random.SimplexNoiseGenerator;
public class SimplexPatternParser extends NoisePatternParser {
private static final String SIMPLEX_NAME = "simplex";
public SimplexPatternParser(WorldEdit worldEdit) {
super(worldEdit, SIMPLEX_NAME, SimplexNoiseGenerator::new);
}
}

View File

@ -0,0 +1,18 @@
package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.math.noise.VoronoiNoise;
public class VoronoiPatternParser extends NoisePatternParser {
private static final String VORONOI_NAME = "voronoi";
/**
* Create a new voronoi noise parser.
*
* @param worldEdit the worldedit instance.
*/
public VoronoiPatternParser(WorldEdit worldEdit) {
super(worldEdit, VORONOI_NAME, VoronoiNoise::new);
}
}

View File

@ -0,0 +1,9 @@
package com.fastasyncworldedit.core.extension.platform.binding;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Binding {
String value() default "";
}

View File

@ -0,0 +1,135 @@
package com.fastasyncworldedit.core.extension.platform.binding;
import com.fastasyncworldedit.core.util.StringMan;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import org.apache.logging.log4j.Logger;
import org.enginehub.piston.CommandManager;
import org.enginehub.piston.converter.ArgumentConverter;
import org.enginehub.piston.converter.ConversionResult;
import org.enginehub.piston.converter.FailedConversion;
import org.enginehub.piston.converter.SuccessfulConversion;
import org.enginehub.piston.exception.StopExecutionException;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.enginehub.piston.inject.InjectedValueStore;
import org.enginehub.piston.inject.Key;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Optional;
import java.util.function.Function;
public class Bindings {
private static final Logger LOGGER = LogManagerCompat.getLogger();
private final WorldEdit worldEdit;
public Bindings(WorldEdit worldEdit) {
this.worldEdit = worldEdit;
}
public WorldEdit getWorldEdit() {
return worldEdit;
}
public void register(InjectedValueStore store, CommandManager manager) {
for (Method method : getClass().getDeclaredMethods()) {
register(method, store, manager);
}
}
private boolean register(Method method, InjectedValueStore store, CommandManager manager) {
// Check that it has the binding
Binding binding = method.getAnnotation(Binding.class);
if (binding == null) {
return false;
}
Annotation[] annotations = method.getAnnotations();
// Get the key
Class<?> ret = method.getReturnType();
Key key;
if ( annotations.length == 1) {
key = Key.of(ret);
} else if (annotations.length == 2) {
Annotation annotation = annotations[0] == binding ? annotations[1] : annotations[0];
key = Key.of(ret, annotation);
} else {
LOGGER.debug("Cannot annotate: " + method + " with " + StringMan.getString(annotations));
return false;
}
// Get the provided parameters
Class<?>[] params = method.getParameterTypes();
Annotation[][] paramAnns = method.getParameterAnnotations();
Function<InjectedValueAccess, Object>[] argsFunc = new Function[params.length];
boolean provide = true;
for (int i = 0; i < params.length; i++) {
Class<?> param = params[i];
if (param != String.class) {
Annotation[] paramAnn = paramAnns[i];
Key paramKey;
if (paramAnn.length == 1) {
paramKey = Key.of(param, paramAnn[0]);
} else if (paramAnn.length == 0) {
paramKey = Key.of(param);
} else {
throw new UnsupportedOperationException("Only one annotation is permitted for " + method);
}
argsFunc[i] = v -> v.injectedValue(paramKey);
} else if (provide) {
provide = false;
} else {
throw new UnsupportedOperationException("Only one argument is allowed");
}
}
// If the method provides all parameters
if (provide) {
store.injectValue(key, access -> Optional.of(invoke(null, argsFunc, access, method)));
} else { // If the method consumes a String argument
manager.registerConverter(key, new ArgumentConverter<Object>() {
@Override
public Component describeAcceptableArguments() {
return TextComponent.of(binding.value());
}
@Override
public ConversionResult<Object> convert(String s, InjectedValueAccess access) {
Object o = invoke(s, argsFunc, access, method);
if (o == null) {
return FailedConversion.from(new NullPointerException());
}
return SuccessfulConversion.fromSingle(o);
}
});
}
return true;
}
private Object invoke(String arg, Function<InjectedValueAccess, Object>[] argsFunc, InjectedValueAccess access, Method method) {
try {
Object[] args = new Object[argsFunc.length];
for (int i = 0; i < argsFunc.length; i++) {
Function<InjectedValueAccess, Object> func = argsFunc[i];
if (func != null) {
Optional optional = (Optional) func.apply(access);
args[i] = optional.get();
} else {
args[i] = arg;
}
}
return method.invoke(this, args);
} catch (IllegalAccessException | InvocationTargetException e) {
if (!(e.getCause() instanceof StopExecutionException)) {
throw new RuntimeException(e);
}
return null;
}
}
}

View File

@ -0,0 +1,10 @@
package com.fastasyncworldedit.core.extension.platform.binding;
import com.sk89q.worldedit.WorldEdit;
public class CommandBindings extends Bindings {
public CommandBindings(WorldEdit worldEdit) {
super(worldEdit);
}
}

View File

@ -0,0 +1,161 @@
package com.fastasyncworldedit.core.extension.platform.binding;
import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.util.MainUtil;
import com.fastasyncworldedit.core.util.image.ImageUtil;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.annotation.Confirm;
import com.sk89q.worldedit.entity.Entity;
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.Actor;
import com.sk89q.worldedit.extension.platform.PlatformCommandManager;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.command.util.annotation.Time;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Identifiable;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import org.enginehub.piston.inject.InjectedValueAccess;
import java.util.UUID;
public class ConsumeBindings extends Bindings {
private final PlatformCommandManager manager;
public ConsumeBindings(WorldEdit worldEdit, PlatformCommandManager manager) {
super(worldEdit);
this.manager = manager;
}
@Time
@Binding
public Long time(Actor actor, String argument) {
return MainUtil.timeToSec(argument) * 1000;
}
@Binding
@Confirm(Confirm.Processor.REGION)
public int regionMultiple(Actor actor, InjectedValueAccess context, @Selection Region region, String argument) {
int times = (int) Expression.compile(argument).evaluate();
return Confirm.Processor.REGION.check(actor, context, times);
}
@Binding
@Confirm(Confirm.Processor.RADIUS)
public Integer radiusInteger(Actor actor, InjectedValueAccess context, String argument) {
int times = (int) Expression.compile(argument).evaluate();
return Confirm.Processor.RADIUS.check(actor, context, times);
}
@Binding
@Confirm(Confirm.Processor.LIMIT)
public Integer limitInteger(Actor actor, InjectedValueAccess context, String argument) {
int times = (int) Expression.compile(argument).evaluate();
return Confirm.Processor.LIMIT.check(actor, context, times);
}
@Binding
@Confirm(Confirm.Processor.RADIUS)
public Double radiusDouble(Actor actor, InjectedValueAccess context, String argument) {
double times = Expression.compile(argument).evaluate();
return Confirm.Processor.RADIUS.check(actor, context, times);
}
@Binding
@Confirm(Confirm.Processor.LIMIT)
public Double limitDouble(Actor actor, InjectedValueAccess context, String argument) {
double times = Expression.compile(argument).evaluate();
return Confirm.Processor.LIMIT.check(actor, context, times);
}
@Binding
@Confirm(Confirm.Processor.RADIUS)
public BlockVector2 radiusVec2(Actor actor, InjectedValueAccess context, String argument) {
BlockVector2 radius = manager.parseConverter(argument, context, BlockVector2.class);
double length = radius.length();
Confirm.Processor.RADIUS.check(actor, context, length);
return radius;
}
@Binding
@Confirm(Confirm.Processor.RADIUS)
public BlockVector3 radiusVec3(Actor actor, InjectedValueAccess context, String argument) {
BlockVector3 radius = manager.parseConverter(argument, context, BlockVector3.class);
double length = radius.length();
Confirm.Processor.RADIUS.check(actor, context, length);
return radius;
}
@Binding
public UUID playerUUID(Actor actor, String argument) {
if (argument.equals("me")) {
return actor.getUniqueId();
}
if (argument.equals("*")) {
return Identifiable.EVERYONE;
}
if (argument.equalsIgnoreCase("console") || argument.equalsIgnoreCase("server")) {
return Identifiable.CONSOLE;
}
UUID uuid;
if (argument.length() > 16) {
uuid = UUID.fromString(argument);
} else {
uuid = Fawe.imp().getUUID(argument);
}
if (uuid == null) {
throw new InputParseException(Caption.of("fawe.error.player.not.found", TextComponent.of(argument)));
}
return uuid;
}
@Binding
public ProvideBindings.ImageUri getImage(String argument) {
return new ProvideBindings.ImageUri(ImageUtil.getImageURI(argument));
}
@Binding
public BlockType blockType(Actor actor, String argument) {
return blockState(actor, argument).getBlockType();
}
@Binding
public BlockStateHolder blockStateHolder(Actor actor, String argument) {
return blockState(actor, argument);
}
@Binding
public BlockState blockState(Actor actor, String argument) {
return baseBlock(actor, argument).toBlockState();
}
@Binding
public BaseBlock baseBlock(Actor actor, String argument) {
ParserContext parserContext = new ParserContext();
parserContext.setActor(actor);
if (actor instanceof Entity) {
Extent extent = ((Entity) actor).getExtent();
if (extent instanceof World) {
parserContext.setWorld((World) extent);
}
}
parserContext.setSession(getWorldEdit().getSessionManager().get(actor));
try {
return getWorldEdit().getBlockFactory().parseFromInput(argument, parserContext);
} catch (NoMatchException e) {
throw new InputParseException(Caption.of(e.getMessage()));
}
}
}

View File

@ -0,0 +1,245 @@
package com.fastasyncworldedit.core.extension.platform.binding;
import com.fastasyncworldedit.core.configuration.Caption;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.internal.expression.EvaluationException;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector2;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import java.util.Locale;
import javax.annotation.Nullable;
public class PrimitiveBindings extends Bindings {
public PrimitiveBindings(WorldEdit worldEdit) {
super(worldEdit);
}
/*
Parsers
*/
@Binding
public Expression getExpression(String argument) throws ExpressionException {
try {
Expression expression = Expression.compile(argument);
expression.optimize();
return expression;
} catch (EvaluationException e) {
throw new InputParseException(String.format(
"Expected '%s' to be a valid number (or a valid mathematical expression)", argument));
} catch (ExpressionException e) {
throw new InputParseException(String.format(
"Expected '%s' to be a number or valid math expression (error: %s)", argument, e.getMessage()));
}
}
// TODO: Ping @MattBDev to reimplement 2020-02-04
//
// /**
// * Gets an {@link Extent} from a {@link Binding}.
// *
// * @param argument the context
// * @return an extent
// * @throws InputParseException on other error
// */
// @Binding
// public ResettableExtent getResettableExtent(Actor actor, String argument) throws InputParseException {
// if (argument.equalsIgnoreCase("#null")) {
// return new NullExtent();
// }
// DefaultTransformParser parser = Fawe.get().getTransformParser();
// ParserContext parserContext = new ParserContext();
// if (actor instanceof Entity) {
// Extent extent = ((Entity) actor).getExtent();
// if (extent instanceof World) {
// parserContext.setWorld((World) extent);
// }
// }
// parserContext.setSession(WorldEdit.getInstance().getSessionManager().get(actor));
// return parser.parseFromInput(argument, parserContext);
// }
/**
* Gets a type from a {@link Binding}.
*
* @param argument the context
* @return the requested type
* @throws InputParseException on error
*/
@Binding
public Boolean getBoolean(String argument) {
switch (argument.toLowerCase(Locale.ROOT)) {
case "":
throw new InputParseException(Caption.of("fawe.error.input-parser-exception"));
case "true":
case "yes":
case "on":
case "y":
case "1":
case "t":
return true;
case "false":
case "no":
case "off":
case "f":
case "n":
case "0":
return false;
default:
throw new InputParseException(Caption.of("fawe.error.invalid-boolean", TextComponent.of(argument)));
}
}
/**
* Gets a type from a {@link Binding}.
*
* @param argument the context
* @return the requested type
* @throws InputParseException on error
*/
@Binding
public Vector3 getVector3(String argument) {
String[] radii = argument.split(",");
final double radiusX;
final double radiusY;
final double radiusZ;
switch (radii.length) {
case 1:
radiusX = radiusY = radiusZ = PrimitiveBindings.parseNumericInput(radii[0]);
break;
case 3:
radiusX = PrimitiveBindings.parseNumericInput(radii[0]);
radiusY = PrimitiveBindings.parseNumericInput(radii[1]);
radiusZ = PrimitiveBindings.parseNumericInput(radii[2]);
break;
default:
throw new InputParseException("You must either specify 1 or 3 radius values.");
}
return Vector3.at(radiusX, radiusY, radiusZ);
}
/**
* Gets a type from a {@link Binding}.
*
* @param argument the context
* @return the requested type
* @throws InputParseException on error
*/
@Binding
public Vector2 getVector2(String argument) {
String radiusString = argument;
String[] radii = radiusString.split(",");
final double radiusX;
final double radiusZ;
switch (radii.length) {
case 1:
radiusX = radiusZ = PrimitiveBindings.parseNumericInput(radii[0]);
break;
case 2:
radiusX = PrimitiveBindings.parseNumericInput(radii[0]);
radiusZ = PrimitiveBindings.parseNumericInput(radii[1]);
break;
default:
throw new InputParseException("You must either specify 1 or 2 radius values.");
}
return Vector2.at(radiusX, radiusZ);
}
/**
* Gets a type from a {@link Binding}.
*
* @param argument the context
* @return the requested type
* @throws InputParseException on error
*/
@Binding
public BlockVector3 getBlockVector3(String argument) {
String radiusString = argument;
String[] radii = radiusString.split(",");
final double radiusX;
final double radiusY;
final double radiusZ;
switch (radii.length) {
case 1:
radiusX = radiusY = radiusZ = PrimitiveBindings.parseNumericInput(radii[0]);
break;
case 3:
radiusX = PrimitiveBindings.parseNumericInput(radii[0]);
radiusY = PrimitiveBindings.parseNumericInput(radii[1]);
radiusZ = PrimitiveBindings.parseNumericInput(radii[2]);
break;
default:
throw new InputParseException("You must either specify 1 or 3 radius values.");
}
return BlockVector3.at(radiusX, radiusY, radiusZ);
}
/**
* Gets a type from a {@link Binding}.
*
* @param argument the context
* @return the requested type
* @throws InputParseException on error
*/
@Binding
public BlockVector2 getBlockVector2(String argument) {
String[] radii = argument.split(",");
final double radiusX;
final double radiusZ;
switch (radii.length) {
case 1:
radiusX = radiusZ = parseNumericInput(radii[0]);
break;
case 2:
radiusX = parseNumericInput(radii[0]);
radiusZ = parseNumericInput(radii[1]);
break;
default:
throw new InputParseException("You must either specify 1 or 2 radius values.");
}
return BlockVector2.at(radiusX, radiusZ);
}
/**
* Try to parse numeric input as either a number or a mathematical expression.
*
* @param input input
* @return a number
* @throws InputParseException thrown on parse error
*/
@Nullable
public static Double parseNumericInput(@Nullable String input) {
if (input == null) {
return null;
}
try {
return Double.parseDouble(input);
} catch (NumberFormatException e1) {
try {
Expression expression = Expression.compile(input);
return expression.evaluate();
} catch (EvaluationException e) {
throw new InputParseException(String.format(
"Expected '%s' to be a valid number (or a valid mathematical expression)", input));
} catch (ExpressionException e) {
throw new InputParseException(String.format(
"Expected '%s' to be a number or valid math expression (error: %s)", input, e.getMessage()));
}
}
}
}

View File

@ -0,0 +1,132 @@
package com.fastasyncworldedit.core.extension.platform.binding;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.database.DBHandler;
import com.fastasyncworldedit.core.database.RollbackDatabase;
import com.fastasyncworldedit.core.regions.FaweMaskManager;
import com.fastasyncworldedit.core.util.TextureUtil;
import com.fastasyncworldedit.core.util.image.ImageUtil;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.argument.Arguments;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.command.util.annotation.AllowedRegion;
import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.session.request.Request;
import com.sk89q.worldedit.world.World;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.enginehub.piston.inject.InjectedValueStore;
import org.enginehub.piston.inject.Key;
import org.enginehub.piston.util.ValueProvider;
import java.awt.image.BufferedImage;
import java.net.URI;
import java.util.Optional;
public class ProvideBindings extends Bindings {
public ProvideBindings(WorldEdit worldEdit) {
super(worldEdit);
}
/*
Provided
*/
@Binding
public Player getPlayer(Actor actor) {
if (actor.isPlayer()) {
return (Player) actor;
}
throw new InputParseException(Caption.of("worldedit.command.player-only"));
}
@Binding
public LocalSession getLocalSession(Player player) {
return getWorldEdit().getSessionManager().get(player);
}
@Binding
public EditSession editSession(LocalSession localSession, Player player, InjectedValueAccess context) {
Arguments arguments = context.injectedValue(Key.of(Arguments.class)).orElse(null);
String command = arguments == null ? null : arguments.get();
EditSession editSession = localSession.createEditSession(player, command);
editSession.enableStandardMode();
Request.request().setEditSession(editSession);
return editSession;
}
@Selection
@Binding
public Region selection(LocalSession localSession, Player player) {
return localSession.getSelection(player.getWorld());
}
@Binding
public RollbackDatabase database(World world) {
return DBHandler.IMP.getDatabase(world);
}
@AllowedRegion(FaweMaskManager.MaskType.OWNER)
@Binding
public Region[] regionsOwner(Player player) {
return regions(player, FaweMaskManager.MaskType.OWNER);
}
@AllowedRegion(FaweMaskManager.MaskType.MEMBER)
@Binding
public Region[] regionsMember(Player player) {
return regions(player, FaweMaskManager.MaskType.MEMBER);
}
public Region[] regions(Player player, FaweMaskManager.MaskType type) {
Region[] regions = player.getCurrentRegions(type);
if (regions == null) {
throw new IllegalArgumentException(Caption.toString(Caption.of("fawe.error.no.region")));
}
return regions;
}
@Binding
public TextureUtil getTexture(LocalSession session) {
return session.getTextureUtil();
}
public static class ImageUri {
public final URI uri;
private BufferedImage image;
ImageUri(URI uri) {
this.uri = uri;
}
public BufferedImage load() {
if (image != null) {
return image;
}
return image = ImageUtil.load(uri);
}
}
@Binding
public Extent getExtent(Actor actor, InjectedValueAccess access) {
Optional<EditSession> editSessionOpt = access.injectedValue(Key.of(EditSession.class));
if (editSessionOpt.isPresent()) {
return editSessionOpt.get();
}
Extent extent = Request.request().getExtent();
if (extent != null) {
return extent;
}
Player plr = getPlayer(actor);
EditSession editSession = editSession(getLocalSession(plr), plr, access);
if (access instanceof InjectedValueStore) {
InjectedValueStore store = (InjectedValueStore) access;
store.injectValue(Key.of(EditSession.class), ValueProvider.constant(editSession));
}
return editSession;
}
}