2014-07-09 00:39:33 +00:00
|
|
|
package com.sk89q.worldedit.extension.factory;
|
2014-04-04 00:52:53 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
import com.boydti.fawe.command.FaweParser;
|
2018-08-21 17:22:37 +00:00
|
|
|
import com.boydti.fawe.command.SuggestInputParseException;
|
2018-08-12 14:03:07 +00:00
|
|
|
import com.boydti.fawe.config.BBC;
|
|
|
|
import com.boydti.fawe.util.StringMan;
|
2018-08-21 17:22:37 +00:00
|
|
|
import com.sk89q.minecraft.util.commands.CommandException;
|
2018-08-12 14:03:07 +00:00
|
|
|
import com.sk89q.minecraft.util.commands.CommandLocals;
|
2014-07-17 07:21:13 +00:00
|
|
|
import com.sk89q.worldedit.WorldEdit;
|
2018-08-12 14:03:07 +00:00
|
|
|
import com.sk89q.worldedit.command.MaskCommands;
|
2014-04-04 00:52:53 +00:00
|
|
|
import com.sk89q.worldedit.extension.input.InputParseException;
|
|
|
|
import com.sk89q.worldedit.extension.input.NoMatchException;
|
|
|
|
import com.sk89q.worldedit.extension.input.ParserContext;
|
2018-08-12 14:03:07 +00:00
|
|
|
import com.sk89q.worldedit.extension.platform.Actor;
|
2014-04-04 00:52:53 +00:00
|
|
|
import com.sk89q.worldedit.extent.Extent;
|
2018-09-04 19:10:15 +00:00
|
|
|
import com.sk89q.worldedit.function.mask.BlockMaskBuilder;
|
2014-07-17 07:21:13 +00:00
|
|
|
import com.sk89q.worldedit.function.mask.Mask;
|
|
|
|
import com.sk89q.worldedit.function.mask.MaskIntersection;
|
2018-09-04 19:10:15 +00:00
|
|
|
import com.sk89q.worldedit.function.mask.MaskUnion;
|
2018-08-12 14:03:07 +00:00
|
|
|
import com.sk89q.worldedit.internal.command.ActorAuthorizer;
|
|
|
|
import com.sk89q.worldedit.internal.command.WorldEditBinding;
|
2014-04-04 00:52:53 +00:00
|
|
|
import com.sk89q.worldedit.session.request.Request;
|
2018-09-04 19:10:15 +00:00
|
|
|
import com.sk89q.worldedit.util.command.Dispatcher;
|
|
|
|
import com.sk89q.worldedit.util.command.SimpleDispatcher;
|
2018-08-12 14:03:07 +00:00
|
|
|
import com.sk89q.worldedit.util.command.parametric.ParametricBuilder;
|
|
|
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
2018-08-21 17:22:37 +00:00
|
|
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
2014-04-04 00:52:53 +00:00
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
2018-09-04 19:10:15 +00:00
|
|
|
import java.util.Map;
|
2018-08-12 14:03:07 +00:00
|
|
|
import java.util.regex.Pattern;
|
2018-08-21 17:22:37 +00:00
|
|
|
import java.util.stream.Collectors;
|
|
|
|
import java.util.stream.Stream;
|
2014-04-04 00:52:53 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
public class DefaultMaskParser extends FaweParser<Mask> {
|
|
|
|
private final Dispatcher dispatcher;
|
|
|
|
private final Pattern INTERSECTION_PATTERN = Pattern.compile("[&|;]+(?![^\\[]*\\])");
|
2014-04-04 00:52:53 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
public DefaultMaskParser(WorldEdit worldEdit) {
|
2014-04-04 00:52:53 +00:00
|
|
|
super(worldEdit);
|
2018-08-12 14:03:07 +00:00
|
|
|
this.dispatcher = new SimpleDispatcher();
|
|
|
|
this.register(new MaskCommands(worldEdit));
|
2014-04-04 00:52:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2018-08-12 14:03:07 +00:00
|
|
|
public Dispatcher getDispatcher() {
|
|
|
|
return dispatcher;
|
2014-04-04 00:52:53 +00:00
|
|
|
}
|
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
public void register(Object clazz) {
|
|
|
|
ParametricBuilder builder = new ParametricBuilder();
|
|
|
|
builder.setAuthorizer(new ActorAuthorizer());
|
|
|
|
builder.addBinding(new WorldEditBinding(worldEdit));
|
|
|
|
builder.registerMethodsAsCommands(dispatcher, clazz);
|
|
|
|
}
|
2014-04-04 00:52:53 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
@Override
|
|
|
|
public Mask parseFromInput(String input, ParserContext context) throws InputParseException {
|
2018-08-21 17:22:37 +00:00
|
|
|
if (input.isEmpty()) {
|
|
|
|
throw new SuggestInputParseException("No input provided", "", () -> Stream.concat(Stream.of("#", ",", "&"), BlockTypes.getNameSpaces().stream().map(n -> n + ":")).collect(Collectors.toList()));
|
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
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();
|
2018-08-21 17:22:37 +00:00
|
|
|
final String command = pe.input;
|
|
|
|
String full = pe.full;
|
2018-08-12 14:03:07 +00:00
|
|
|
Mask mask = null;
|
|
|
|
if (command.isEmpty()) {
|
|
|
|
mask = parseFromInput(StringMan.join(entry.getValue(), ','), context);
|
|
|
|
} else if (dispatcher.get(command) == 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);
|
|
|
|
}
|
2018-08-21 17:22:37 +00:00
|
|
|
if (char0 == '#') {
|
2018-10-16 20:15:45 +00:00
|
|
|
throw new SuggestInputParseException(new NoMatchException("Unknown mask: " + full + ", See: //masks"), full,
|
2018-08-21 17:22:37 +00:00
|
|
|
() -> {
|
|
|
|
if (full.length() == 1) return new ArrayList<>(dispatcher.getPrimaryAliases());
|
|
|
|
return dispatcher.getAliases().stream().filter(
|
|
|
|
s -> s.startsWith(command.toLowerCase())
|
|
|
|
).collect(Collectors.toList());
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
2018-08-21 17:22:37 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
// 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;
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
2018-08-21 17:22:37 +00:00
|
|
|
case '|':
|
|
|
|
case '~':
|
|
|
|
case '<':
|
|
|
|
case '>':
|
|
|
|
case '!':
|
|
|
|
input = input.substring(input.indexOf(char0) + 1);
|
|
|
|
mask = parseFromInput(char0 + "[" + input + "]", context);
|
|
|
|
if (actor != null) {
|
|
|
|
BBC.COMMAND_CLARIFYING_BRACKET.send(actor, char0 + "[" + input + "]");
|
|
|
|
}
|
|
|
|
return mask;
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
2018-08-21 17:22:37 +00:00
|
|
|
}
|
|
|
|
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, "\\^$.|?+(){}<>~$!%^&*+-/"))
|
|
|
|
{
|
2018-08-16 13:38:56 +00:00
|
|
|
try {
|
2018-08-21 17:22:37 +00:00
|
|
|
builder.addRegex(full);
|
|
|
|
} catch (SuggestInputParseException rethrow) {
|
|
|
|
throw rethrow;
|
|
|
|
} catch (InputParseException ignore) {}
|
|
|
|
}
|
|
|
|
if (mask == null) {
|
|
|
|
context.setPreferringWildcard(true);
|
|
|
|
context.setRestricted(false);
|
|
|
|
BlockStateHolder block = worldEdit.getBlockFactory().parseFromInput(full, context);
|
|
|
|
builder.add(block);
|
|
|
|
mask = builder.build(extent);
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
|
|
|
}
|
2014-04-04 00:52:53 +00:00
|
|
|
}
|
|
|
|
} else {
|
2018-08-12 14:03:07 +00:00
|
|
|
List<String> args = entry.getValue();
|
2018-08-21 17:22:37 +00:00
|
|
|
String cmdArgs = ((args.isEmpty()) ? "" : " " + StringMan.join(args, " "));
|
|
|
|
try {
|
|
|
|
mask = (Mask) dispatcher.call(command + cmdArgs, locals, new String[0]);
|
|
|
|
} catch (SuggestInputParseException rethrow) {
|
|
|
|
throw rethrow;
|
|
|
|
} catch (Throwable e) {
|
|
|
|
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 = BBC.color("[" + 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());
|
|
|
|
}
|
|
|
|
});
|
2014-04-04 00:52:53 +00:00
|
|
|
}
|
2014-07-28 09:35:58 +00:00
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
if (pe.and) {
|
|
|
|
masks.add(new ArrayList<>());
|
2014-04-04 00:52:53 +00:00
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
masks.get(masks.size() - 1).add(mask);
|
|
|
|
}
|
2018-08-21 17:22:37 +00:00
|
|
|
} catch (InputParseException rethrow) {
|
|
|
|
throw rethrow;
|
2018-08-12 14:03:07 +00:00
|
|
|
} 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;
|
2014-04-04 00:52:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|