Search in sources :

Example 1 with MemoizingValueAccess

use of org.enginehub.piston.inject.MemoizingValueAccess in project FastAsyncWorldEdit by IntellectualSites.

the class PlatformCommandManager method handleCommandSuggestion.

@Subscribe
public void handleCommandSuggestion(CommandSuggestionEvent event) {
    try {
        String rawArgs = event.getArguments();
        // FAWE start
        // Increase the resulting positions by 1 if we remove a leading `/`
        final int posOffset = rawArgs.startsWith("/") ? 1 : 0;
        String arguments = rawArgs.startsWith("/") ? rawArgs.substring(1) : rawArgs;
        // FAWE end
        List<Substring> split = parseArgs(arguments).collect(Collectors.toList());
        List<String> argStrings = split.stream().map(Substring::getSubstring).collect(Collectors.toList());
        // FAWE start - event & suggestion
        MemoizingValueAccess access = initializeInjectedValues(() -> arguments, event.getActor(), event, true);
        // FAWE end
        ImmutableSet<Suggestion> suggestions;
        try {
            suggestions = commandManager.getSuggestions(access, argStrings);
        } catch (Throwable t) {
            // catch errors which are *not* command exceptions generated by parsers/suggesters
            if (!(t instanceof InputParseException) && !(t instanceof CommandException)) {
                Throwable cause = t;
                // These exceptions can be very nested, and should not be printed as they are not an actual error.
                boolean printError = true;
                while ((cause = cause.getCause()) != null) {
                    if (cause instanceof InputParseException || cause instanceof CommandException) {
                        printError = false;
                        break;
                    }
                }
                if (printError) {
                    LOGGER.error("Unexpected error occurred while generating suggestions for input: {}", arguments, t);
                    return;
                }
            }
            return;
        }
        event.setSuggestions(suggestions.stream().map(suggestion -> {
            int noSlashLength = arguments.length();
            Substring original = suggestion.getReplacedArgument() == split.size() ? Substring.from(arguments, noSlashLength, noSlashLength) : split.get(suggestion.getReplacedArgument());
            return Substring.wrap(suggestion.getSuggestion(), original.getStart() + posOffset, original.getEnd() + posOffset);
        }).collect(Collectors.toList()));
    } catch (ConditionFailedException e) {
        if (e.getCondition() instanceof PermissionCondition) {
            event.setSuggestions(new ArrayList<>());
        }
    }
}
Also used : Substring(com.sk89q.worldedit.internal.util.Substring) MemoizingValueAccess(org.enginehub.piston.inject.MemoizingValueAccess) ArrayList(java.util.ArrayList) CommandException(org.enginehub.piston.exception.CommandException) Suggestion(org.enginehub.piston.suggestion.Suggestion) InputParseException(com.sk89q.worldedit.extension.input.InputParseException) ConditionFailedException(org.enginehub.piston.exception.ConditionFailedException) PermissionCondition(com.sk89q.worldedit.command.util.PermissionCondition) SubCommandPermissionCondition(com.sk89q.worldedit.command.util.SubCommandPermissionCondition) Subscribe(com.sk89q.worldedit.util.eventbus.Subscribe)

Example 2 with MemoizingValueAccess

use of org.enginehub.piston.inject.MemoizingValueAccess in project FastAsyncWorldEdit by IntellectualSites.

the class PlatformCommandManager method handleCommandOnCurrentThread.

public void handleCommandOnCurrentThread(CommandEvent event) {
    Actor actor = platformManager.createProxyActor(event.getActor());
    String[] split = parseArgs(event.getArguments()).map(Substring::getSubstring).toArray(String[]::new);
    // No command found!
    if (!commandManager.containsCommand(split[0])) {
        return;
    }
    LocalSession session = worldEdit.getSessionManager().get(actor);
    Request.request().setSession(session);
    if (actor instanceof Entity) {
        Extent extent = ((Entity) actor).getExtent();
        if (extent instanceof World) {
            Request.request().setWorld(((World) extent));
        }
    }
    MemoizingValueAccess context = initializeInjectedValues(event::getArguments, actor, event, false);
    ThrowableSupplier<Throwable> task = () -> commandManager.execute(context, ImmutableList.copyOf(split));
    handleCommandTask(task, context, session, event);
}
Also used : Entity(com.sk89q.worldedit.entity.Entity) MemoizingValueAccess(org.enginehub.piston.inject.MemoizingValueAccess) Extent(com.sk89q.worldedit.extent.Extent) LocalSession(com.sk89q.worldedit.LocalSession) World(com.sk89q.worldedit.world.World)

Example 3 with MemoizingValueAccess

use of org.enginehub.piston.inject.MemoizingValueAccess in project FastAsyncWorldEdit by IntellectualSites.

the class RichPatternParser method parseFromInput.

@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.getInput();
            String full = pe.getFull();
            Pattern pattern = null;
            double chance = 1;
            if (command.isEmpty()) {
                pattern = parseFromInput(StringMan.join(entry.getValue(), ','), context);
            } else if (!worldEdit.getPatternFactory().containsAlias(command)) {
                // Legacy patterns
                char char0 = command.charAt(0);
                boolean charPattern = input.length() > 1 && input.charAt(1) != '[';
                if (charPattern && input.charAt(0) == '=') {
                    pattern = parseFromInput(char0 + "[" + input.substring(1) + "]", context);
                }
                if (char0 == '#' && command.length() > 1 && command.charAt(1) != '#') {
                    throw new SuggestInputParseException(new NoMatchException(Caption.of("fawe.error.parse.unknown-pattern", full, TextComponent.of("https://intellectualsites.github.io/fastasyncworldedit-documentation/patterns/patterns").clickEvent(ClickEvent.openUrl("https://intellectualsites.github.io/fastasyncworldedit-documentation/patterns/patterns")))), full, () -> {
                        if (full.length() == 1) {
                            return new ArrayList<>(worldEdit.getPatternFactory().getSuggestions(""));
                        }
                        return new ArrayList<>(worldEdit.getPatternFactory().getSuggestions(command.toLowerCase(Locale.ROOT)));
                    });
                }
                if (charPattern) {
                    if (char0 == '$' || char0 == '^' || char0 == '*' || (char0 == '#' && input.charAt(1) == '#')) {
                        pattern = worldEdit.getPatternFactory().parseWithoutRich(full, 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 && percentPatternRegex.matcher(command).matches()) {
                            // Legacy percent pattern
                            chance = Expression.compile(command.substring(0, percentIndex)).evaluate();
                            String value = command.substring(percentIndex + 1);
                            if (!entry.getValue().isEmpty()) {
                                boolean addBrackets = !value.isEmpty();
                                if (addBrackets) {
                                    value += "[";
                                }
                                value += StringMan.join(entry.getValue(), " ");
                                if (addBrackets) {
                                    value += "]";
                                }
                            }
                            pattern = parseFromInput(value, context);
                        } else {
                            // legacy block pattern
                            try {
                                pattern = worldEdit.getBlockFactory().parseFromInput(pe.getFull(), context);
                            } catch (NoMatchException e) {
                                throw new NoMatchException(Caption.of("fawe.error.parse.unknown-pattern", full, TextComponent.of("https://intellectualsites.github.io/fastasyncworldedit-documentation/patterns/patterns").clickEvent(com.sk89q.worldedit.util.formatting.text.event.ClickEvent.openUrl("https://intellectualsites.github.io/fastasyncworldedit-documentation/patterns/patterns"))));
                            }
                        }
                    }
                }
            } else {
                List<String> args = entry.getValue();
                try {
                    pattern = worldEdit.getPatternFactory().parseWithoutRich(full, context);
                } catch (InputParseException rethrow) {
                    throw rethrow;
                } catch (Throwable e) {
                    throw SuggestInputParseException.of(e, full, () -> {
                        try {
                            String cmdArgs = ((args.isEmpty()) ? "" : " " + StringMan.join(args, " "));
                            List<Substring> split = CommandArgParser.forArgString(cmdArgs).parseArgs().toList();
                            List<String> argStrings = split.stream().map(Substring::getSubstring).collect(Collectors.toList());
                            MemoizingValueAccess access = getPlatform().initializeInjectedValues(() -> cmdArgs, actor, null, true);
                            List<String> suggestions = getPlatform().getCommandManager().getSuggestions(access, argStrings).stream().map(Suggestion::getSuggestion).collect(Collectors.toUnmodifiableList());
                            List<String> result = new ArrayList<>();
                            if (suggestions.size() <= 2) {
                                for (int i = 0; i < suggestions.size(); i++) {
                                    String suggestion = suggestions.get(i);
                                    if (suggestion.indexOf(' ') != 0) {
                                        String[] splitSuggestion = suggestion.split(" ");
                                        suggestion = "[" + StringMan.join(splitSuggestion, "][") + "]";
                                        result.set(i, suggestion);
                                    }
                                }
                            }
                            return result;
                        } catch (Throwable e2) {
                            e2.printStackTrace();
                            throw new InputParseException(TextComponent.of(e2.getMessage()));
                        }
                    });
                }
            }
            if (pattern != null) {
                patterns.add(pattern);
                chances.add(chance);
            }
        }
    } catch (InputParseException rethrow) {
        throw rethrow;
    } catch (Throwable e) {
        e.printStackTrace();
        throw new InputParseException(TextComponent.of(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;
}
Also used : SuggestInputParseException(com.fastasyncworldedit.core.command.SuggestInputParseException) BlockTypes(com.sk89q.worldedit.world.block.BlockTypes) Suggestion(org.enginehub.piston.suggestion.Suggestion) Caption(com.fastasyncworldedit.core.configuration.Caption) MemoizingValueAccess(org.enginehub.piston.inject.MemoizingValueAccess) ParserContext(com.sk89q.worldedit.extension.input.ParserContext) FaweParser(com.fastasyncworldedit.core.extension.factory.parser.FaweParser) TrueRandom(com.fastasyncworldedit.core.math.random.TrueRandom) StringMan(com.fastasyncworldedit.core.util.StringMan) ArrayList(java.util.ArrayList) CommandLocals(com.sk89q.minecraft.util.commands.CommandLocals) Substring(com.sk89q.worldedit.internal.util.Substring) InputParseException(com.sk89q.worldedit.extension.input.InputParseException) Locale(java.util.Locale) ClickEvent(com.sk89q.worldedit.util.formatting.text.event.ClickEvent) Map(java.util.Map) WorldEdit(com.sk89q.worldedit.WorldEdit) NoMatchException(com.sk89q.worldedit.extension.input.NoMatchException) CommandArgParser(com.sk89q.worldedit.internal.command.CommandArgParser) TextComponent(com.sk89q.worldedit.util.formatting.text.TextComponent) Expression(com.sk89q.worldedit.internal.expression.Expression) RandomPattern(com.sk89q.worldedit.function.pattern.RandomPattern) Collectors(java.util.stream.Collectors) Actor(com.sk89q.worldedit.extension.platform.Actor) List(java.util.List) Stream(java.util.stream.Stream) Pattern(com.sk89q.worldedit.function.pattern.Pattern) Collections(java.util.Collections) ArrayList(java.util.ArrayList) SuggestInputParseException(com.fastasyncworldedit.core.command.SuggestInputParseException) InputParseException(com.sk89q.worldedit.extension.input.InputParseException) Actor(com.sk89q.worldedit.extension.platform.Actor) TrueRandom(com.fastasyncworldedit.core.math.random.TrueRandom) ArrayList(java.util.ArrayList) List(java.util.List) Substring(com.sk89q.worldedit.internal.util.Substring) RandomPattern(com.sk89q.worldedit.function.pattern.RandomPattern) Pattern(com.sk89q.worldedit.function.pattern.Pattern) MemoizingValueAccess(org.enginehub.piston.inject.MemoizingValueAccess) SuggestInputParseException(com.fastasyncworldedit.core.command.SuggestInputParseException) CommandLocals(com.sk89q.minecraft.util.commands.CommandLocals) RandomPattern(com.sk89q.worldedit.function.pattern.RandomPattern) NoMatchException(com.sk89q.worldedit.extension.input.NoMatchException) Map(java.util.Map)

Example 4 with MemoizingValueAccess

use of org.enginehub.piston.inject.MemoizingValueAccess in project FastAsyncWorldEdit by IntellectualSites.

the class PlatformCommandManager method handleCommandTask.

public void handleCommandTask(ThrowableSupplier<Throwable> task, InjectedValueAccess context, @Nullable LocalSession session, CommandEvent event) {
    Actor actor = context.injectedValue(Key.of(Actor.class)).orElseThrow(() -> new IllegalStateException("No player"));
    long start = System.currentTimeMillis();
    try {
        // exceptions and rethrow their converted form, if their is one.
        try {
            Object result = task.get();
        } catch (Throwable t) {
            // Use the exception converter to convert the exception if any of its causes
            // can be converted, otherwise throw the original exception
            Throwable next = t;
            do {
                exceptionConverter.convert(next);
                next = next.getCause();
            } while (next != null);
            throw t;
        }
    } catch (ConditionFailedException e) {
        if (e.getCondition() instanceof PermissionCondition) {
            actor.print(Caption.of("fawe.error.no-perm", StringMan.getString(((PermissionCondition) e.getCondition()).getPermissions())));
        } else {
            actor.print(e.getRichMessage());
        }
    } catch (FaweException e) {
        actor.print(Caption.of("fawe.cancel.reason", e.getComponent()));
    } catch (UsageException e) {
        actor.printError(e.getRichMessage());
    } catch (CommandExecutionException e) {
        handleUnknownException(actor, e.getCause());
    } catch (CommandException e) {
        if (e.getCause() instanceof FaweException) {
            actor.print(Caption.of("fawe.cancel.reason", ((FaweException) e.getCause()).getComponent()));
        } else {
            Component msg = e.getRichMessage();
            if (msg == TextComponent.empty()) {
                List<String> argList = parseArgs(event.getArguments()).map(Substring::getSubstring).collect(Collectors.toList());
                printUsage(actor, argList);
            } else {
                actor.printError(msg);
            }
        }
    } catch (Throwable t) {
        handleUnknownException(actor, t);
    } finally {
        if (context instanceof MemoizingValueAccess) {
            context = ((MemoizingValueAccess) context).snapshotMemory();
        }
        Optional<EditSession> editSessionOpt = context.injectedValue(Key.of(EditSession.class));
        // Require null CommandEvent#getSession as it means the editsession is being handled somewhere else.
        if (editSessionOpt.isPresent() && event.getSession() == null) {
            EditSession editSession = editSessionOpt.get();
            editSession.close();
            session.remember(editSession);
            long time = System.currentTimeMillis() - start;
            double timeS = (time / 1000.0);
            int changed = editSession.getBlockChangeCount();
            double throughput = timeS == 0 ? changed : changed / timeS;
            if (time > 1000) {
                actor.print(Caption.of("worldedit.command.time-elapsed", TextComponent.of(timeS), TextComponent.of(changed), TextComponent.of(Math.round(throughput))));
            }
            worldEdit.flushBlockBag(actor, editSession);
        }
        // TODO: Ping @MattBDev to reimplement 2020-02-04
        // CFICommands.CFISettings cfi = actor.getMeta("CFISettings");
        // if (cfi != null) {
        // HeightMapMCAGenerator gen = cfi.getGenerator();
        // if (gen != null && gen.isModified()) {
        // try {
        // gen.update();
        // CFIChangeSet set = new CFIChangeSet(gen, actor.getUniqueId());
        // session.remember(actor, gen, set, actor.getLimit());
        // } catch (IOException e) {
        // e.printStackTrace();
        // }
        // }
        // }
        Request.reset();
    }
    event.setCancelled(true);
}
Also used : Substring(com.sk89q.worldedit.internal.util.Substring) UsageException(org.enginehub.piston.exception.UsageException) MemoizingValueAccess(org.enginehub.piston.inject.MemoizingValueAccess) FaweException(com.fastasyncworldedit.core.internal.exception.FaweException) CommandException(org.enginehub.piston.exception.CommandException) ConditionFailedException(org.enginehub.piston.exception.ConditionFailedException) PermissionCondition(com.sk89q.worldedit.command.util.PermissionCondition) SubCommandPermissionCondition(com.sk89q.worldedit.command.util.SubCommandPermissionCondition) CommandExecutionException(org.enginehub.piston.exception.CommandExecutionException) ArrayList(java.util.ArrayList) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) EditSession(com.sk89q.worldedit.EditSession) Component(com.sk89q.worldedit.util.formatting.text.Component) TextComponent(com.sk89q.worldedit.util.formatting.text.TextComponent)

Aggregations

MemoizingValueAccess (org.enginehub.piston.inject.MemoizingValueAccess)4 Substring (com.sk89q.worldedit.internal.util.Substring)3 ArrayList (java.util.ArrayList)3 PermissionCondition (com.sk89q.worldedit.command.util.PermissionCondition)2 SubCommandPermissionCondition (com.sk89q.worldedit.command.util.SubCommandPermissionCondition)2 InputParseException (com.sk89q.worldedit.extension.input.InputParseException)2 TextComponent (com.sk89q.worldedit.util.formatting.text.TextComponent)2 List (java.util.List)2 CommandException (org.enginehub.piston.exception.CommandException)2 ConditionFailedException (org.enginehub.piston.exception.ConditionFailedException)2 Suggestion (org.enginehub.piston.suggestion.Suggestion)2 SuggestInputParseException (com.fastasyncworldedit.core.command.SuggestInputParseException)1 Caption (com.fastasyncworldedit.core.configuration.Caption)1 FaweParser (com.fastasyncworldedit.core.extension.factory.parser.FaweParser)1 FaweException (com.fastasyncworldedit.core.internal.exception.FaweException)1 TrueRandom (com.fastasyncworldedit.core.math.random.TrueRandom)1 StringMan (com.fastasyncworldedit.core.util.StringMan)1 ImmutableList (com.google.common.collect.ImmutableList)1 CommandLocals (com.sk89q.minecraft.util.commands.CommandLocals)1 EditSession (com.sk89q.worldedit.EditSession)1