Purge intake-like command system

This commit is contained in:
Kenzie Togami 2019-04-30 14:59:45 -07:00
parent 7c1764548d
commit 743d7f08ab
No known key found for this signature in database
GPG Key ID: 5D200B325E157A81
66 changed files with 10 additions and 6189 deletions

View File

@ -1,63 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.command.argument;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.util.command.argument.CommandArgs;
import com.sk89q.worldedit.util.command.composition.CommandExecutor;
import java.util.Collections;
import java.util.List;
public class BooleanFlag implements CommandExecutor<Boolean> {
private final String description;
public BooleanFlag(String description) {
this.description = description;
}
@Override
public Boolean call(CommandArgs args, CommandLocals locals) throws CommandException {
return true;
}
@Override
public List<String> getSuggestions(CommandArgs args, CommandLocals locals) {
return Collections.emptyList();
}
@Override
public String getUsage() {
return "";
}
@Override
public String getDescription() {
return description;
}
@Override
public boolean testPermission(CommandLocals locals) {
return true;
}
}

View File

@ -1,85 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.command.argument;
import com.google.common.collect.Lists;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.util.command.argument.CommandArgs;
import com.sk89q.worldedit.util.command.argument.MissingArgumentException;
import com.sk89q.worldedit.util.command.composition.CommandExecutor;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
public class NumberParser implements CommandExecutor<Number> {
private final String name;
private final String description;
private final @Nullable String defaultSuggestion;
public NumberParser(String name, String description) {
this(name, description, null);
}
public NumberParser(String name, String description, @Nullable String defaultSuggestion) {
this.name = name;
this.description = description;
this.defaultSuggestion = defaultSuggestion;
}
@Override
public Number call(CommandArgs args, CommandLocals locals) throws CommandException {
try {
String next = args.next();
try {
return Double.parseDouble(next);
} catch (NumberFormatException ignored) {
throw new CommandException("The value for <" + name + "> should be a number. '" + next + "' is not a number.");
}
} catch (MissingArgumentException e) {
throw new CommandException("Missing value for <" + name + "> (try a number).");
}
}
@Override
public List<String> getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException {
String value = args.next();
return value.isEmpty() && defaultSuggestion != null ? Lists.newArrayList(defaultSuggestion) : Collections.emptyList();
}
@Override
public String getUsage() {
return "<" + name + ">";
}
@Override
public String getDescription() {
return description;
}
@Override
public boolean testPermission(CommandLocals locals) {
return true;
}
}

View File

@ -1,81 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.command.argument;
import com.google.common.collect.Lists;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.regions.factory.CuboidRegionFactory;
import com.sk89q.worldedit.regions.factory.CylinderRegionFactory;
import com.sk89q.worldedit.regions.factory.RegionFactory;
import com.sk89q.worldedit.regions.factory.SphereRegionFactory;
import com.sk89q.worldedit.util.command.argument.ArgumentUtils;
import com.sk89q.worldedit.util.command.argument.CommandArgs;
import com.sk89q.worldedit.util.command.argument.MissingArgumentException;
import com.sk89q.worldedit.util.command.composition.CommandExecutor;
import java.util.List;
public class RegionFactoryParser implements CommandExecutor<RegionFactory> {
@Override
public RegionFactory call(CommandArgs args, CommandLocals locals) throws CommandException {
try {
String type = args.next();
switch (type) {
case "cuboid":
return new CuboidRegionFactory();
case "sphere":
return new SphereRegionFactory();
case "cyl":
case "cylinder":
return new CylinderRegionFactory(1); // TODO: Adjustable height
default:
throw new CommandException("Unknown shape type: " + type + " (try one of " + getUsage() + ")");
}
} catch (MissingArgumentException e) {
throw new CommandException("Missing shape type (try one of " + getUsage() + ")");
}
}
@Override
public List<String> getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException {
return ArgumentUtils.getMatchingSuggestions(Lists.newArrayList("cuboid", "sphere", "cyl"), args.next());
}
@Override
public String getUsage() {
return "(cuboid | sphere | cyl)";
}
@Override
public String getDescription() {
return "Defines a region";
}
@Override
public boolean testPermission(CommandLocals locals) {
return true;
}
}

View File

@ -1,80 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.command.argument;
import com.google.common.collect.Lists;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.util.command.argument.CommandArgs;
import com.sk89q.worldedit.util.command.argument.MissingArgumentException;
import com.sk89q.worldedit.util.command.composition.CommandExecutor;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
public class StringParser implements CommandExecutor<String> {
private final String name;
private final String description;
private final @Nullable String defaultSuggestion;
public StringParser(String name, String description) {
this(name, description, null);
}
public StringParser(String name, String description, @Nullable String defaultSuggestion) {
this.name = name;
this.description = description;
this.defaultSuggestion = defaultSuggestion;
}
@Override
public String call(CommandArgs args, CommandLocals locals) throws CommandException {
try {
return args.next();
} catch (MissingArgumentException e) {
throw new CommandException("Missing value for <" + name + ">.");
}
}
@Override
public List<String> getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException {
String value = args.next();
return value.isEmpty() && defaultSuggestion != null ? Lists.newArrayList(defaultSuggestion) : Collections.emptyList();
}
@Override
public String getUsage() {
return "<" + name + ">";
}
@Override
public String getDescription() {
return description;
}
@Override
public boolean testPermission(CommandLocals locals) {
return true;
}
}

View File

@ -1,106 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.command.argument;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.function.Contextual;
import com.sk89q.worldedit.function.EditContext;
import com.sk89q.worldedit.function.generator.ForestGenerator;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
import com.sk89q.worldedit.util.command.argument.ArgumentUtils;
import com.sk89q.worldedit.util.command.argument.CommandArgs;
import com.sk89q.worldedit.util.command.argument.MissingArgumentException;
import com.sk89q.worldedit.util.command.composition.CommandExecutor;
import java.util.Arrays;
import java.util.List;
public class TreeGeneratorParser implements CommandExecutor<Contextual<ForestGenerator>> {
private final String name;
public TreeGeneratorParser(String name) {
this.name = name;
}
private String getOptionsList() {
return Joiner.on(" | ").join(Arrays.asList(TreeType.values()));
}
@Override
public Contextual<ForestGenerator> call(CommandArgs args, CommandLocals locals) throws CommandException {
try {
String input = args.next();
TreeType type = TreeGenerator.lookup(input);
if (type != null) {
return new GeneratorFactory(type);
} else {
throw new CommandException("Unknown value for <" + name + "> (try one of " + getOptionsList() + ").");
}
} catch (MissingArgumentException e) {
throw new CommandException("Missing value for <" + name + "> (try one of " + getOptionsList() + ").");
}
}
@Override
public List<String> getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException {
String s = args.next();
return s.isEmpty() ? Lists.newArrayList(TreeType.getPrimaryAliases()) : ArgumentUtils.getMatchingSuggestions(TreeType.getAliases(), s);
}
@Override
public String getUsage() {
return "<" + name + ">";
}
@Override
public String getDescription() {
return "Choose a tree generator";
}
@Override
public boolean testPermission(CommandLocals locals) {
return true;
}
private static final class GeneratorFactory implements Contextual<ForestGenerator> {
private final TreeType type;
private GeneratorFactory(TreeType type) {
this.type = type;
}
@Override
public ForestGenerator createFromContext(EditContext input) {
return new ForestGenerator((EditSession) input.getDestination(), type);
}
@Override
public String toString() {
return "tree of type " + type;
}
}
}

View File

@ -1,84 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.command.composition;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.minecraft.util.commands.WrappedCommandException;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.argument.BooleanFlag;
import com.sk89q.worldedit.command.argument.StringParser;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.function.Contextual;
import com.sk89q.worldedit.function.factory.Deform;
import com.sk89q.worldedit.function.factory.Deform.Mode;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.util.command.argument.CommandArgs;
import com.sk89q.worldedit.util.command.composition.FlagParser.Flag;
import com.sk89q.worldedit.util.command.composition.FlagParser.FlagData;
import com.sk89q.worldedit.util.command.composition.SimpleCommand;
public class DeformCommand extends SimpleCommand<Contextual<? extends Operation>> {
private final Flag<Boolean> rawCoordsFlag = addFlag('r', new BooleanFlag("Raw coords mode"));
private final Flag<Boolean> offsetFlag = addFlag('o', new BooleanFlag("Offset mode"));
private final StringParser expressionParser = addParameter(new StringParser("expression", "Expression to apply", "y-=0.2"));
@Override
public Deform call(CommandArgs args, CommandLocals locals) throws CommandException {
FlagData flagData = getFlagParser().call(args, locals);
String expression = expressionParser.call(args, locals);
boolean rawCoords = rawCoordsFlag.get(flagData, false);
boolean offset = offsetFlag.get(flagData, false);
Deform deform = new Deform(expression);
if (rawCoords) {
deform.setMode(Mode.RAW_COORD);
} else if (offset) {
deform.setMode(Mode.OFFSET);
Player player = (Player) locals.get(Actor.class);
LocalSession session = WorldEdit.getInstance().getSessionManager().get(locals.get(Actor.class));
try {
deform.setOffset(session.getPlacementPosition(player).toVector3());
} catch (IncompleteRegionException e) {
throw new WrappedCommandException(e);
}
} else {
deform.setMode(Mode.UNIT_CUBE);
}
return deform;
}
@Override
public String getDescription() {
return "Apply math expression to area";
}
@Override
protected boolean testPermission0(CommandLocals locals) {
return true;
}
}

View File

@ -1,115 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.command.composition;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.function.Contextual;
import com.sk89q.worldedit.function.EditContext;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.command.argument.CommandArgs;
import com.sk89q.worldedit.util.command.composition.CommandExecutor;
import com.sk89q.worldedit.util.command.composition.SimpleCommand;
import java.util.List;
public class SelectionCommand extends SimpleCommand<Operation> {
private final CommandExecutor<Contextual<? extends Operation>> delegate;
private final String permission;
public SelectionCommand(CommandExecutor<Contextual<? extends Operation>> delegate, String permission) {
checkNotNull(delegate, "delegate");
checkNotNull(permission, "permission");
this.delegate = delegate;
this.permission = permission;
addParameter(delegate);
}
@Override
public Operation call(CommandArgs args, CommandLocals locals) throws CommandException {
if (!testPermission(locals)) {
throw new CommandPermissionsException();
}
Contextual<? extends Operation> operationFactory = delegate.call(args, locals);
Actor actor = locals.get(Actor.class);
if (actor instanceof Player) {
try {
Player player = (Player) actor;
LocalSession session = WorldEdit.getInstance().getSessionManager().get(player);
Region selection = session.getSelection(player.getWorld());
EditSession editSession = session.createEditSession(player);
editSession.enableStandardMode();
locals.put(EditSession.class, editSession);
session.tellVersion(player);
EditContext editContext = new EditContext();
editContext.setDestination(locals.get(EditSession.class));
editContext.setRegion(selection);
editContext.setSession(session);
Operation operation = operationFactory.createFromContext(editContext);
Operations.completeBlindly(operation);
List<String> messages = Lists.newArrayList();
operation.addStatusMessages(messages);
if (messages.isEmpty()) {
actor.print("Operation completed.");
} else {
actor.print("Operation completed (" + Joiner.on(", ").join(messages) + ").");
}
return operation;
} catch (IncompleteRegionException e) {
WorldEdit.getInstance().getPlatformManager().getPlatformCommandManager().getExceptionConverter().convert(e);
return null;
}
} else {
throw new CommandException("This command can only be used by players.");
}
}
@Override
public String getDescription() {
return delegate.getDescription();
}
@Override
protected boolean testPermission0(CommandLocals locals) {
return locals.get(Actor.class).hasPermission(permission);
}
}

View File

@ -1,103 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.command.composition;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.MaxBrushRadiusException;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.argument.NumberParser;
import com.sk89q.worldedit.command.argument.RegionFactoryParser;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.command.tool.InvalidToolBindException;
import com.sk89q.worldedit.command.tool.brush.OperationFactoryBrush;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.function.Contextual;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.regions.factory.RegionFactory;
import com.sk89q.worldedit.util.HandSide;
import com.sk89q.worldedit.util.command.argument.CommandArgs;
import com.sk89q.worldedit.util.command.composition.CommandExecutor;
import com.sk89q.worldedit.util.command.composition.SimpleCommand;
public class ShapedBrushCommand extends SimpleCommand<Object> {
private final CommandExecutor<? extends Contextual<? extends Operation>> delegate;
private final String permission;
private final RegionFactoryParser regionFactoryParser = addParameter(new RegionFactoryParser());
private final NumberParser radiusCommand = addParameter(new NumberParser("size", "The size of the brush", "5"));
public ShapedBrushCommand(CommandExecutor<? extends Contextual<? extends Operation>> delegate, String permission) {
checkNotNull(delegate, "delegate");
this.permission = permission;
this.delegate = delegate;
addParameter(delegate);
}
@Override
public Object call(CommandArgs args, CommandLocals locals) throws CommandException {
if (!testPermission(locals)) {
throw new CommandPermissionsException();
}
RegionFactory regionFactory = regionFactoryParser.call(args, locals);
int radius = radiusCommand.call(args, locals).intValue();
Contextual<? extends Operation> factory = delegate.call(args, locals);
Player player = (Player) locals.get(Actor.class);
LocalSession session = WorldEdit.getInstance().getSessionManager().get(player);
try {
WorldEdit.getInstance().checkMaxBrushRadius(radius);
BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType());
tool.setSize(radius);
tool.setFill(null);
tool.setBrush(new OperationFactoryBrush(factory, regionFactory, session), permission);
} catch (MaxBrushRadiusException | InvalidToolBindException e) {
WorldEdit.getInstance().getPlatformManager().getPlatformCommandManager().getExceptionConverter().convert(e);
}
player.print("Set brush to " + factory);
return true;
}
@Override
public String getDescription() {
return delegate.getDescription();
}
@Override
public boolean testPermission0(CommandLocals locals) {
Actor sender = locals.get(Actor.class);
if (sender == null) {
throw new RuntimeException("Uh oh! No 'Actor' specified so that we can check permissions");
} else {
return sender.hasPermission(permission);
}
}
}

View File

@ -21,16 +21,14 @@ package com.sk89q.worldedit.extension.platform;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.registry.Registries;
import org.enginehub.piston.CommandManager;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
/**
* Represents a platform that WorldEdit has been implemented for.
*

View File

@ -1,72 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.internal.command;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.MultiUserPlatform;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.extension.platform.PlatformManager;
import com.sk89q.worldedit.util.command.CommandCompleter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* Provides the names of connected users as suggestions.
*/
public class UserCommandCompleter implements CommandCompleter {
private final PlatformManager platformManager;
/**
* Create a new instance.
*
* @param platformManager the platform manager
*/
public UserCommandCompleter(PlatformManager platformManager) {
checkNotNull(platformManager);
this.platformManager = platformManager;
}
@Override
public List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException {
Platform platform = platformManager.queryCapability(Capability.USER_COMMANDS);
if (platform instanceof MultiUserPlatform) {
List<String> suggestions = new ArrayList<>();
Collection<Actor> users = ((MultiUserPlatform) platform).getConnectedUsers();
for (Actor user : users) {
if (user.getName().toLowerCase().startsWith(arguments.toLowerCase().trim())) {
suggestions.add(user.getName());
}
}
return suggestions;
} else {
return Collections.emptyList();
}
}
}

View File

@ -1,331 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.internal.command;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.UnknownDirectionException;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.Player;
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.Capability;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.annotation.Direction;
import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
import com.sk89q.worldedit.util.command.parametric.ArgumentStack;
import com.sk89q.worldedit.util.command.parametric.BindingBehavior;
import com.sk89q.worldedit.util.command.parametric.BindingHelper;
import com.sk89q.worldedit.util.command.parametric.BindingMatch;
import com.sk89q.worldedit.util.command.parametric.ParameterException;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.Biomes;
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.registry.BiomeRegistry;
import java.util.Collection;
/**
* Binds standard WorldEdit classes such as {@link Player} and {@link LocalSession}.
*/
public class WorldEditBinding extends BindingHelper {
private final WorldEdit worldEdit;
/**
* Create a new instance.
*
* @param worldEdit the WorldEdit instance to bind to
*/
public WorldEditBinding(WorldEdit worldEdit) {
this.worldEdit = worldEdit;
}
/**
* Gets a selection from a {@link ArgumentStack}.
*
* @param context the context
* @param selection the annotation
* @return a selection
* @throws IncompleteRegionException if no selection is available
* @throws ParameterException on other error
*/
@BindingMatch(classifier = Selection.class,
type = Region.class,
behavior = BindingBehavior.PROVIDES)
public Object getSelection(ArgumentStack context, @SuppressWarnings("unused") Selection selection) throws IncompleteRegionException, ParameterException {
Player sender = getPlayer(context);
LocalSession session = worldEdit.getSessionManager().get(sender);
return session.getSelection(sender.getWorld());
}
/**
* Gets an {@link EditSession} from a {@link ArgumentStack}.
*
* @param context the context
* @return an edit session
* @throws ParameterException on other error
*/
@BindingMatch(type = EditSession.class,
behavior = BindingBehavior.PROVIDES)
public EditSession getEditSession(ArgumentStack context) throws ParameterException {
Player sender = getPlayer(context);
LocalSession session = worldEdit.getSessionManager().get(sender);
EditSession editSession = session.createEditSession(sender);
editSession.enableStandardMode();
context.getContext().getLocals().put(EditSession.class, editSession);
session.tellVersion(sender);
return editSession;
}
/**
* Gets an {@link LocalSession} from a {@link ArgumentStack}.
*
* @param context the context
* @return a local session
* @throws ParameterException on error
*/
@BindingMatch(type = LocalSession.class,
behavior = BindingBehavior.PROVIDES)
public LocalSession getLocalSession(ArgumentStack context) throws ParameterException {
Player sender = getPlayer(context);
return worldEdit.getSessionManager().get(sender);
}
/**
* Gets an {@link Actor} from a {@link ArgumentStack}.
*
* @param context the context
* @return a local player
* @throws ParameterException on error
*/
@BindingMatch(type = Actor.class,
behavior = BindingBehavior.PROVIDES)
public Actor getActor(ArgumentStack context) throws ParameterException {
Actor sender = context.getContext().getLocals().get(Actor.class);
if (sender == null) {
throw new ParameterException("Missing 'Actor'");
} else {
return sender;
}
}
/**
* Gets an {@link Player} from a {@link ArgumentStack}.
*
* @param context the context
* @return a local player
* @throws ParameterException on error
*/
@BindingMatch(type = Player.class,
behavior = BindingBehavior.PROVIDES)
public Player getPlayer(ArgumentStack context) throws ParameterException {
Actor sender = context.getContext().getLocals().get(Actor.class);
if (sender == null) {
throw new ParameterException("No player to get a session for");
} else if (sender instanceof Player) {
return (Player) sender;
} else {
throw new ParameterException("Caller is not a player");
}
}
/**
* Gets an {@link BaseBlock} from a {@link ArgumentStack}.
*
* @param context the context
* @return a pattern
* @throws ParameterException on error
* @throws WorldEditException on error
*/
@BindingMatch(type = {BaseBlock.class, BlockState.class, BlockStateHolder.class},
behavior = BindingBehavior.CONSUMES,
consumedCount = 1)
public BaseBlock getBaseBlock(ArgumentStack context) throws ParameterException, WorldEditException {
Actor actor = context.getContext().getLocals().get(Actor.class);
ParserContext parserContext = new ParserContext();
parserContext.setActor(context.getContext().getLocals().get(Actor.class));
if (actor instanceof Entity) {
Extent extent = ((Entity) actor).getExtent();
if (extent instanceof World) {
parserContext.setWorld((World) extent);
}
}
parserContext.setSession(worldEdit.getSessionManager().get(actor));
try {
return worldEdit.getBlockFactory().parseFromInput(context.next(), parserContext);
} catch (NoMatchException e) {
throw new ParameterException(e.getMessage(), e);
}
}
/**
* Gets an {@link Pattern} from a {@link ArgumentStack}.
*
* @param context the context
* @return a pattern
* @throws ParameterException on error
* @throws WorldEditException on error
*/
@BindingMatch(type = Pattern.class,
behavior = BindingBehavior.CONSUMES,
consumedCount = 1)
public Pattern getPattern(ArgumentStack context) throws ParameterException, WorldEditException {
Actor actor = context.getContext().getLocals().get(Actor.class);
ParserContext parserContext = new ParserContext();
parserContext.setActor(context.getContext().getLocals().get(Actor.class));
if (actor instanceof Entity) {
Extent extent = ((Entity) actor).getExtent();
if (extent instanceof World) {
parserContext.setWorld((World) extent);
}
}
parserContext.setSession(worldEdit.getSessionManager().get(actor));
try {
return worldEdit.getPatternFactory().parseFromInput(context.next(), parserContext);
} catch (NoMatchException e) {
throw new ParameterException(e.getMessage(), e);
}
}
/**
* Gets an {@link Mask} from a {@link ArgumentStack}.
*
* @param context the context
* @return a pattern
* @throws ParameterException on error
* @throws WorldEditException on error
*/
@BindingMatch(type = Mask.class,
behavior = BindingBehavior.CONSUMES,
consumedCount = 1)
public Mask getMask(ArgumentStack context) throws ParameterException, WorldEditException {
Actor actor = context.getContext().getLocals().get(Actor.class);
ParserContext parserContext = new ParserContext();
parserContext.setActor(context.getContext().getLocals().get(Actor.class));
if (actor instanceof Entity) {
Extent extent = ((Entity) actor).getExtent();
if (extent instanceof World) {
parserContext.setWorld((World) extent);
}
}
parserContext.setSession(worldEdit.getSessionManager().get(actor));
try {
return worldEdit.getMaskFactory().parseFromInput(context.next(), parserContext);
} catch (NoMatchException e) {
throw new ParameterException(e.getMessage(), e);
}
}
/**
* Get a direction from the player.
*
* @param context the context
* @param direction the direction annotation
* @return a pattern
* @throws ParameterException on error
* @throws UnknownDirectionException on an unknown direction
*/
@BindingMatch(classifier = Direction.class,
type = BlockVector3.class,
behavior = BindingBehavior.CONSUMES,
consumedCount = 1)
public BlockVector3 getDirection(ArgumentStack context, Direction direction)
throws ParameterException, UnknownDirectionException {
Player sender = getPlayer(context);
if (direction.includeDiagonals()) {
return worldEdit.getDiagonalDirection(sender, context.next());
} else {
return worldEdit.getDirection(sender, context.next());
}
}
/**
* Gets an {@link TreeType} from a {@link ArgumentStack}.
*
* @param context the context
* @return a pattern
* @throws ParameterException on error
* @throws WorldEditException on error
*/
@BindingMatch(type = TreeType.class,
behavior = BindingBehavior.CONSUMES,
consumedCount = 1)
public TreeType getTreeType(ArgumentStack context) throws ParameterException, WorldEditException {
String input = context.next();
if (input != null) {
TreeType type = TreeGenerator.lookup(input);
if (type != null) {
return type;
} else {
throw new ParameterException(
String.format("Can't recognize tree type '%s' -- choose from: %s", input,
TreeType.getPrimaryAliases()));
}
} else {
return TreeType.TREE;
}
}
/**
* Gets an {@link BiomeType} from a {@link ArgumentStack}.
*
* @param context the context
* @return a pattern
* @throws ParameterException on error
* @throws WorldEditException on error
*/
@BindingMatch(type = BiomeType.class,
behavior = BindingBehavior.CONSUMES,
consumedCount = 1)
public BiomeType getBiomeType(ArgumentStack context) throws ParameterException, WorldEditException {
String input = context.next();
if (input != null) {
BiomeRegistry biomeRegistry = WorldEdit.getInstance().getPlatformManager()
.queryCapability(Capability.GAME_HOOKS).getRegistries().getBiomeRegistry();
Collection<BiomeType> knownBiomes = BiomeType.REGISTRY.values();
BiomeType biome = Biomes.findBiomeByName(knownBiomes, input, biomeRegistry);
if (biome != null) {
return biome;
} else {
throw new ParameterException(
String.format("Can't recognize biome type '%s' -- use /biomelist to list available types", input));
}
} else {
throw new ParameterException(
"This command takes a 'default' biome if one is not set, except there is no particular " +
"biome that should be 'default', so the command should not be taking a default biome");
}
}
}

View File

@ -1,59 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
/**
* A command that can be executed.
*/
public interface CommandCallable extends CommandCompleter {
/**
* Execute the correct command based on the input.
*
* <p>The implementing class must perform the necessary permission
* checks.</p>
*
* @param arguments the arguments
* @param locals the locals
* @param parentCommands a list of parent commands, with the first most entry being the top-level command
* @return the called command, or null if there was no command found
* @throws CommandException thrown on a command error
*/
Object call(String arguments, CommandLocals locals, String[] parentCommands) throws CommandException;
/**
* Get an object describing this command.
*
* @return the command description
*/
Description getDescription();
/**
* Test whether this command can be executed with the given context.
*
* @param locals the locals
* @return true if execution is permitted
*/
boolean testPermission(CommandLocals locals);
}

View File

@ -1,42 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import java.util.List;
/**
* Provides a method that can provide tab completion for commands.
*/
public interface CommandCompleter {
/**
* Get a list of suggestions based on input.
*
* @param arguments the arguments entered up to this point
* @param locals the locals
* @return a list of suggestions
* @throws CommandException thrown if there was a parsing error
*/
List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException;
}

View File

@ -1,55 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command;
/**
* Provides information about a mapping between a command and its aliases.
*/
public interface CommandMapping {
/**
* Get the primary alias.
*
* @return the primary alias
*/
String getPrimaryAlias();
/**
* Get a list of all aliases.
*
* @return aliases
*/
String[] getAllAliases();
/**
* Get the callable
*
* @return the callable
*/
CommandCallable getCallable();
/**
* Get the {@link Description} form the callable.
*
* @return the description
*/
Description getDescription();
}

View File

@ -1,70 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command;
import java.util.List;
/**
* A description of a command.
*/
public interface Description {
/**
* Get the list of parameters for this command.
*
* @return a list of parameters
*/
List<Parameter> getParameters();
/**
* Get a short one-line description of this command.
*
* @return a description, or null if no description is available
*/
String getDescription();
/**
* Get a longer help text about this command.
*
* @return a help text, or null if no help is available
*/
String getHelp();
/**
* Get the usage string of this command.
*
* <p>A usage string may look like
* {@code [-w &lt;world&gt;] &lt;var1&gt; &lt;var2&gt;}.</p>
*
* @return a usage string
*/
String getUsage();
/**
* Get a list of permissions that the player may have to have permission.
*
* <p>Permission data may or may not be available. This is only useful as a
* potential hint.</p>
*
* @return the list of permissions
*/
List<String> getPermissions();
}

View File

@ -1,86 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command;
import java.util.Collection;
import java.util.Set;
import javax.annotation.Nullable;
/**
* Executes a command based on user input.
*/
public interface Dispatcher extends CommandCallable {
/**
* Register a command with this dispatcher.
*
* @param callable the command executor
* @param alias a list of aliases, where the first alias is the primary name
*/
void registerCommand(CommandCallable callable, String... alias);
/**
* Get a list of commands. Each command, regardless of how many aliases
* it may have, will only appear once in the returned set.
*
* <p>The returned collection cannot be modified.</p>
*
* @return a list of registrations
*/
Set<CommandMapping> getCommands();
/**
* Get a list of primary aliases.
*
* <p>The returned collection cannot be modified.</p>
*
* @return a list of aliases
*/
Collection<String> getPrimaryAliases();
/**
* Get a list of all the command aliases, which includes the primary alias.
*
* <p>A command may have more than one alias assigned to it. The returned
* collection cannot be modified.</p>
*
* @return a list of aliases
*/
Collection<String> getAliases();
/**
* Get the {@link CommandCallable} associated with an alias. Returns
* null if no command is named by the given alias.
*
* @param alias the alias
* @return the command mapping (null if not found)
*/
@Nullable CommandMapping get(String alias);
/**
* Returns whether the dispatcher contains a registered command for the given alias.
*
* @param alias the alias
* @return true if a registered command exists
*/
boolean contains(String alias);
}

View File

@ -1,107 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.minecraft.util.commands.CommandException;
import javax.annotation.Nullable;
/**
* Thrown when a command is not used properly.
*
* <p>When handling this exception, print the error message if it is not null.
* Print a one line help instruction unless {@link #isFullHelpSuggested()}
* is true, which, in that case, the full help of the command should be
* shown.</p>
*
* <p>If no error message is set and full help is not to be shown, then a generic
* "you used this command incorrectly" message should be shown.</p>
*/
public class InvalidUsageException extends CommandException {
private final CommandCallable command;
private final boolean fullHelpSuggested;
/**
* Create a new instance with no error message and with no suggestion
* that full and complete help for the command should be shown. This will
* result in a generic error message.
*
* @param command the command
*/
public InvalidUsageException(CommandCallable command) {
this(null, command);
}
/**
* Create a new instance with a message and with no suggestion
* that full and complete help for the command should be shown.
*
* @param message the message
* @param command the command
*/
public InvalidUsageException(@Nullable String message, CommandCallable command) {
this(message, command, false);
}
/**
* Create a new instance with a message.
*
* @param message the message
* @param command the command
* @param fullHelpSuggested true if the full help for the command should be shown
*/
public InvalidUsageException(@Nullable String message, CommandCallable command, boolean fullHelpSuggested) {
super(message);
checkNotNull(command);
this.command = command;
this.fullHelpSuggested = fullHelpSuggested;
}
/**
* Get the command.
*
* @return the command
*/
public CommandCallable getCommand() {
return command;
}
/**
* Get a simple usage string.
*
* @param prefix the command shebang (such as "/") -- may be blank
* @return a usage string
*/
public String getSimpleUsageString(String prefix) {
return getCommandUsed(prefix, command.getDescription().getUsage());
}
/**
* Return whether the full usage of the command should be shown.
*
* @return show full usage
*/
public boolean isFullHelpSuggested() {
return fullHelpSuggested;
}
}

View File

@ -1,29 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command;
import com.sk89q.worldedit.util.command.parametric.ParameterException;
/**
* Thrown when there is a missing parameter.
*/
public class MissingParameterException extends ParameterException {
}

View File

@ -1,38 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import java.util.Collections;
import java.util.List;
/**
* Always returns an empty list of suggestions.
*/
public class NullCompleter implements CommandCompleter {
@Override
public List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException {
return Collections.emptyList();
}
}

View File

@ -1,66 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command;
/**
* Describes a parameter.
*
* @see Description
*/
public interface Parameter {
/**
* The name of the parameter.
*
* @return the name
*/
String getName();
/**
* Get the flag associated with this parameter.
*
* @return the flag, or null if there is no flag associated
* @see #isValueFlag()
*/
Character getFlag();
/**
* Return whether the flag is a value flag.
*
* @return true if the flag is a value flag
* @see #getFlag()
*/
boolean isValueFlag();
/**
* Get whether this parameter is optional.
*
* @return true if the parameter does not have to be specified
*/
boolean isOptional();
/**
* Get the default value as a string to be parsed by the binding.
*
* @return a default value, or null if none is set
*/
String[] getDefaultValue();
}

View File

@ -1,60 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command;
import java.util.Comparator;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
/**
* Compares the primary aliases of two {@link CommandMapping} using
* {@link String#compareTo(String)}.
*/
public final class PrimaryAliasComparator implements Comparator<CommandMapping> {
/**
* An instance of this class.
*/
public static final PrimaryAliasComparator INSTANCE = new PrimaryAliasComparator(null);
private final @Nullable Pattern removalPattern;
/**
* Create a new instance.
*
* @param removalPattern a regex to remove unwanted characters from the compared aliases
*/
public PrimaryAliasComparator(@Nullable Pattern removalPattern) {
this.removalPattern = removalPattern;
}
private String clean(String alias) {
if (removalPattern != null) {
return removalPattern.matcher(alias).replaceAll("");
}
return alias;
}
@Override
public int compare(CommandMapping o1, CommandMapping o2) {
return clean(o1.getPrimaryAlias()).compareTo(clean(o2.getPrimaryAlias()));
}
}

View File

@ -1,72 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command;
import java.util.Arrays;
/**
* Tracks a command registration.
*/
public class SimpleCommandMapping implements CommandMapping {
private final String[] aliases;
private final CommandCallable callable;
/**
* Create a new instance.
*
* @param callable the command callable
* @param alias a list of all aliases, where the first one is the primary one
*/
public SimpleCommandMapping(CommandCallable callable, String... alias) {
super();
this.aliases = alias;
this.callable = callable;
}
@Override
public String getPrimaryAlias() {
return aliases[0];
}
@Override
public String[] getAllAliases() {
return aliases;
}
@Override
public CommandCallable getCallable() {
return callable;
}
@Override
public Description getDescription() {
return getCallable().getDescription();
}
@Override
public String toString() {
return "CommandMapping{" +
"aliases=" + Arrays.toString(aliases) +
", callable=" + callable +
'}';
}
}

View File

@ -1,135 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* A simple implementation of {@link Description} which has setters.
*/
public class SimpleDescription implements Description {
private List<Parameter> parameters = new ArrayList<>();
private List<String> permissions = new ArrayList<>();
private String description;
private String help;
private String overrideUsage;
@Override
public List<Parameter> getParameters() {
return parameters;
}
/**
* Set the list of parameters.
*
* @param parameters the list of parameters
* @see #getParameters()
*/
public SimpleDescription setParameters(List<Parameter> parameters) {
this.parameters = Collections.unmodifiableList(parameters);
return this;
}
@Override
public String getDescription() {
return description;
}
/**
* Set the description of the command.
*
* @param description the description
* @see #getDescription()
*/
public SimpleDescription setDescription(String description) {
this.description = description;
return this;
}
@Override
public String getHelp() {
return help;
}
/**
* Set the help text of the command.
*
* @param help the help text
* @see #getHelp()
*/
public SimpleDescription setHelp(String help) {
this.help = help;
return this;
}
@Override
public List<String> getPermissions() {
return permissions;
}
/**
* Set the permissions of this command.
*
* @param permissions the permissions
*/
public SimpleDescription setPermissions(List<String> permissions) {
this.permissions = Collections.unmodifiableList(permissions);
return this;
}
/**
* Override the usage string returned with a given one.
*
* @param usage usage string, or null
*/
public SimpleDescription overrideUsage(String usage) {
this.overrideUsage = usage;
return this;
}
@Override
public String getUsage() {
if (overrideUsage != null) {
return overrideUsage;
}
StringBuilder builder = new StringBuilder();
boolean first = true;
for (Parameter parameter : parameters) {
if (!first) {
builder.append(" ");
}
builder.append(parameter);
first = false;
}
return builder.toString();
}
@Override
public String toString() {
return getUsage();
}
}

View File

@ -1,189 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command;
import com.google.common.base.Joiner;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
import com.sk89q.minecraft.util.commands.WrappedCommandException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* A simple implementation of {@link Dispatcher}.
*/
public class SimpleDispatcher implements Dispatcher {
private final Map<String, CommandMapping> commands = new HashMap<>();
private final SimpleDescription description = new SimpleDescription();
/**
* Create a new instance.
*/
public SimpleDispatcher() {
description.getParameters().add(new SimpleParameter("subcommand"));
SimpleParameter extraArgs = new SimpleParameter("...");
extraArgs.setOptional(true);
description.getParameters().add(extraArgs);
}
@Override
public void registerCommand(CommandCallable callable, String... alias) {
CommandMapping mapping = new SimpleCommandMapping(callable, alias);
// Check for replacements
for (String a : alias) {
String lower = a.toLowerCase();
if (commands.containsKey(lower)) {
throw new IllegalArgumentException(
"Replacing commands is currently undefined behavior");
}
}
for (String a : alias) {
String lower = a.toLowerCase();
commands.put(lower, mapping);
}
}
@Override
public Set<CommandMapping> getCommands() {
return Collections.unmodifiableSet(new HashSet<>(commands.values()));
}
@Override
public Set<String> getAliases() {
return Collections.unmodifiableSet(commands.keySet());
}
@Override
public Set<String> getPrimaryAliases() {
Set<String> aliases = new HashSet<>();
for (CommandMapping mapping : getCommands()) {
aliases.add(mapping.getPrimaryAlias());
}
return Collections.unmodifiableSet(aliases);
}
@Override
public boolean contains(String alias) {
return commands.containsKey(alias.toLowerCase());
}
@Override
public CommandMapping get(String alias) {
return commands.get(alias.toLowerCase());
}
@Override
public Object call(String arguments, CommandLocals locals, String[] parentCommands) throws CommandException {
// We have permission for this command if we have permissions for subcommands
if (parentCommands.length != 0 && !testPermission(locals)) {
throw new CommandPermissionsException();
}
String[] split = CommandContext.split(arguments);
Set<String> aliases = getPrimaryAliases();
if (aliases.isEmpty()) {
throw new InvalidUsageException("This command has no sub-commands.", this);
} else if (split.length > 0) {
String subCommand = split[0];
String subArguments = Joiner.on(" ").join(Arrays.copyOfRange(split, 1, split.length));
String[] subParents = Arrays.copyOf(parentCommands, parentCommands.length + 1);
subParents[parentCommands.length] = subCommand;
CommandMapping mapping = get(subCommand);
if (mapping != null) {
try {
return mapping.getCallable().call(subArguments, locals, subParents);
} catch (CommandException e) {
e.prependStack(subCommand);
throw e;
} catch (Throwable t) {
throw new WrappedCommandException(t);
}
}
}
throw new InvalidUsageException("Please choose a sub-command.", this, true);
}
@Override
public List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException {
String[] split = CommandContext.split(arguments);
if (split.length <= 1) {
String prefix = split.length > 0 ? split[0] : "";
List<String> suggestions = new ArrayList<>();
for (CommandMapping mapping : getCommands()) {
if (mapping.getCallable().testPermission(locals)) {
for (String alias : mapping.getAllAliases()) {
if (prefix.isEmpty() || alias.startsWith(arguments)) {
suggestions.add(mapping.getPrimaryAlias());
break;
}
}
}
}
return suggestions;
} else {
String subCommand = split[0];
CommandMapping mapping = get(subCommand);
String passedArguments = Joiner.on(" ").join(Arrays.copyOfRange(split, 1, split.length));
if (mapping != null) {
return mapping.getCallable().getSuggestions(passedArguments, locals);
} else {
return Collections.emptyList();
}
}
}
@Override
public SimpleDescription getDescription() {
return description;
}
@Override
public boolean testPermission(CommandLocals locals) {
for (CommandMapping mapping : getCommands()) {
if (mapping.getCallable().testPermission(locals)) {
return true;
}
}
return false;
}
}

View File

@ -1,134 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command;
/**
* A simple implementation of {@link Parameter} that has setters.
*/
public class SimpleParameter implements Parameter {
private String name;
private Character flag;
private boolean isValue;
private boolean isOptional;
private String[] defaultValue;
/**
* Create a new parameter with no name defined yet.
*/
public SimpleParameter() {
}
/**
* Create a new parameter of the given name.
*
* @param name the name
*/
public SimpleParameter(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
/**
* Set the name of the parameter.
*
* @param name the parameter name
*/
public SimpleParameter setName(String name) {
this.name = name;
return this;
}
@Override
public Character getFlag() {
return flag;
}
@Override
public boolean isValueFlag() {
return flag != null && isValue;
}
/**
* Set the flag used by this parameter.
* @param flag the flag, or null if there is no flag
* @param isValue true if the flag is a value flag
*/
public SimpleParameter setFlag(Character flag, boolean isValue) {
this.flag = flag;
this.isValue = isValue;
return this;
}
@Override
public boolean isOptional() {
return isOptional || getFlag() != null;
}
/**
* Set whether this parameter is optional.
*
* @param isOptional true if this parameter is optional
*/
public SimpleParameter setOptional(boolean isOptional) {
this.isOptional = isOptional;
return this;
}
@Override
public String[] getDefaultValue() {
return defaultValue;
}
/**
* Set the default value.
*
* @param defaultValue a default value, or null if none
*/
public SimpleParameter setDefaultValue(String[] defaultValue) {
this.defaultValue = defaultValue;
return this;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
if (getFlag() != null) {
if (isValueFlag()) {
builder.append("[-")
.append(getFlag()).append(" <").append(getName()).append(">]");
} else {
builder.append("[-").append(getFlag()).append("]");
}
} else {
if (isOptional()) {
builder.append("[<").append(getName()).append(">]");
} else {
builder.append("<").append(getName()).append(">");
}
}
return builder.toString();
}
}

View File

@ -1,40 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command;
import com.sk89q.worldedit.util.command.parametric.ParameterException;
/**
* Thrown when there are leftover parameters that were not consumed, particular in the
* case of the user providing too many parameters.
*/
public class UnconsumedParameterException extends ParameterException {
private String unconsumed;
public UnconsumedParameterException(String unconsumed) {
this.unconsumed = unconsumed;
}
public String getUnconsumed() {
return unconsumed;
}
}

View File

@ -1,39 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.argument;
public class ArgumentException extends Exception {
public ArgumentException() {
}
public ArgumentException(String message) {
super(message);
}
public ArgumentException(String message, Throwable cause) {
super(message, cause);
}
public ArgumentException(Throwable cause) {
super(cause);
}
}

View File

@ -1,39 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.argument;
public class ArgumentParseException extends ArgumentException {
public ArgumentParseException() {
}
public ArgumentParseException(String message) {
super(message);
}
public ArgumentParseException(String message, Throwable cause) {
super(message, cause);
}
public ArgumentParseException(Throwable cause) {
super(cause);
}
}

View File

@ -1,45 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.argument;
import com.google.common.collect.Lists;
import java.util.Collection;
import java.util.List;
public final class ArgumentUtils {
private ArgumentUtils() {
}
public static List<String> getMatchingSuggestions(Collection<String> items, String s) {
if (s.isEmpty()) {
return Lists.newArrayList(items);
}
List<String> suggestions = Lists.newArrayList();
for (String item : items) {
if (item.toLowerCase().startsWith(s)) {
suggestions.add(item);
}
}
return suggestions;
}
}

View File

@ -1,162 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.argument;
import com.google.common.collect.Lists;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import java.util.Collections;
import java.util.List;
public class CommandArgs {
private final List<String> arguments;
private int position = 0;
public CommandArgs(List<String> arguments) {
this.arguments = arguments;
}
public CommandArgs(CommandArgs args) {
this(Lists.newArrayList(args.arguments));
}
public boolean hasNext() {
return position < arguments.size();
}
public String next() throws MissingArgumentException {
try {
return arguments.get(position++);
} catch (IndexOutOfBoundsException ignored) {
throw new MissingArgumentException("Too few arguments specified.");
}
}
public String uncheckedNext() {
if (hasNext()) {
return arguments.get(position);
} else {
return null;
}
}
public String peek() throws MissingArgumentException {
try {
return arguments.get(position);
} catch (IndexOutOfBoundsException ignored) {
throw new MissingArgumentException("Too few arguments specified.");
}
}
public String uncheckedPeek() {
if (hasNext()) {
return arguments.get(position);
} else {
return null;
}
}
public String remaining() throws MissingArgumentException {
if (hasNext()) {
StringBuilder builder = new StringBuilder();
boolean first = true;
while (hasNext()) {
if (!first) {
builder.append(" ");
}
builder.append(next());
first = false;
}
return builder.toString();
} else {
throw new MissingArgumentException("Too few arguments specified.");
}
}
public String peekRemaining() throws MissingArgumentException {
if (hasNext()) {
StringBuilder builder = new StringBuilder();
boolean first = true;
while (hasNext()) {
if (!first) {
builder.append(" ");
}
builder.append(next());
first = false;
}
return builder.toString();
} else {
throw new MissingArgumentException();
}
}
public int position() {
return position;
}
public int size() {
return arguments.size();
}
public void markConsumed() {
position = arguments.size();
}
public void requireAllConsumed() throws UnusedArgumentsException {
if (hasNext()) {
StringBuilder builder = new StringBuilder();
try {
builder.append(peekRemaining());
} catch (MissingArgumentException e) {
throw new RuntimeException("This should not have happened", e);
}
throw new UnusedArgumentsException("There were unused arguments: " + builder);
}
}
public static class Parser {
private boolean usingHangingArguments = false;
public boolean isUsingHangingArguments() {
return usingHangingArguments;
}
public Parser setUsingHangingArguments(boolean usingHangingArguments) {
this.usingHangingArguments = usingHangingArguments;
return this;
}
public CommandArgs parse(String arguments) throws CommandException {
CommandContext context = new CommandContext(CommandContext.split("_ " + arguments), Collections.<Character>emptySet(), false, null, false);
List<String> args = Lists.newArrayList();
for (int i = 0; i < context.argsLength(); i++) {
args.add(context.getString(i));
}
if (isUsingHangingArguments()) {
if (arguments.isEmpty() || arguments.endsWith(" ")) {
args.add("");
}
}
return new CommandArgs(args);
}
}
}

View File

@ -1,39 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.argument;
public class MissingArgumentException extends ArgumentException {
public MissingArgumentException() {
}
public MissingArgumentException(String message) {
super(message);
}
public MissingArgumentException(String message, Throwable cause) {
super(message, cause);
}
public MissingArgumentException(Throwable cause) {
super(cause);
}
}

View File

@ -1,39 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.argument;
public class UnusedArgumentsException extends ArgumentException {
public UnusedArgumentsException() {
}
public UnusedArgumentsException(String message) {
super(message);
}
public UnusedArgumentsException(String message, Throwable cause) {
super(message, cause);
}
public UnusedArgumentsException(Throwable cause) {
super(cause);
}
}

View File

@ -1,294 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.binding;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
import com.sk89q.worldedit.util.command.parametric.ArgumentStack;
import com.sk89q.worldedit.util.command.parametric.BindingBehavior;
import com.sk89q.worldedit.util.command.parametric.BindingHelper;
import com.sk89q.worldedit.util.command.parametric.BindingMatch;
import com.sk89q.worldedit.util.command.parametric.ParameterException;
import java.lang.annotation.Annotation;
import javax.annotation.Nullable;
/**
* Handles basic Java types such as {@link String}s, {@link Byte}s, etc.
*
* <p>Handles both the object and primitive types.</p>
*/
public final class PrimitiveBindings extends BindingHelper {
/**
* Gets a type from a {@link ArgumentStack}.
*
* @param context the context
* @param text the text annotation
* @param modifiers a list of modifiers
* @return the requested type
* @throws ParameterException on error
*/
@BindingMatch(classifier = Text.class,
type = String.class,
behavior = BindingBehavior.CONSUMES,
consumedCount = -1,
provideModifiers = true)
public String getText(ArgumentStack context, Text text, Annotation[] modifiers)
throws ParameterException {
String v = context.remaining();
validate(v, modifiers);
return v;
}
/**
* Gets a type from a {@link ArgumentStack}.
*
* @param context the context
* @param modifiers a list of modifiers
* @return the requested type
* @throws ParameterException on error
*/
@BindingMatch(type = String.class,
behavior = BindingBehavior.CONSUMES,
consumedCount = 1,
provideModifiers = true)
public String getString(ArgumentStack context, Annotation[] modifiers)
throws ParameterException {
String v = context.next();
validate(v, modifiers);
return v;
}
/**
* Gets a type from a {@link ArgumentStack}.
*
* @param context the context
* @return the requested type
* @throws ParameterException on error
*/
@BindingMatch(type = { Boolean.class, boolean.class },
behavior = BindingBehavior.CONSUMES,
consumedCount = 1)
public Boolean getBoolean(ArgumentStack context) throws ParameterException {
return context.nextBoolean();
}
/**
* Try to parse numeric input as either a number or a mathematical expression.
*
* @param input input
* @return a number
* @throws ParameterException thrown on parse error
*/
private @Nullable Double parseNumericInput(@Nullable String input) throws ParameterException {
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 ParameterException(String.format(
"Expected '%s' to be a valid number (or a valid mathematical expression)", input));
} catch (ExpressionException e) {
throw new ParameterException(String.format(
"Expected '%s' to be a number or valid math expression (error: %s)", input, e.getMessage()));
}
}
}
/**
* Gets a type from a {@link ArgumentStack}.
*
* @param context the context
* @param modifiers a list of modifiers
* @return the requested type
* @throws ParameterException on error
*/
@BindingMatch(type = { Integer.class, int.class },
behavior = BindingBehavior.CONSUMES,
consumedCount = 1,
provideModifiers = true)
public Integer getInteger(ArgumentStack context, Annotation[] modifiers) throws ParameterException {
Double v = parseNumericInput(context.next());
if (v != null) {
int intValue = v.intValue();
validate(intValue, modifiers);
return intValue;
} else {
return null;
}
}
/**
* Gets a type from a {@link ArgumentStack}.
*
* @param context the context
* @param modifiers a list of modifiers
* @return the requested type
* @throws ParameterException on error
*/
@BindingMatch(type = { Short.class, short.class },
behavior = BindingBehavior.CONSUMES,
consumedCount = 1,
provideModifiers = true)
public Short getShort(ArgumentStack context, Annotation[] modifiers) throws ParameterException {
Integer v = getInteger(context, modifiers);
if (v != null) {
return v.shortValue();
}
return null;
}
/**
* Gets a type from a {@link ArgumentStack}.
*
* @param context the context
* @param modifiers a list of modifiers
* @return the requested type
* @throws ParameterException on error
*/
@BindingMatch(type = { Double.class, double.class },
behavior = BindingBehavior.CONSUMES,
consumedCount = 1,
provideModifiers = true)
public Double getDouble(ArgumentStack context, Annotation[] modifiers) throws ParameterException {
Double v = parseNumericInput(context.next());
if (v != null) {
validate(v, modifiers);
return v;
} else {
return null;
}
}
/**
* Gets a type from a {@link ArgumentStack}.
*
* @param context the context
* @param modifiers a list of modifiers
* @return the requested type
* @throws ParameterException on error
*/
@BindingMatch(type = { Float.class, float.class },
behavior = BindingBehavior.CONSUMES,
consumedCount = 1,
provideModifiers = true)
public Float getFloat(ArgumentStack context, Annotation[] modifiers) throws ParameterException {
Double v = getDouble(context, modifiers);
if (v != null) {
return v.floatValue();
}
return null;
}
/**
* Validate a number value using relevant modifiers.
*
* @param number the number
* @param modifiers the list of modifiers to scan
* @throws ParameterException on a validation error
*/
private static void validate(double number, Annotation[] modifiers)
throws ParameterException {
for (Annotation modifier : modifiers) {
if (modifier instanceof Range) {
Range range = (Range) modifier;
if (number < range.min()) {
throw new ParameterException(
String.format(
"A valid value is greater than or equal to %s " +
"(you entered %s)", range.min(), number));
} else if (number > range.max()) {
throw new ParameterException(
String.format(
"A valid value is less than or equal to %s " +
"(you entered %s)", range.max(), number));
}
}
}
}
/**
* Validate a number value using relevant modifiers.
*
* @param number the number
* @param modifiers the list of modifiers to scan
* @throws ParameterException on a validation error
*/
private static void validate(int number, Annotation[] modifiers)
throws ParameterException {
for (Annotation modifier : modifiers) {
if (modifier instanceof Range) {
Range range = (Range) modifier;
if (number < range.min()) {
throw new ParameterException(
String.format(
"A valid value is greater than or equal to %s " +
"(you entered %s)", range.min(), number));
} else if (number > range.max()) {
throw new ParameterException(
String.format(
"A valid value is less than or equal to %s " +
"(you entered %s)", range.max(), number));
}
}
}
}
/**
* Validate a string value using relevant modifiers.
*
* @param string the string
* @param modifiers the list of modifiers to scan
* @throws ParameterException on a validation error
*/
private static void validate(String string, Annotation[] modifiers)
throws ParameterException {
if (string == null) {
return;
}
for (Annotation modifier : modifiers) {
if (modifier instanceof Validate) {
Validate validate = (Validate) modifier;
if (!validate.regex().isEmpty()) {
if (!string.matches(validate.regex())) {
throw new ParameterException(
String.format(
"The given text doesn't match the right " +
"format (technically speaking, the 'format' is %s)",
validate.regex()));
}
}
}
}
}
}

View File

@ -1,50 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.binding;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specifies a range of values for numbers.
*
* @see PrimitiveBindings a user of this annotation as a modifier
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Range {
/**
* The minimum value that the number can be at, inclusive.
*
* @return the minimum value
*/
double min() default Double.MIN_VALUE;
/**
* The maximum value that the number can be at, inclusive.
*
* @return the maximum value
*/
double max() default Double.MAX_VALUE;
}

View File

@ -1,46 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.binding;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.worldedit.util.command.parametric.ArgumentStack;
import com.sk89q.worldedit.util.command.parametric.BindingBehavior;
import com.sk89q.worldedit.util.command.parametric.BindingHelper;
import com.sk89q.worldedit.util.command.parametric.BindingMatch;
/**
* Standard bindings that should be available to most configurations.
*/
public final class StandardBindings extends BindingHelper {
/**
* Gets a {@link CommandContext} from a {@link ArgumentStack}.
*
* @param context the context
* @return a selection
*/
@BindingMatch(type = CommandContext.class,
behavior = BindingBehavior.PROVIDES)
public CommandContext getCommandContext(ArgumentStack context) {
context.markConsumed(); // Consume entire stack
return context.getContext();
}
}

View File

@ -1,44 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.binding;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Indicates a command flag, such as {@code /command -f}.
*
* <p>If used on a boolean type, then the flag will be a non-value flag. If
* used on any other type, then the flag will be a value flag.</p>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Switch {
/**
* The flag character.
*
* @return the flag character (A-Z a-z 0-9 is acceptable)
*/
char value();
}

View File

@ -1,41 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.binding;
import com.sk89q.worldedit.util.command.parametric.ArgumentStack;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Indicates a {@link String} parameter will call {@link ArgumentStack#remaining()} and
* therefore consume all remaining arguments.
*
* <p>This should only be used at the end of a list of parameters (of parameters that
* need to consume from the stack of arguments), otherwise following parameters will
* have no values left to consume.</p>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Text {
}

View File

@ -1,45 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.binding;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.regex.Pattern;
/**
* Used to validate a string.
*
* @see PrimitiveBindings where this validation is used
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Validate {
/**
* An optional regular expression that must match the string.
*
* @see Pattern regular expression class
* @return the pattern
*/
String regex() default "";
}

View File

@ -1,111 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.composition;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.util.command.argument.ArgumentUtils;
import com.sk89q.worldedit.util.command.argument.CommandArgs;
import com.sk89q.worldedit.util.command.argument.MissingArgumentException;
import java.util.List;
import java.util.Map;
import java.util.Set;
public abstract class BranchingCommand<T> implements CommandExecutor<T> {
private final String name;
private final Map<String, CommandExecutor<? extends T>> options = Maps.newHashMap();
private final Set<String> primaryAliases = Sets.newHashSet();
public BranchingCommand(String name) {
this.name = name;
}
public void putOption(CommandExecutor<? extends T> executor, String primaryAlias, String... aliases) {
options.put(primaryAlias, executor);
primaryAliases.add(primaryAlias);
for (String alias : aliases) {
options.put(alias, executor);
}
}
@Override
public T call(CommandArgs args, CommandLocals locals) throws CommandException {
try {
String classifier = args.next();
CommandExecutor<? extends T> executor = options.get(classifier.toLowerCase());
if (executor != null) {
return executor.call(args, locals);
} else {
throw new CommandException("'" + classifier + "' isn't a valid option for '" + name + "'. " +
"Try one of: " + Joiner.on(", ").join(primaryAliases));
}
} catch (MissingArgumentException e) {
throw new CommandException("Missing value for <" + name + "> " +
"(try one of " + Joiner.on(" | ").join(primaryAliases) + ").");
}
}
@Override
public List<String> getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException {
String classifier = args.next();
try {
CommandExecutor<? extends T> executor = options.get(classifier.toLowerCase());
if (executor != null) {
return executor.getSuggestions(args, locals);
}
} catch (MissingArgumentException ignored) {
}
return ArgumentUtils.getMatchingSuggestions((classifier.isEmpty() ? primaryAliases : options.keySet()), classifier);
}
@Override
public String getUsage() {
List<String> optionUsages = Lists.newArrayList();
for (String alias : primaryAliases) {
CommandExecutor<? extends T> executor = options.get(alias);
String usage = executor.getUsage();
if (usage.isEmpty()) {
optionUsages.add(alias);
} else {
optionUsages.add(alias + " " + executor.getUsage());
}
}
return "(" + Joiner.on(" | ").join(optionUsages) + ")";
}
@Override
public boolean testPermission(CommandLocals locals) {
for (CommandExecutor<?> executor : options.values()) {
if (!executor.testPermission(locals)) {
return false;
}
}
return true;
}
}

View File

@ -1,41 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.composition;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.util.command.argument.CommandArgs;
import com.sk89q.worldedit.util.command.argument.MissingArgumentException;
import java.util.List;
public interface CommandExecutor<T> {
T call(CommandArgs args, CommandLocals locals) throws CommandException;
List<String> getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException;
String getUsage();
String getDescription();
boolean testPermission(CommandLocals locals);
}

View File

@ -1,196 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.composition;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.util.command.argument.CommandArgs;
import com.sk89q.worldedit.util.command.argument.MissingArgumentException;
import com.sk89q.worldedit.util.command.composition.FlagParser.FlagData;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Nullable;
public class FlagParser implements CommandExecutor<FlagData> {
private final Map<Character, CommandExecutor<?>> flags = Maps.newHashMap();
public <T> Flag<T> registerFlag(char flag, CommandExecutor<T> executor) {
Flag<T> ret = new Flag<>(flag);
flags.put(flag, executor);
return ret;
}
@Override
public FlagData call(CommandArgs args, CommandLocals locals) throws CommandException {
Map<Character, Object> values = Maps.newHashMap();
try {
while (true) {
String next = args.peek();
if (next.equals("--")) {
args.next();
break;
} else if (next.length() > 0 && next.charAt(0) == '-') {
args.next();
if (next.length() == 1) {
throw new CommandException("- must be followed by a flag (like -a), otherwise use -- before the - (i.e. /cmd -- - is a dash).");
} else {
for (int i = 1; i < next.length(); i++) {
char flag = next.charAt(i);
CommandExecutor<?> executor = flags.get(flag);
if (executor != null) {
values.put(flag, executor.call(args, locals));
} else {
throw new CommandException("Unknown flag: -" + flag + " (try one of -" + Joiner.on("").join(flags.keySet()) + " or put -- to skip flag parsing, i.e. /cmd -- -this begins with a dash).");
}
}
}
} else {
break;
}
}
} catch (MissingArgumentException ignored) {
}
return new FlagData(values);
}
@Override
public List<String> getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException {
List<String> suggestions = Collections.emptyList();
while (true) {
String next = args.peek();
if (next.equals("--")) {
args.next();
break;
} else if (next.length() > 0 && next.charAt(0) == '-') {
args.next();
if (!args.hasNext()) { // Completing -| or -???|
List<String> flagSuggestions = Lists.newArrayList();
for (Character flag : flags.keySet()) {
if (next.indexOf(flag) < 1) { // Don't add any flags that the user has entered
flagSuggestions.add(next + flag);
}
}
return flagSuggestions;
} else { // Completing -??? ???|
for (int i = 1; i < next.length(); i++) {
char flag = next.charAt(i);
CommandExecutor<?> executor = flags.get(flag);
if (executor != null) {
suggestions = executor.getSuggestions(args, locals);
} else {
return suggestions;
}
}
}
} else {
return suggestions;
}
}
return suggestions;
}
@Override
public String getUsage() {
List<String> options = Lists.newArrayList();
for (Entry<Character, CommandExecutor<?>> entry : flags.entrySet()) {
String usage = entry.getValue().getUsage();
options.add("[-" + entry.getKey() + (!usage.isEmpty() ? " " + usage : "") + "]");
}
return Joiner.on(" ").join(options);
}
@Override
public String getDescription() {
return "Read flags";
}
@Override
public boolean testPermission(CommandLocals locals) {
for (CommandExecutor<?> executor : flags.values()) {
if (!executor.testPermission(locals)) {
return false;
}
}
return true;
}
public static class FlagData {
private final Map<Character, Object> data;
private FlagData(Map<Character, Object> data) {
this.data = data;
}
public int size() {
return data.size();
}
public boolean isEmpty() {
return data.isEmpty();
}
public Object get(char key) {
return data.get(key);
}
public boolean containsKey(char key) {
return data.containsKey(key);
}
}
public static final class Flag<T> {
private final char flag;
private Flag(char flag) {
this.flag = flag;
}
@SuppressWarnings("unchecked")
@Nullable
public T get(FlagData data) {
return (T) data.get(flag);
}
public T get(FlagData data, T fallback) {
T value = get(data);
if (value == null) {
return fallback;
} else {
return value;
}
}
}
}

View File

@ -1,87 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.composition;
import com.google.common.collect.Lists;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.util.command.CommandCallable;
import com.sk89q.worldedit.util.command.Description;
import com.sk89q.worldedit.util.command.SimpleDescription;
import com.sk89q.worldedit.util.command.argument.CommandArgs;
import com.sk89q.worldedit.util.command.argument.MissingArgumentException;
import com.sk89q.worldedit.util.command.argument.UnusedArgumentsException;
import java.util.List;
public class LegacyCommandAdapter implements CommandCallable {
private final CommandExecutor<?> executor;
private LegacyCommandAdapter(CommandExecutor<?> executor) {
this.executor = executor;
}
@Override
public final Object call(String arguments, CommandLocals locals, String[] parentCommands) throws CommandException {
CommandArgs args = new CommandArgs.Parser().parse(arguments);
if (args.hasNext()) {
if (args.uncheckedPeek().equals("-?")) {
throw new CommandException(executor.getUsage());
}
}
Object ret = executor.call(args, locals);
try {
args.requireAllConsumed();
} catch (UnusedArgumentsException e) {
throw new CommandException(e.getMessage());
}
return ret;
}
@Override
public Description getDescription() {
return new SimpleDescription()
.setDescription(executor.getDescription())
.overrideUsage(executor.getUsage());
}
@Override
public boolean testPermission(CommandLocals locals) {
return executor.testPermission(locals);
}
@Override
public List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException {
CommandArgs args = new CommandArgs.Parser().setUsingHangingArguments(true).parse(arguments);
try {
return executor.getSuggestions(args, locals);
} catch (MissingArgumentException e) {
return Lists.newArrayList();
}
}
public static LegacyCommandAdapter adapt(CommandExecutor<?> executor) {
return new LegacyCommandAdapter(executor);
}
}

View File

@ -1,79 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.composition;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.util.command.composition.FlagParser.Flag;
import java.util.List;
public abstract class ParameterCommand<T> implements CommandExecutor<T> {
private final List<CommandExecutor<?>> parameters = Lists.newArrayList();
private final FlagParser flagParser = new FlagParser();
public ParameterCommand() {
addParameter(flagParser);
}
protected List<CommandExecutor<?>> getParameters() {
return parameters;
}
public <E extends CommandExecutor<?>> E addParameter(E executor) {
parameters.add(executor);
return executor;
}
public <E> Flag<E> addFlag(char flag, CommandExecutor<E> executor) {
return flagParser.registerFlag(flag, executor);
}
protected FlagParser getFlagParser() {
return flagParser;
}
@Override
public final String getUsage() {
List<String> parts = Lists.newArrayList();
for (CommandExecutor<?> executor : parameters) {
String usage = executor.getUsage();
if (!usage.isEmpty()) {
parts.add(executor.getUsage());
}
}
return Joiner.on(" ").join(parts);
}
@Override
public final boolean testPermission(CommandLocals locals) {
for (CommandExecutor<?> executor : parameters) {
if (!executor.testPermission(locals)) {
return false;
}
}
return testPermission0(locals);
}
protected abstract boolean testPermission0(CommandLocals locals);
}

View File

@ -1,69 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.composition;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.util.command.argument.CommandArgs;
import com.sk89q.worldedit.util.command.argument.MissingArgumentException;
import java.util.Collections;
import java.util.List;
public class ProvidedValue<T> implements CommandExecutor<T> {
private final T value;
private final String description;
private ProvidedValue(T value, String description) {
this.value = value;
this.description = description;
}
@Override
public T call(CommandArgs args, CommandLocals locals) throws CommandException {
return value;
}
@Override
public List<String> getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException {
return Collections.emptyList();
}
@Override
public String getUsage() {
return "";
}
@Override
public String getDescription() {
return description;
}
@Override
public boolean testPermission(CommandLocals locals) {
return true;
}
public static <T> ProvidedValue<T> create(T value, String description) {
return new ProvidedValue<>(value, description);
}
}

View File

@ -1,54 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.composition;
import com.google.common.collect.Lists;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.util.command.argument.CommandArgs;
import com.sk89q.worldedit.util.command.argument.MissingArgumentException;
import java.util.List;
public abstract class SimpleCommand<T> extends ParameterCommand<T> {
@Override
public final List<String> getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException {
List<String> suggestions = Lists.newArrayList();
boolean seenParameter = false;
for (CommandExecutor<?> parameter : getParameters()) {
try {
suggestions = parameter.getSuggestions(args, locals);
seenParameter = true;
} catch (MissingArgumentException e) {
if (seenParameter) {
return suggestions;
} else {
throw e;
}
}
// There's nothing more anyway
if (args.position() == args.size()) {
return suggestions;
}
}
return suggestions;
}
}

View File

@ -1,84 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.fluent;
import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.util.command.SimpleDispatcher;
import com.sk89q.worldedit.util.command.parametric.ParametricBuilder;
/**
* A fluent interface to creating a command graph.
*
* <p>A command graph may have multiple commands, and multiple sub-commands below that,
* and possibly below that.</p>
*/
public class CommandGraph {
private final DispatcherNode rootDispatcher;
private ParametricBuilder builder;
/**
* Create a new command graph.
*/
public CommandGraph() {
SimpleDispatcher dispatcher = new SimpleDispatcher();
rootDispatcher = new DispatcherNode(this, null, dispatcher);
}
/**
* Get the root dispatcher node.
*
* @return the root dispatcher node
*/
public DispatcherNode commands() {
return rootDispatcher;
}
/**
* Get the {@link ParametricBuilder}.
*
* @return the builder, or null.
*/
public ParametricBuilder getBuilder() {
return builder;
}
/**
* Set the {@link ParametricBuilder} used for calls to
* {@link DispatcherNode#registerMethods(Object)}.
*
* @param builder the builder, or null
* @return this object
*/
public CommandGraph builder(ParametricBuilder builder) {
this.builder = builder;
return this;
}
/**
* Get the root dispatcher.
*
* @return the root dispatcher
*/
public Dispatcher getDispatcher() {
return rootDispatcher.getDispatcher();
}
}

View File

@ -1,139 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.fluent;
import com.sk89q.worldedit.util.command.CommandCallable;
import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.util.command.SimpleDispatcher;
import com.sk89q.worldedit.util.command.parametric.ParametricBuilder;
/**
* A collection of commands.
*/
public class DispatcherNode {
private final CommandGraph graph;
private final DispatcherNode parent;
private final SimpleDispatcher dispatcher;
/**
* Create a new instance.
*
* @param graph the root fluent graph object
* @param parent the parent node, or null
* @param dispatcher the dispatcher for this node
*/
DispatcherNode(CommandGraph graph, DispatcherNode parent,
SimpleDispatcher dispatcher) {
this.graph = graph;
this.parent = parent;
this.dispatcher = dispatcher;
}
/**
* Set the description.
*
* <p>This can only be used on {@link DispatcherNode}s returned by
* {@link #group(String...)}.</p>
*
* @param description the description
* @return this object
*/
public DispatcherNode describeAs(String description) {
dispatcher.getDescription().setDescription(description);
return this;
}
/**
* Register a command with this dispatcher.
*
* @param callable the executor
* @param alias the list of aliases, where the first alias is the primary one
*/
public DispatcherNode register(CommandCallable callable, String... alias) {
dispatcher.registerCommand(callable, alias);
return this;
}
/**
* Build and register a command with this dispatcher using the
* {@link ParametricBuilder} assigned on the root {@link CommandGraph}.
*
* @param object the object provided to the {@link ParametricBuilder}
* @return this object
* @see ParametricBuilder#registerMethodsAsCommands(com.sk89q.worldedit.util.command.Dispatcher, Object)
*/
public DispatcherNode registerMethods(Object object) {
ParametricBuilder builder = graph.getBuilder();
if (builder == null) {
throw new RuntimeException("No ParametricBuilder set");
}
builder.registerMethodsAsCommands(getDispatcher(), object);
return this;
}
/**
* Create a new command that will contain sub-commands.
*
* <p>The object returned by this method can be used to add sub-commands. To
* return to this "parent" context, use {@link DispatcherNode#graph()}.</p>
*
* @param alias the list of aliases, where the first alias is the primary one
* @return an object to place sub-commands
*/
public DispatcherNode group(String... alias) {
SimpleDispatcher command = new SimpleDispatcher();
getDispatcher().registerCommand(command, alias);
return new DispatcherNode(graph, this, command);
}
/**
* Return the parent node.
*
* @return the parent node
* @throws RuntimeException if there is no parent node.
*/
public DispatcherNode parent() {
if (parent != null) {
return parent;
}
throw new RuntimeException("This node does not have a parent");
}
/**
* Get the root command graph.
*
* @return the root command graph
*/
public CommandGraph graph() {
return graph;
}
/**
* Get the underlying dispatcher of this object.
*
* @return the dispatcher
*/
public Dispatcher getDispatcher() {
return dispatcher;
}
}

View File

@ -1,36 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
import com.sk89q.worldedit.util.command.SimpleDescription;
import java.lang.reflect.Method;
/**
* An abstract listener.
*/
public abstract class AbstractInvokeListener implements InvokeListener {
@Override
public void updateDescription(Object object, Method method,
ParameterData[] parameters, SimpleDescription description) {
}
}

View File

@ -1,78 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
import com.sk89q.minecraft.util.commands.CommandContext;
public interface ArgumentStack {
/**
* Get the next string, which may come from the stack or a value flag.
*
* @return the value
* @throws ParameterException on a parameter error
*/
String next() throws ParameterException;
/**
* Get the next integer, which may come from the stack or a value flag.
*
* @return the value
* @throws ParameterException on a parameter error
*/
Integer nextInt() throws ParameterException;
/**
* Get the next double, which may come from the stack or a value flag.
*
* @return the value
* @throws ParameterException on a parameter error
*/
Double nextDouble() throws ParameterException;
/**
* Get the next boolean, which may come from the stack or a value flag.
*
* @return the value
* @throws ParameterException on a parameter error
*/
Boolean nextBoolean() throws ParameterException;
/**
* Get all remaining string values, which will consume the rest of the stack.
*
* @return the value
* @throws ParameterException on a parameter error
*/
String remaining() throws ParameterException;
/**
* Set as completely consumed.
*/
void markConsumed();
/**
* Get the underlying context.
*
* @return the context
*/
CommandContext getContext();
}

View File

@ -1,93 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldedit.util.command.binding.PrimitiveBindings;
import com.sk89q.worldedit.util.command.binding.StandardBindings;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
import java.util.List;
/**
* Used to parse user input for a command, based on available method types
* and annotations.
*
* <p>A binding can be used to handle several types at once. For a binding to be
* called, it must be registered with a {@link ParametricBuilder} with
* {@link ParametricBuilder#addBinding(Binding, java.lang.reflect.Type...)}.</p>
*
* @see PrimitiveBindings an example of primitive bindings
* @see StandardBindings standard bindings
*/
public interface Binding {
/**
* Get the types that this binding handles.
*
* @return the types
*/
Type[] getTypes();
/**
* Get how this binding consumes from a {@link ArgumentStack}.
*
* @param parameter information about the parameter
* @return the behavior
*/
BindingBehavior getBehavior(ParameterData parameter);
/**
* Get the number of arguments that this binding will consume, if this
* information is available.
*
* <p>This method must return -1 for binding behavior types that are not
* {@link BindingBehavior#CONSUMES}.</p>
*
* @param parameter information about the parameter
* @return the number of consumed arguments, or -1 if unknown or irrelevant
*/
int getConsumedCount(ParameterData parameter);
/**
* Attempt to consume values (if required) from the given {@link ArgumentStack}
* in order to instantiate an object for the given parameter.
*
* @param parameter information about the parameter
* @param scoped the arguments the user has input
* @param onlyConsume true to only consume arguments
* @return an object parsed for the given parameter
* @throws ParameterException thrown if the parameter could not be formulated
* @throws CommandException on a command exception
*/
Object bind(ParameterData parameter, ArgumentStack scoped, boolean onlyConsume)
throws ParameterException, CommandException, InvocationTargetException;
/**
* Get a list of suggestions for the given parameter and user arguments.
*
* @param parameter information about the parameter
* @param prefix what the user has typed so far (may be an empty string)
* @return a list of suggestions
*/
List<String> getSuggestions(ParameterData parameter, String prefix);
}

View File

@ -1,52 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.util.command.binding.Switch;
/**
* Determines the type of binding.
*/
public enum BindingBehavior {
/**
* Always consumes from a {@link ArgumentStack}.
*/
CONSUMES,
/**
* Sometimes consumes from a {@link ArgumentStack}.
*
* <p>Bindings that exhibit this behavior must be defined as a {@link Switch}
* by commands utilizing the given binding.</p>
*/
INDETERMINATE,
/**
* Never consumes from a {@link ArgumentStack}.
*
* <p>Bindings that exhibit this behavior generate objects from other sources,
* such as from a {@link CommandLocals}. These are "magic" bindings that inject
* variables.</p>
*/
PROVIDES
}

View File

@ -1,224 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
import com.sk89q.minecraft.util.commands.CommandException;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* A binding helper that uses the {@link BindingMatch} annotation to make
* writing bindings extremely easy.
*
* <p>Methods must have the following and only the following parameters:</p>
*
* <ul>
* <li>A {@link ArgumentStack}</li>
* <li>A {@link Annotation} <strong>if there is a classifier set</strong></li>
* <li>A {@link Annotation}[]
* <strong>if there {@link BindingMatch#provideModifiers()} is true</strong></li>
* </ul>
*
* <p>Methods may throw any exception. Exceptions may be converted using a
* {@link ExceptionConverter} registered with the {@link ParametricBuilder}.</p>
*/
public class BindingHelper implements Binding {
private final List<BoundMethod> bindings;
private final Type[] types;
/**
* Create a new instance.
*/
public BindingHelper() {
List<BoundMethod> bindings = new ArrayList<>();
List<Type> types = new ArrayList<>();
for (Method method : this.getClass().getMethods()) {
BindingMatch info = method.getAnnotation(BindingMatch.class);
if (info != null) {
Class<? extends Annotation> classifier = null;
// Set classifier
if (!info.classifier().equals(Annotation.class)) {
classifier = info.classifier();
types.add(classifier);
}
for (Type t : info.type()) {
Type type = null;
// Set type
if (!t.equals(Class.class)) {
type = t;
if (classifier == null) {
types.add(type); // Only if there is no classifier set!
}
}
// Check to see if at least one is set
if (type == null && classifier == null) {
throw new RuntimeException(
"A @BindingMatch needs either a type or classifier set");
}
BoundMethod handler = new BoundMethod(info, type, classifier, method);
bindings.add(handler);
}
}
}
Collections.sort(bindings);
this.bindings = bindings;
Type[] typesArray = new Type[types.size()];
types.toArray(typesArray);
this.types = typesArray;
}
/**
* Match a {@link BindingMatch} according to the given parameter.
*
* @param parameter the parameter
* @return a binding
*/
private BoundMethod match(ParameterData parameter) {
for (BoundMethod binding : bindings) {
Annotation classifer = parameter.getClassifier();
Type type = parameter.getType();
if (binding.classifier != null) {
if (classifer != null && classifer.annotationType().equals(binding.classifier)) {
if (binding.type == null || binding.type.equals(type)) {
return binding;
}
}
} else if (binding.type.equals(type)) {
return binding;
}
}
throw new RuntimeException("Unknown type");
}
@Override
public Type[] getTypes() {
return types;
}
@Override
public int getConsumedCount(ParameterData parameter) {
return match(parameter).annotation.consumedCount();
}
@Override
public BindingBehavior getBehavior(ParameterData parameter) {
return match(parameter).annotation.behavior();
}
@Override
public Object bind(ParameterData parameter, ArgumentStack scoped,
boolean onlyConsume) throws ParameterException, CommandException, InvocationTargetException {
BoundMethod binding = match(parameter);
List<Object> args = new ArrayList<>();
args.add(scoped);
if (binding.classifier != null) {
args.add(parameter.getClassifier());
}
if (binding.annotation.provideModifiers()) {
args.add(parameter.getModifiers());
}
if (onlyConsume && binding.annotation.behavior() == BindingBehavior.PROVIDES) {
return null; // Nothing to consume, nothing to do
}
Object[] argsArray = new Object[args.size()];
args.toArray(argsArray);
try {
return binding.method.invoke(this, argsArray);
} catch (IllegalArgumentException e) {
throw new RuntimeException(
"Processing of classifier " + parameter.getClassifier() +
" and type " + parameter.getType() + " failed for method\n" +
binding.method + "\nbecause the parameters for that method are wrong", e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof ParameterException) {
throw (ParameterException) e.getCause();
} else if (e.getCause() instanceof CommandException) {
throw (CommandException) e.getCause();
}
throw e;
}
}
@Override
public List<String> getSuggestions(ParameterData parameter, String prefix) {
return new ArrayList<>();
}
private static class BoundMethod implements Comparable<BoundMethod> {
private final BindingMatch annotation;
private final Type type;
private final Class<? extends Annotation> classifier;
private final Method method;
BoundMethod(BindingMatch annotation, Type type,
Class<? extends Annotation> classifier, Method method) {
this.annotation = annotation;
this.type = type;
this.classifier = classifier;
this.method = method;
}
@Override
public int compareTo(BoundMethod o) {
if (classifier != null && o.classifier == null) {
return -1;
} else if (classifier == null && o.classifier != null) {
return 1;
} else if (classifier != null && o.classifier != null) {
if (type != null && o.type == null) {
return -1;
} else if (type == null && o.type != null) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
}
}
}

View File

@ -1,71 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Denotes a match of a binding.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BindingMatch {
/**
* The classifier.
*
* @return the classifier, or {@link Annotation} if not set
*/
Class<? extends Annotation> classifier() default Annotation.class;
/**
* The type.
*
* @return the type, or {@link Class} if not set
*/
Class<?>[] type() default Class.class;
/**
* The binding behavior.
*
* @return the behavior
*/
BindingBehavior behavior();
/**
* Get the number of arguments that this binding consumes.
*
* @return -1 if unknown or irrelevant
*/
int consumedCount() default -1;
/**
* Set whether an array of modifier annotations is provided in the list of
* arguments.
*
* @return true to provide modifiers
*/
boolean provideModifiers() default false;
}

View File

@ -1,178 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.worldedit.util.command.MissingParameterException;
/**
* Makes an instance of a {@link CommandContext} into a stack of arguments
* that can be consumed.
*
* @see ParametricBuilder a user of this class
*/
public class ContextArgumentStack implements ArgumentStack {
private final CommandContext context;
private int index = 0;
private int markedIndex = 0;
/**
* Create a new instance using the given context.
*
* @param context the context
*/
public ContextArgumentStack(CommandContext context) {
this.context = context;
}
@Override
public String next() throws ParameterException {
try {
return context.getString(index++);
} catch (IndexOutOfBoundsException e) {
throw new MissingParameterException();
}
}
@Override
public Integer nextInt() throws ParameterException {
try {
return Integer.parseInt(next());
} catch (NumberFormatException e) {
throw new ParameterException(
"Expected a number, got '" + context.getString(index - 1) + "'");
}
}
@Override
public Double nextDouble() throws ParameterException {
try {
return Double.parseDouble(next());
} catch (NumberFormatException e) {
throw new ParameterException(
"Expected a number, got '" + context.getString(index - 1) + "'");
}
}
@Override
public Boolean nextBoolean() throws ParameterException {
try {
return next().equalsIgnoreCase("true");
} catch (IndexOutOfBoundsException e) {
throw new MissingParameterException();
}
}
@Override
public String remaining() throws ParameterException {
try {
String value = context.getJoinedStrings(index);
index = context.argsLength();
return value;
} catch (IndexOutOfBoundsException e) {
throw new MissingParameterException();
}
}
/**
* Get the unconsumed arguments left over, without touching the stack.
*
* @return the unconsumed arguments
*/
public String getUnconsumed() {
if (index >= context.argsLength()) {
return null;
}
return context.getJoinedStrings(index);
}
@Override
public void markConsumed() {
index = context.argsLength();
}
/**
* Return the current position.
*
* @return the position
*/
public int position() {
return index;
}
/**
* Mark the current position of the stack.
*
* <p>The marked position initially starts at 0.</p>
*/
public void mark() {
markedIndex = index;
}
/**
* Reset to the previously {@link #mark()}ed position of the stack, and return
* the arguments that were consumed between this point and that previous point.
*
* <p>The marked position initially starts at 0.</p>
*
* @return the consumed arguments
*/
public String reset() {
String value = context.getString(markedIndex, index);
index = markedIndex;
return value;
}
/**
* Return whether any arguments were consumed between the marked position
* and the current position.
*
* <p>The marked position initially starts at 0.</p>
*
* @return true if values were consumed.
*/
public boolean wasConsumed() {
return markedIndex != index;
}
/**
* Return the arguments that were consumed between this point and that marked point.
*
* <p>The marked position initially starts at 0.</p>
*
* @return the consumed arguments
*/
public String getConsumed() {
return context.getString(markedIndex, index);
}
/**
* Get the underlying context.
*
* @return the context
*/
@Override
public CommandContext getContext() {
return context;
}
}

View File

@ -24,27 +24,26 @@ import org.enginehub.piston.exception.CommandException;
import org.enginehub.piston.exception.CommandExecutionException;
/**
* Used to convert a recognized {@link Throwable} into an appropriate
* Used to convert a recognized {@link Throwable} into an appropriate
* {@link CommandException}.
*
* <p>Methods (when invoked by a {@link ParametricBuilder}-created command) may throw
* relevant exceptions that are not caught by the command manager, but translate
* into reasonable exceptions for an application. However, unknown exceptions are
*
* <p>Methods may throw relevant exceptions that are not caught by the command manager,
* but translate into reasonable exceptions for an application. However, unknown exceptions are
* normally simply wrapped in a {@link CommandExecutionException} and bubbled up. Only
* normal {@link CommandException}s will be printed correctly, so a converter translates
* one of these unknown exceptions into an appropriate {@link CommandException}.</p>
*
*
* <p>This also allows the code calling the command to not need be aware of these
* application-specific exceptions, as they will all be converted to
* {@link CommandException}s that are handled normally.</p>
*/
public interface ExceptionConverter {
/**
* Attempt to convert the given throwable into a {@link CommandException}.
*
*
* <p>If the exception is not recognized, then nothing should be thrown.</p>
*
*
* @param t the throwable
* @throws CommandException a command exception
*/

View File

@ -1,82 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import java.lang.reflect.Method;
/**
* Called before and after a command is invoked for commands executed by a command
* created using {@link ParametricBuilder}.
*
* <p>Invocation handlers are created by {@link InvokeListener}s. Multiple
* listeners and handlers can be registered, and all be run. However, if one handler
* throws an exception, future handlers will not execute and the command will
* not execute (if thrown in
* {@link #preInvoke(Object, Method, ParameterData[], Object[], CommandContext)}).</p>
*
* @see InvokeListener the factory
*/
public interface InvokeHandler {
/**
* Called before parameters are processed.
*
* @param object the object
* @param method the method
* @param parameters the list of parameters
* @param context the context
* @throws CommandException can be thrown for an error, which will stop invocation
* @throws ParameterException on parameter error
*/
void preProcess(Object object, Method method, ParameterData[] parameters,
CommandContext context) throws CommandException, ParameterException;
/**
* Called before the parameter is invoked.
*
* @param object the object
* @param method the method
* @param parameters the list of parameters
* @param args the arguments to be given to the method
* @param context the context
* @throws CommandException can be thrown for an error, which will stop invocation
* @throws ParameterException on parameter error
*/
void preInvoke(Object object, Method method, ParameterData[] parameters,
Object[] args, CommandContext context) throws CommandException, ParameterException;
/**
* Called after the parameter is invoked.
*
* @param object the object
* @param method the method
* @param parameters the list of parameters
* @param args the arguments to be given to the method
* @param context the context
* @throws CommandException can be thrown for an error
* @throws ParameterException on parameter error
*/
void postInvoke(Object object, Method method, ParameterData[] parameters,
Object[] args, CommandContext context) throws CommandException, ParameterException;
}

View File

@ -1,58 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.util.command.CommandCallable;
import com.sk89q.worldedit.util.command.SimpleDescription;
import java.lang.reflect.Method;
/**
* Listens to events related to {@link ParametricBuilder}.
*/
public interface InvokeListener {
/**
* Create a new invocation handler.
*
* <p>An example use of an {@link InvokeHandler} would be to verify permissions
* added by the {@link CommandPermissions} annotation.</p>
*
* <p>For simple {@link InvokeHandler}, an object can implement both this
* interface and {@link InvokeHandler}.</p>
*
* @return a new invocation handler
*/
InvokeHandler createInvokeHandler();
/**
* During creation of a {@link CommandCallable} by a {@link ParametricBuilder},
* this will be called in case the description needs to be updated.
*
* @param object the object
* @param method the method
* @param parameters a list of parameters
* @param description the description to be updated
*/
void updateDescription(Object object, Method method, ParameterData[] parameters,
SimpleDescription description);
}

View File

@ -1,97 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldedit.util.command.MissingParameterException;
import com.sk89q.worldedit.util.command.SimpleDescription;
import com.sk89q.worldedit.util.command.UnconsumedParameterException;
import java.lang.reflect.Method;
/**
* Handles legacy properties on {@link Command} such as {@link Command#min()} and
* {@link Command#max()}.
*/
public class LegacyCommandsHandler extends AbstractInvokeListener implements InvokeHandler {
@Override
public InvokeHandler createInvokeHandler() {
return this;
}
@Override
public void preProcess(Object object, Method method,
ParameterData[] parameters, CommandContext context)
throws CommandException, ParameterException {
}
@Override
public void preInvoke(Object object, Method method,
ParameterData[] parameters, Object[] args, CommandContext context)
throws ParameterException {
Command annotation = method.getAnnotation(Command.class);
if (annotation != null) {
if (context.argsLength() < annotation.min()) {
throw new MissingParameterException();
}
if (annotation.max() != -1 && context.argsLength() > annotation.max()) {
throw new UnconsumedParameterException(
context.getRemainingString(annotation.max()));
}
}
}
@Override
public void postInvoke(Object object, Method method,
ParameterData[] parameters, Object[] args, CommandContext context) {
}
@Override
public void updateDescription(Object object, Method method,
ParameterData[] parameters, SimpleDescription description) {
Command annotation = method.getAnnotation(Command.class);
// Handle the case for old commands where no usage is set and all of its
// parameters are provider bindings, so its usage information would
// be blank and would imply that there were no accepted parameters
if (annotation != null && annotation.usage().isEmpty()
&& (annotation.min() > 0 || annotation.max() > 0)) {
boolean hasUserParameters = false;
for (ParameterData parameter : parameters) {
if (parameter.getBinding().getBehavior(parameter) != BindingBehavior.PROVIDES) {
hasUserParameters = true;
break;
}
}
if (!hasUserParameters) {
description.overrideUsage("(unknown usage information)");
}
}
}
}

View File

@ -1,41 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Indicates an optional parameter.
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Optional {
/**
* The default value to use if no value is set.
*
* @return a string value, or an empty list
*/
String[] value() default {};
}

View File

@ -1,194 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
import com.sk89q.worldedit.util.command.SimpleParameter;
import com.sk89q.worldedit.util.command.binding.PrimitiveBindings;
import com.sk89q.worldedit.util.command.binding.Range;
import com.sk89q.worldedit.util.command.binding.Text;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
/**
* Describes a parameter in detail.
*/
public class ParameterData extends SimpleParameter {
private Binding binding;
private Annotation classifier;
private Annotation[] modifiers;
private Type type;
/**
* Get the binding associated with this parameter.
*
* @return the binding
*/
public Binding getBinding() {
return binding;
}
/**
* Set the binding associated with this parameter.
*
* @param binding the binding
*/
void setBinding(Binding binding) {
this.binding = binding;
}
/**
* Set the main type of this parameter.
*
* <p>The type is normally that is used to determine which binding is used
* for a particular method's parameter.</p>
*
* @return the main type
* @see #getClassifier() which can override the type
*/
public Type getType() {
return type;
}
/**
* Set the main type of this parameter.
*
* @param type the main type
*/
void setType(Type type) {
this.type = type;
}
/**
* Get the classifier annotation.
*
* <p>Normally, the type determines what binding is called, but classifiers
* take precedence if one is found (and registered with
* {@link ParametricBuilder#addBinding(Binding, Type...)}).
* An example of a classifier annotation is {@link Text}.</p>
*
* @return the classifier annotation, null is possible
*/
public Annotation getClassifier() {
return classifier;
}
/**
* Set the classifier annotation.
*
* @param classifier the classifier annotation, null is possible
*/
void setClassifier(Annotation classifier) {
this.classifier = classifier;
}
/**
* Get a list of modifier annotations.
*
* <p>Modifier annotations are not considered in the process of choosing a binding
* for a method parameter, but they can be used to modify the behavior of a binding.
* An example of a modifier annotation is {@link Range}, which can restrict
* numeric values handled by {@link PrimitiveBindings} to be within a range. The list
* of annotations may contain a classifier and other unrelated annotations.</p>
*
* @return a list of annotations
*/
public Annotation[] getModifiers() {
return modifiers;
}
/**
* Set the list of modifiers.
*
* @param modifiers a list of annotations
*/
void setModifiers(Annotation[] modifiers) {
this.modifiers = modifiers;
}
/**
* Return the number of arguments this binding consumes.
*
* @return -1 if unknown or unavailable
*/
int getConsumedCount() {
return getBinding().getConsumedCount(this);
}
/**
* Get whether this parameter is entered by the user.
*
* @return true if this parameter is entered by the user.
*/
boolean isUserInput() {
return getBinding().getBehavior(this) != BindingBehavior.PROVIDES;
}
/**
* Get whether this parameter consumes non-flag arguments.
*
* @return true if this parameter consumes non-flag arguments
*/
boolean isNonFlagConsumer() {
return getBinding().getBehavior(this) != BindingBehavior.PROVIDES && !isValueFlag();
}
/**
* Validate this parameter and its binding.
*/
void validate(Method method, int parameterIndex) throws ParametricException {
// We can't have indeterminate consumers without @Switches otherwise
// it may screw up parameter processing for later bindings
BindingBehavior behavior = getBinding().getBehavior(this);
boolean indeterminate = (behavior == BindingBehavior.INDETERMINATE);
if (!isValueFlag() && indeterminate) {
throw new ParametricException(
"@Switch missing for indeterminate consumer\n\n" +
"Notably:\nFor the type " + type + ", the binding " +
getBinding().getClass().getCanonicalName() +
"\nmay or may not consume parameters (isIndeterminateConsumer(" + type + ") = true)" +
"\nand therefore @Switch(flag) is required for parameter #" + parameterIndex + " of \n" +
method.toGenericString());
}
// getConsumedCount() better return -1 if the BindingBehavior is not CONSUMES
if (behavior != BindingBehavior.CONSUMES && binding.getConsumedCount(this) != -1) {
throw new ParametricException(
"getConsumedCount() does not return -1 for binding " +
getBinding().getClass().getCanonicalName() +
"\neven though its behavior type is " + behavior.name() +
"\nfor parameter #" + parameterIndex + " of \n" +
method.toGenericString());
}
// getConsumedCount() should not return 0 if the BindingBehavior is not PROVIDES
if (behavior != BindingBehavior.PROVIDES && binding.getConsumedCount(this) == 0) {
throw new ParametricException(
"getConsumedCount() must not return 0 for binding " +
getBinding().getClass().getCanonicalName() +
"\nwhen its behavior type is " + behavior.name() + " and not PROVIDES " +
"\nfor parameter #" + parameterIndex + " of \n" +
method.toGenericString());
}
}
}

View File

@ -1,43 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
/**
* Thrown if there is an error with a parameter.
*/
public class ParameterException extends Exception {
public ParameterException() {
super();
}
public ParameterException(String message) {
super(message);
}
public ParameterException(Throwable cause) {
super(cause);
}
public ParameterException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -1,230 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.ImmutableBiMap.Builder;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.util.auth.Authorizer;
import com.sk89q.worldedit.util.auth.NullAuthorizer;
import com.sk89q.worldedit.util.command.CommandCallable;
import com.sk89q.worldedit.util.command.CommandCompleter;
import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.util.command.NullCompleter;
import com.sk89q.worldedit.util.command.binding.PrimitiveBindings;
import com.sk89q.worldedit.util.command.binding.StandardBindings;
import com.sk89q.worldedit.util.command.binding.Switch;
import com.thoughtworks.paranamer.CachingParanamer;
import com.thoughtworks.paranamer.Paranamer;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Creates commands using annotations placed on methods and individual parameters of
* such methods.
*
* @see Command defines a command
* @see Switch defines a flag
*/
public class ParametricBuilder {
private final Map<Type, Binding> bindings = new HashMap<>();
private final Paranamer paranamer = new CachingParanamer();
private final List<InvokeListener> invokeListeners = new ArrayList<>();
private Authorizer authorizer = new NullAuthorizer();
private CommandCompleter defaultCompleter = new NullCompleter();
/**
* Create a new builder.
*
* <p>This method will install {@link PrimitiveBindings} and
* {@link StandardBindings} and default bindings.</p>
*/
public ParametricBuilder() {
addBinding(new PrimitiveBindings());
addBinding(new StandardBindings());
}
/**
* Add a binding for a given type or classifier (annotation).
*
* <p>Whenever a method parameter is encountered, a binding must be found for it
* so that it can be called later to consume the stack of arguments provided by
* the user and return an object that is later passed to
* {@link Method#invoke(Object, Object...)}.</p>
*
* <p>Normally, a {@link Type} is used to discern between different bindings, but
* if this is not specific enough, an annotation can be defined and used. This
* makes it a "classifier" and it will take precedence over the base type. For
* example, even if there is a binding that handles {@link String} parameters,
* a special {@code @MyArg} annotation can be assigned to a {@link String}
* parameter, which will cause the {@link Builder} to consult the {@link Binding}
* associated with {@code @MyArg} rather than with the binding for
* the {@link String} type.</p>
*
* @param binding the binding
* @param type a list of types (if specified) to override the binding's types
*/
public void addBinding(Binding binding, Type... type) {
if (type == null || type.length == 0) {
type = binding.getTypes();
}
for (Type t : type) {
bindings.put(t, binding);
}
}
/**
* Attach an invocation listener.
*
* <p>Invocation handlers are called in order that their listeners are
* registered with a {@link ParametricBuilder}. It is not guaranteed that
* a listener may be called, in the case of a {@link CommandException} being
* thrown at any time before the appropriate listener or handler is called.
* It is possible for a
* {@link InvokeHandler#preInvoke(Object, Method, ParameterData[], Object[], CommandContext)} to
* be called for a invocation handler, but not the associated
* {@link InvokeHandler#postInvoke(Object, Method, ParameterData[], Object[], CommandContext)}.</p>
*
* <p>An example of an invocation listener is one to handle
* {@link CommandPermissions}, by first checking to see if permission is available
* in a {@link InvokeHandler#preInvoke(Object, Method, ParameterData[], Object[], CommandContext)}
* call. If permission is not found, then an appropriate {@link CommandException}
* can be thrown to cease invocation.</p>
*
* @param listener the listener
* @see InvokeHandler the handler
*/
public void addInvokeListener(InvokeListener listener) {
invokeListeners.add(listener);
}
/**
* Build a list of commands from methods specially annotated with {@link Command}
* (and other relevant annotations) and register them all with the given
* {@link Dispatcher}.
*
* @param dispatcher the dispatcher to register commands with
* @param object the object contain the methods
* @throws ParametricException thrown if the commands cannot be registered
*/
public void registerMethodsAsCommands(Dispatcher dispatcher, Object object) throws ParametricException {
for (Method method : object.getClass().getDeclaredMethods()) {
Command definition = method.getAnnotation(Command.class);
if (definition != null) {
CommandCallable callable = build(object, method, definition);
dispatcher.registerCommand(callable, definition.aliases());
}
}
}
/**
* Build a {@link CommandCallable} for the given method.
*
* @param object the object to be invoked on
* @param method the method to invoke
* @param definition the command definition annotation
* @return the command executor
* @throws ParametricException thrown on an error
*/
private CommandCallable build(Object object, Method method, Command definition)
throws ParametricException {
return new ParametricCallable(this, object, method, definition);
}
/**
* Get the object used to get method names on Java versions before 8 (assuming
* that Java 8 is given the ability to reliably reflect method names at runtime).
*
* @return the paranamer
*/
Paranamer getParanamer() {
return paranamer;
}
/**
* Get the map of bindings.
*
* @return the map of bindings
*/
Map<Type, Binding> getBindings() {
return bindings;
}
/**
* Get a list of invocation listeners.
*
* @return a list of invocation listeners
*/
List<InvokeListener> getInvokeListeners() {
return invokeListeners;
}
/**
* Get the authorizer.
*
* @return the authorizer
*/
public Authorizer getAuthorizer() {
return authorizer;
}
/**
* Set the authorizer.
*
* @param authorizer the authorizer
*/
public void setAuthorizer(Authorizer authorizer) {
checkNotNull(authorizer);
this.authorizer = authorizer;
}
/**
* Get the default command suggestions provider that will be used if
* no suggestions are available.
*
* @return the default command completer
*/
public CommandCompleter getDefaultCompleter() {
return defaultCompleter;
}
/**
* Set the default command suggestions provider that will be used if
* no suggestions are available.
*
* @param defaultCompleter the default command completer
*/
public void setDefaultCompleter(CommandCompleter defaultCompleter) {
checkNotNull(defaultCompleter);
this.defaultCompleter = defaultCompleter;
}
}

View File

@ -1,479 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
import com.google.common.primitives.Chars;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
import com.sk89q.minecraft.util.commands.WrappedCommandException;
import com.sk89q.worldedit.util.command.CommandCallable;
import com.sk89q.worldedit.util.command.InvalidUsageException;
import com.sk89q.worldedit.util.command.MissingParameterException;
import com.sk89q.worldedit.util.command.Parameter;
import com.sk89q.worldedit.util.command.SimpleDescription;
import com.sk89q.worldedit.util.command.UnconsumedParameterException;
import com.sk89q.worldedit.util.command.binding.Switch;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* The implementation of a {@link CommandCallable} for the {@link ParametricBuilder}.
*/
class ParametricCallable implements CommandCallable {
private final ParametricBuilder builder;
private final Object object;
private final Method method;
private final ParameterData[] parameters;
private final Set<Character> valueFlags = new HashSet<>();
private final boolean anyFlags;
private final Set<Character> legacyFlags = new HashSet<>();
private final SimpleDescription description = new SimpleDescription();
private final CommandPermissions commandPermissions;
/**
* Create a new instance.
*
* @param builder the parametric builder
* @param object the object to invoke on
* @param method the method to invoke
* @param definition the command definition annotation
* @throws ParametricException thrown on an error
*/
ParametricCallable(ParametricBuilder builder, Object object, Method method, Command definition) throws ParametricException {
this.builder = builder;
this.object = object;
this.method = method;
Annotation[][] annotations = method.getParameterAnnotations();
String[] names = builder.getParanamer().lookupParameterNames(method, false);
Type[] types = method.getGenericParameterTypes();
parameters = new ParameterData[types.length];
List<Parameter> userParameters = new ArrayList<>();
// This helps keep tracks of @Nullables that appear in the middle of a list
// of parameters
int numOptional = 0;
// Set permission hint
CommandPermissions permHint = method.getAnnotation(CommandPermissions.class);
if (permHint != null) {
description.setPermissions(Arrays.asList(permHint.value()));
}
// Go through each parameter
for (int i = 0; i < types.length; i++) {
Type type = types[i];
ParameterData parameter = new ParameterData();
parameter.setType(type);
parameter.setModifiers(annotations[i]);
// Search for annotations
for (Annotation annotation : annotations[i]) {
if (annotation instanceof Switch) {
parameter.setFlag(((Switch) annotation).value(), type != boolean.class);
} else if (annotation instanceof Optional) {
parameter.setOptional(true);
String[] value = ((Optional) annotation).value();
if (value.length > 0) {
parameter.setDefaultValue(value);
}
// Special annotation bindings
} else if (parameter.getBinding() == null) {
parameter.setBinding(builder.getBindings().get(annotation.annotationType()));
parameter.setClassifier(annotation);
}
}
parameter.setName(names.length > 0 ? names[i] : generateName(type, parameter.getClassifier(), i));
// Track all value flags
if (parameter.isValueFlag()) {
valueFlags.add(parameter.getFlag());
}
// No special @annotation binding... let's check for the type
if (parameter.getBinding() == null) {
parameter.setBinding(builder.getBindings().get(type));
// Don't know how to parse for this type of value
if (parameter.getBinding() == null) {
throw new ParametricException("Don't know how to handle the parameter type '" + type + "' in\n" + method.toGenericString());
}
}
// Do some validation of this parameter
parameter.validate(method, i + 1);
// Keep track of optional parameters
if (parameter.isOptional() && parameter.getFlag() == null) {
numOptional++;
} else {
if (numOptional > 0 && parameter.isNonFlagConsumer()) {
if (parameter.getConsumedCount() < 0) {
throw new ParametricException(
"Found an parameter using the binding " +
parameter.getBinding().getClass().getCanonicalName() +
"\nthat does not know how many arguments it consumes, but " +
"it follows an optional parameter\nMethod: " +
method.toGenericString());
}
}
}
parameters[i] = parameter;
// Make a list of "real" parameters
if (parameter.isUserInput()) {
userParameters.add(parameter);
}
}
// Gather legacy flags
anyFlags = definition.anyFlags();
legacyFlags.addAll(Chars.asList(definition.flags().toCharArray()));
// Finish description
description.setDescription(!definition.desc().isEmpty() ? definition.desc() : null);
description.setHelp(!definition.help().isEmpty() ? definition.help() : null);
description.overrideUsage(!definition.usage().isEmpty() ? definition.usage() : null);
for (InvokeListener listener : builder.getInvokeListeners()) {
listener.updateDescription(object, method, parameters, description);
}
// Set parameters
description.setParameters(userParameters);
// Get permissions annotation
commandPermissions = method.getAnnotation(CommandPermissions.class);
}
@Override
public Object call(String stringArguments, CommandLocals locals, String[] parentCommands) throws CommandException {
// Test permission
if (parentCommands.length != 0 && !testPermission(locals)) {
throw new CommandPermissionsException();
}
String calledCommand = parentCommands.length > 0 ? parentCommands[parentCommands.length - 1] : "_";
String[] split = CommandContext.split(calledCommand + " " + stringArguments);
CommandContext context = new CommandContext(split, getValueFlags(), false, locals);
// Provide help if -? is specified
if (context.hasFlag('?')) {
throw new InvalidUsageException(null, this, true);
}
Object[] args = new Object[parameters.length];
ContextArgumentStack arguments = new ContextArgumentStack(context);
ParameterData parameter = null;
try {
// preProcess handlers
List<InvokeHandler> handlers = new ArrayList<>();
for (InvokeListener listener : builder.getInvokeListeners()) {
InvokeHandler handler = listener.createInvokeHandler();
handlers.add(handler);
handler.preProcess(object, method, parameters, context);
}
// Collect parameters
for (int i = 0; i < parameters.length; i++) {
parameter = parameters[i];
if (mayConsumeArguments(i, arguments)) {
// Parse the user input into a method argument
ArgumentStack usedArguments = getScopedContext(parameter, arguments);
try {
args[i] = parameter.getBinding().bind(parameter, usedArguments, false);
} catch (MissingParameterException e) {
// Not optional? Then we can't execute this command
if (!parameter.isOptional()) {
throw e;
}
args[i] = getDefaultValue(i, arguments);
}
} else {
args[i] = getDefaultValue(i, arguments);
}
}
// Check for unused arguments
checkUnconsumed(arguments);
// preInvoke handlers
for (InvokeHandler handler : handlers) {
handler.preInvoke(object, method, parameters, args, context);
}
// Execute!
method.invoke(object, args);
// postInvoke handlers
for (InvokeHandler handler : handlers) {
handler.postInvoke(handler, method, parameters, args, context);
}
} catch (MissingParameterException e) {
throw new InvalidUsageException("Too few parameters!", this);
} catch (UnconsumedParameterException e) {
throw new InvalidUsageException("Too many parameters! Unused parameters: " + e.getUnconsumed(), this);
} catch (ParameterException e) {
assert parameter != null;
String name = parameter.getName();
throw new InvalidUsageException("For parameter '" + name + "': " + e.getMessage(), this);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof CommandException) {
throw (CommandException) e.getCause();
}
throw new WrappedCommandException(e);
} catch (Throwable t) {
throw new WrappedCommandException(t);
}
return true;
}
@Override
public List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException {
return builder.getDefaultCompleter().getSuggestions(arguments, locals);
}
/**
* Get a list of value flags used by this command.
*
* @return a list of value flags
*/
public Set<Character> getValueFlags() {
return valueFlags;
}
@Override
public SimpleDescription getDescription() {
return description;
}
@Override
public boolean testPermission(CommandLocals locals) {
if (commandPermissions != null) {
for (String perm : commandPermissions.value()) {
if (builder.getAuthorizer().testPermission(locals, perm)) {
return true;
}
}
return false;
} else {
return true;
}
}
/**
* Get the right {@link ArgumentStack}.
*
* @param parameter the parameter
* @param existing the existing scoped context
* @return the context to use
*/
private static ArgumentStack getScopedContext(Parameter parameter, ArgumentStack existing) {
if (parameter.getFlag() != null) {
CommandContext context = existing.getContext();
if (parameter.isValueFlag()) {
return new StringArgumentStack(context, context.getFlag(parameter.getFlag()), false);
} else {
String v = context.hasFlag(parameter.getFlag()) ? "true" : "false";
return new StringArgumentStack(context, v, true);
}
}
return existing;
}
/**
* Get whether a parameter is allowed to consume arguments.
*
* @param i the index of the parameter
* @param scoped the scoped context
* @return true if arguments may be consumed
*/
private boolean mayConsumeArguments(int i, ContextArgumentStack scoped) {
CommandContext context = scoped.getContext();
ParameterData parameter = parameters[i];
// Flag parameters: Always consume
// Required non-flag parameters: Always consume
// Optional non-flag parameters:
// - Before required parameters: Consume if there are 'left over' args
// - At the end: Always consumes
if (parameter.isOptional()) {
if (parameter.getFlag() != null) {
return !parameter.isValueFlag() || context.hasFlag(parameter.getFlag());
} else {
int numberFree = context.argsLength() - scoped.position();
for (int j = i; j < parameters.length; j++) {
if (parameters[j].isNonFlagConsumer() && !parameters[j].isOptional()) {
// We already checked if the consumed count was > -1
// when we created this object
numberFree -= parameters[j].getConsumedCount();
}
}
// Skip this optional parameter
if (numberFree < 1) {
return false;
}
}
}
return true;
}
/**
* Get the default value for a parameter.
*
* @param i the index of the parameter
* @param scoped the scoped context
* @return a value
* @throws ParameterException on an error
* @throws CommandException on an error
*/
private Object getDefaultValue(int i, ContextArgumentStack scoped) throws ParameterException, CommandException, InvocationTargetException {
CommandContext context = scoped.getContext();
ParameterData parameter = parameters[i];
String[] defaultValue = parameter.getDefaultValue();
if (defaultValue != null) {
try {
return parameter.getBinding().bind(parameter, new StringArgumentStack(context, defaultValue, false), false);
} catch (MissingParameterException e) {
throw new ParametricException(
"The default value of the parameter using the binding " +
parameter.getBinding().getClass() + " in the method\n" +
method.toGenericString() + "\nis invalid");
}
}
return null;
}
/**
* Check to see if all arguments, including flag arguments, were consumed.
*
* @param scoped the argument scope
* @throws UnconsumedParameterException thrown if parameters were not consumed
*/
private void checkUnconsumed(ContextArgumentStack scoped) throws UnconsumedParameterException {
CommandContext context = scoped.getContext();
String unconsumed;
String unconsumedFlags = getUnusedFlags(context);
if ((unconsumed = scoped.getUnconsumed()) != null) {
throw new UnconsumedParameterException(unconsumed + " " + unconsumedFlags);
}
if (unconsumedFlags != null) {
throw new UnconsumedParameterException(unconsumedFlags);
}
}
/**
* Get any unused flag arguments.
*
* @param context the command context
*/
private String getUnusedFlags(CommandContext context) {
if (!anyFlags) {
Set<Character> unusedFlags = null;
for (char flag : context.getFlags()) {
boolean found = false;
if (legacyFlags.contains(flag)) {
break;
}
for (ParameterData parameter : parameters) {
Character paramFlag = parameter.getFlag();
if (paramFlag != null && flag == paramFlag) {
found = true;
break;
}
}
if (!found) {
if (unusedFlags == null) {
unusedFlags = new HashSet<>();
}
unusedFlags.add(flag);
}
}
if (unusedFlags != null) {
StringBuilder builder = new StringBuilder();
for (Character flag : unusedFlags) {
builder.append("-").append(flag).append(" ");
}
return builder.toString().trim();
}
}
return null;
}
/**
* Generate a name for a parameter.
*
* @param type the type
* @param classifier the classifier
* @param index the index
* @return a generated name
*/
private static String generateName(Type type, Annotation classifier, int index) {
if (classifier != null) {
return classifier.annotationType().getSimpleName().toLowerCase();
} else {
if (type instanceof Class<?>) {
return ((Class<?>) type).getSimpleName().toLowerCase();
} else {
return "unknown" + index;
}
}
}
}

View File

@ -1,44 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
/**
* Thrown if the {@link ParametricBuilder} can't build commands from
* an object for whatever reason.
*/
public class ParametricException extends RuntimeException {
public ParametricException() {
super();
}
public ParametricException(String message, Throwable cause) {
super(message, cause);
}
public ParametricException(String message) {
super(message);
}
public ParametricException(Throwable cause) {
super(cause);
}
}

View File

@ -1,128 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.util.StringUtil;
import com.sk89q.worldedit.util.command.MissingParameterException;
/**
* A virtual scope that does not actually read from the underlying
* {@link CommandContext}.
*/
public class StringArgumentStack implements ArgumentStack {
private final boolean nonNullBoolean;
private final CommandContext context;
private final String[] arguments;
private int index = 0;
/**
* Create a new instance using the given context.
*
* @param context the context
* @param arguments a list of arguments
* @param nonNullBoolean true to have {@link #nextBoolean()} return false instead of null
*/
public StringArgumentStack(
CommandContext context, String[] arguments, boolean nonNullBoolean) {
this.context = context;
this.arguments = arguments;
this.nonNullBoolean = nonNullBoolean;
}
/**
* Create a new instance using the given context.
*
* @param context the context
* @param arguments an argument string to be parsed
* @param nonNullBoolean true to have {@link #nextBoolean()} return false instead of null
*/
public StringArgumentStack(
CommandContext context, String arguments, boolean nonNullBoolean) {
this.context = context;
this.arguments = CommandContext.split(arguments);
this.nonNullBoolean = nonNullBoolean;
}
@Override
public String next() throws ParameterException {
try {
return arguments[index++];
} catch (ArrayIndexOutOfBoundsException e) {
throw new MissingParameterException();
}
}
@Override
public Integer nextInt() throws ParameterException {
try {
return Integer.parseInt(next());
} catch (NumberFormatException e) {
throw new ParameterException(
"Expected a number, got '" + context.getString(index - 1) + "'");
}
}
@Override
public Double nextDouble() throws ParameterException {
try {
return Double.parseDouble(next());
} catch (NumberFormatException e) {
throw new ParameterException(
"Expected a number, got '" + context.getString(index - 1) + "'");
}
}
@Override
public Boolean nextBoolean() throws ParameterException {
try {
return next().equalsIgnoreCase("true");
} catch (IndexOutOfBoundsException e) {
if (nonNullBoolean) { // Special case
return false;
}
throw new MissingParameterException();
}
}
@Override
public String remaining() throws ParameterException {
try {
String value = StringUtil.joinString(arguments, " ", index);
markConsumed();
return value;
} catch (IndexOutOfBoundsException e) {
throw new MissingParameterException();
}
}
@Override
public void markConsumed() {
index = arguments.length;
}
@Override
public CommandContext getContext() {
return context;
}
}

View File

@ -30,8 +30,6 @@ import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.MultiUserPlatform;
import com.sk89q.worldedit.extension.platform.Preference;
import com.sk89q.worldedit.sponge.config.SpongeConfiguration;
import com.sk89q.worldedit.util.command.CommandMapping;
import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.registry.Registries;
import org.enginehub.piston.Command;
@ -44,6 +42,7 @@ import org.spongepowered.api.entity.EntityType;
import org.spongepowered.api.scheduler.Task;
import org.spongepowered.api.world.Location;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumMap;
@ -51,8 +50,6 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nullable;
import static java.util.stream.Collectors.toList;
class SpongePlatform extends AbstractPlatform implements MultiUserPlatform {