All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.placeblock.commandapi.core.tree.TreeCommand Maven / Gradle / Ivy

package de.placeblock.commandapi.core.tree;

import de.placeblock.commandapi.core.Command;
import de.placeblock.commandapi.core.CommandExecutor;
import de.placeblock.commandapi.core.exception.CommandNoPermissionException;
import de.placeblock.commandapi.core.exception.CommandParseException;
import de.placeblock.commandapi.core.parser.ParsedCommandBranch;
import de.placeblock.commandapi.core.parser.StringReader;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.kyori.adventure.text.TextComponent;

import java.util.ArrayList;
import java.util.List;

/**
 * Author: Placeblock
 */
@Getter
@RequiredArgsConstructor
public abstract class TreeCommand {

    private final Command command;
    private final String name;
    private final List> children;
    private final TextComponent description;
    private final String permission;
    private final CommandExecutor commandExecutor;

    protected abstract void parse(ParsedCommandBranch command, S source) throws CommandParseException;

    public List> parseRecursive(ParsedCommandBranch command, S source) {
        int cursor = command.getReader().getCursor();
        List> commands = new ArrayList<>();
        commands.add(command);
        if (this.hasNoPermission(source)) {
            command.setException(this, new CommandNoPermissionException(this));
            return commands;
        }
        try {
            Command.LOGGER.info("Parsing Command " + this.getName());
            this.parse(command, source);
        } catch (CommandParseException e) {
            Command.LOGGER.info("Error Parsing Command " + this.getName());
            e.setTreeCommand(this);
            command.setException(this, e);
            // If an error occured while parsing we reset the cursor and subtract -1 because of the whitespace
            command.getReader().setCursor(cursor - 1);
            return commands;
        }
        StringReader reader = command.getReader();
        // We only parse Children if we can read further
        if (reader.canReadWord()) {
            for (TreeCommand child : this.getChildren()) {
                Command.LOGGER.info("Parsing Child " + child.getName());
                ParsedCommandBranch childParsedCommandBranch = new ParsedCommandBranch<>(command);
                childParsedCommandBranch.getReader().skip();
                List> childParsedCommandBranches = child.parseRecursive(childParsedCommandBranch, source);
                commands.addAll(childParsedCommandBranches);
            }
        }
        Command.LOGGER.info("Commands of TreeCommand " + this.name);
        for (ParsedCommandBranch parsedCommandBranch : commands) {
            Command.LOGGER.info(parsedCommandBranch.getBranch().stream().map(TreeCommand::getName).toList() + ": " + parsedCommandBranch.getReader().debugString());
        }
        return commands;
    }

    public List>> getBranches(S source) {
        List>> branches = new ArrayList<>();
        if (this.children.size() == 0 || this.getCommandExecutor() != null) {
            branches.add(new ArrayList<>(List.of(this)));
        }
        for (TreeCommand child : this.children) {
            if (child.hasNoPermission(source)) continue;
            List>> childBranches = child.getBranches(source);
            for (List> childBranch : childBranches) {
                childBranch.add(0, this);
                branches.add(childBranch);
            }
        }
        return branches;
    }

    public boolean hasNoPermission(S source) {
        if (this.permission == null) return false;
        return !this.command.hasPermission(source, this.permission);
    }

    public abstract List getSuggestions(ParsedCommandBranch command, S source);

    public abstract TextComponent getHelpComponent();

    public abstract TextComponent getHelpExtraDescription();
}