First attempt at integrating Piston as the only command system

This commit is contained in:
Kenzie Togami 2019-04-15 01:21:15 -07:00
parent da35b3c174
commit 267ccf2298
No known key found for this signature in database
GPG Key ID: 5D200B325E157A81
28 changed files with 493 additions and 389 deletions

View File

@ -101,6 +101,8 @@ subprojects {
mavenCentral() mavenCentral()
maven { url "http://maven.sk89q.com/repo/" } maven { url "http://maven.sk89q.com/repo/" }
maven { url "http://repo.maven.apache.org/maven2" } maven { url "http://repo.maven.apache.org/maven2" }
// temporary, for Piston
mavenLocal()
} }
if (JavaVersion.current().isJava8Compatible()) { if (JavaVersion.current().isJava8Compatible()) {

View File

@ -19,26 +19,29 @@
package com.sk89q.worldedit.bukkit; package com.sk89q.worldedit.bukkit;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Key;
import com.sk89q.bukkit.util.CommandInspector; import com.sk89q.bukkit.util.CommandInspector;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.util.command.CommandMapping;
import com.sk89q.worldedit.util.command.Description;
import com.sk89q.worldedit.util.command.Dispatcher;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.enginehub.piston.CommandManager;
import org.enginehub.piston.CommandParameters;
import org.enginehub.piston.NoInputCommandParameters;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Optional;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
class BukkitCommandInspector implements CommandInspector { class BukkitCommandInspector implements CommandInspector {
private static final Logger logger = LoggerFactory.getLogger(BukkitCommandInspector.class); private static final Logger logger = LoggerFactory.getLogger(BukkitCommandInspector.class);
private final WorldEditPlugin plugin; private final WorldEditPlugin plugin;
private final Dispatcher dispatcher; private final CommandManager dispatcher;
BukkitCommandInspector(WorldEditPlugin plugin, Dispatcher dispatcher) { BukkitCommandInspector(WorldEditPlugin plugin, CommandManager dispatcher) {
checkNotNull(plugin); checkNotNull(plugin);
checkNotNull(dispatcher); checkNotNull(dispatcher);
this.plugin = plugin; this.plugin = plugin;
@ -47,9 +50,9 @@ class BukkitCommandInspector implements CommandInspector {
@Override @Override
public String getShortText(Command command) { public String getShortText(Command command) {
CommandMapping mapping = dispatcher.get(command.getName()); Optional<org.enginehub.piston.Command> mapping = dispatcher.getCommand(command.getName());
if (mapping != null) { if (mapping.isPresent()) {
return mapping.getDescription().getDescription(); return mapping.get().getDescription();
} else { } else {
logger.warn("BukkitCommandInspector doesn't know how about the command '" + command + "'"); logger.warn("BukkitCommandInspector doesn't know how about the command '" + command + "'");
return "Help text not available"; return "Help text not available";
@ -58,10 +61,9 @@ class BukkitCommandInspector implements CommandInspector {
@Override @Override
public String getFullText(Command command) { public String getFullText(Command command) {
CommandMapping mapping = dispatcher.get(command.getName()); Optional<org.enginehub.piston.Command> mapping = dispatcher.getCommand(command.getName());
if (mapping != null) { if (mapping.isPresent()) {
Description description = mapping.getDescription(); return mapping.get().getFullHelp();
return "Usage: " + description.getUsage() + (description.getHelp() != null ? "\n" + description.getHelp() : "");
} else { } else {
logger.warn("BukkitCommandInspector doesn't know how about the command '" + command + "'"); logger.warn("BukkitCommandInspector doesn't know how about the command '" + command + "'");
return "Help text not available"; return "Help text not available";
@ -70,11 +72,14 @@ class BukkitCommandInspector implements CommandInspector {
@Override @Override
public boolean testPermission(CommandSender sender, Command command) { public boolean testPermission(CommandSender sender, Command command) {
CommandMapping mapping = dispatcher.get(command.getName()); Optional<org.enginehub.piston.Command> mapping = dispatcher.getCommand(command.getName());
if (mapping != null) { if (mapping.isPresent()) {
CommandLocals locals = new CommandLocals(); CommandParameters parameters = NoInputCommandParameters.builder()
locals.put(Actor.class, plugin.wrapCommandSender(sender)); .injectedValues(ImmutableMap.of(
return mapping.getCallable().testPermission(locals); Key.get(Actor.class), plugin.wrapCommandSender(sender)
))
.build();
return mapping.get().getCondition().satisfied(parameters);
} else { } else {
logger.warn("BukkitCommandInspector doesn't know how about the command '" + command + "'"); logger.warn("BukkitCommandInspector doesn't know how about the command '" + command + "'");
return false; return false;

View File

@ -22,27 +22,28 @@ package com.sk89q.worldedit.bukkit;
import com.sk89q.bukkit.util.CommandInfo; import com.sk89q.bukkit.util.CommandInfo;
import com.sk89q.bukkit.util.CommandRegistration; import com.sk89q.bukkit.util.CommandRegistration;
import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.command.util.PermissionCondition;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.MultiUserPlatform; import com.sk89q.worldedit.extension.platform.MultiUserPlatform;
import com.sk89q.worldedit.extension.platform.Preference; import com.sk89q.worldedit.extension.platform.Preference;
import com.sk89q.worldedit.util.command.CommandMapping; import com.sk89q.worldedit.util.command.CommandMapping;
import com.sk89q.worldedit.util.command.Description;
import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.world.registry.Registries; import com.sk89q.worldedit.world.registry.Registries;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.enginehub.piston.CommandManager;
import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nullable; import java.util.stream.Stream;
public class BukkitServerInterface implements MultiUserPlatform { public class BukkitServerInterface implements MultiUserPlatform {
public Server server; public Server server;
@ -116,20 +117,25 @@ public class BukkitServerInterface implements MultiUserPlatform {
} }
@Override @Override
public void registerCommands(Dispatcher dispatcher) { public void registerCommands(CommandManager dispatcher) {
List<CommandInfo> toRegister = new ArrayList<>();
BukkitCommandInspector inspector = new BukkitCommandInspector(plugin, dispatcher); BukkitCommandInspector inspector = new BukkitCommandInspector(plugin, dispatcher);
for (CommandMapping command : dispatcher.getCommands()) {
Description description = command.getDescription();
List<String> permissions = description.getPermissions();
String[] permissionsArray = new String[permissions.size()];
permissions.toArray(permissionsArray);
toRegister.add(new CommandInfo(description.getUsage(), description.getDescription(), command.getAllAliases(), inspector, permissionsArray)); dynamicCommands.register(dispatcher.getAllCommands()
} .map(command -> {
String[] permissionsArray = command.getCondition()
.as(PermissionCondition.class)
.map(PermissionCondition::getPermissions)
.map(s -> s.toArray(new String[0]))
.orElseGet(() -> new String[0]);
dynamicCommands.register(toRegister); String[] aliases = Stream.concat(
Stream.of(command.getName()),
command.getAliases().stream()
).toArray(String[]::new);
return new CommandInfo(command.getUsage(),
command.getDescription(), aliases,
inspector, permissionsArray);
}).collect(Collectors.toList()));
} }
@Override @Override

View File

@ -21,13 +21,13 @@
package com.sk89q.worldedit.bukkit; package com.sk89q.worldedit.bukkit;
import com.sk89q.minecraft.util.commands.CommandLocals; import com.google.common.collect.ImmutableMap;
import com.google.inject.Key;
import com.sk89q.util.StringUtil; import com.sk89q.util.StringUtil;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.command.CommandMapping;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.event.Event.Result; import org.bukkit.event.Event.Result;
@ -40,9 +40,9 @@ import org.bukkit.event.player.PlayerCommandSendEvent;
import org.bukkit.event.player.PlayerGameModeChangeEvent; import org.bukkit.event.player.PlayerGameModeChangeEvent;
import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.EquipmentSlot;
import org.enginehub.piston.CommandManager;
import java.util.Set; import org.enginehub.piston.CommandParameters;
import java.util.stream.Collectors; import org.enginehub.piston.NoInputCommandParameters;
/** /**
* Handles all events thrown in relation to a Player * Handles all events thrown in relation to a Player
@ -87,7 +87,7 @@ public class WorldEditListener implements Listener {
if (split.length > 0) { if (split.length > 0) {
split[0] = split[0].substring(1); split[0] = split[0].substring(1);
split = plugin.getWorldEdit().getPlatformManager().getCommandManager().commandDetection(split); split = plugin.getWorldEdit().getPlatformManager().getPlatformCommandMananger().commandDetection(split);
} }
final String newMessage = "/" + StringUtil.joinString(split, " "); final String newMessage = "/" + StringUtil.joinString(split, " ");
@ -108,13 +108,18 @@ public class WorldEditListener implements Listener {
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerCommand(PlayerCommandSendEvent event) { public void onPlayerCommand(PlayerCommandSendEvent event) {
CommandLocals locals = new CommandLocals(); CommandParameters parameters = NoInputCommandParameters.builder()
locals.put(Actor.class, plugin.wrapCommandSender(event.getPlayer())); .injectedValues(ImmutableMap.of(
Set<String> toRemove = plugin.getWorldEdit().getPlatformManager().getCommandManager().getDispatcher().getCommands().stream() Key.get(Actor.class), plugin.wrapCommandSender(event.getPlayer())
.filter(commandMapping -> !commandMapping.getCallable().testPermission(locals)) ))
.map(CommandMapping::getPrimaryAlias) .build();
.collect(Collectors.toSet()); CommandManager commandManager = plugin.getWorldEdit().getPlatformManager().getPlatformCommandMananger().getCommandManager();
event.getCommands().removeIf(toRemove::contains); event.getCommands().removeIf(name ->
// remove if in the manager and not satisfied
commandManager.getCommand(name)
.filter(command -> !command.getCondition().satisfied(parameters))
.isPresent()
);
} }
/** /**

View File

@ -2,6 +2,7 @@ plugins {
id("net.ltgt.apt") version "0.21" id("net.ltgt.apt") version "0.21"
} }
apply plugin: 'java-library'
apply plugin: 'eclipse' apply plugin: 'eclipse'
apply plugin: 'idea' apply plugin: 'idea'
apply plugin: 'net.ltgt.apt-eclipse' apply plugin: 'net.ltgt.apt-eclipse'
@ -13,11 +14,6 @@ configurations.all { Configuration it ->
} }
} }
repositories {
// temporary, for Piston
mavenLocal()
}
dependencies { dependencies {
compile 'de.schlichtherle:truezip:6.8.3' compile 'de.schlichtherle:truezip:6.8.3'
compile 'rhino:js:1.7R2' compile 'rhino:js:1.7R2'
@ -32,10 +28,11 @@ dependencies {
compile 'org.slf4j:slf4j-api:1.7.26' compile 'org.slf4j:slf4j-api:1.7.26'
def pistonVersion = '0.0.1-SNAPSHOT' def pistonVersion = '0.0.1-SNAPSHOT'
api "org.enginehub.piston:core:$pistonVersion"
compileOnly "org.enginehub.piston.core-ap:annotations:$pistonVersion" compileOnly "org.enginehub.piston.core-ap:annotations:$pistonVersion"
compile "org.enginehub.piston.core-ap:runtime:$pistonVersion" implementation "org.enginehub.piston.core-ap:runtime:$pistonVersion"
annotationProcessor "org.enginehub.piston.core-ap:processor:$pistonVersion" annotationProcessor "org.enginehub.piston.core-ap:processor:$pistonVersion"
compile "org.enginehub.piston:default-impl:$pistonVersion" api "org.enginehub.piston:default-impl:$pistonVersion"
//compile 'net.sf.trove4j:trove4j:3.0.3' //compile 'net.sf.trove4j:trove4j:3.0.3'
testCompile 'org.mockito:mockito-core:1.9.0-rc1' testCompile 'org.mockito:mockito-core:1.9.0-rc1'
} }

View File

@ -39,7 +39,7 @@ import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.CommandManager; import com.sk89q.worldedit.extension.platform.PlatformCommandMananger;
import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.BlockPattern;
@ -67,6 +67,7 @@ import com.sk89q.worldedit.util.formatting.component.CommandUsageBox;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypes;
import org.enginehub.piston.CommandManager;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -598,7 +599,10 @@ public class UtilityCommands {
} }
public static void help(CommandContext args, WorldEdit we, Actor actor) { public static void help(CommandContext args, WorldEdit we, Actor actor) {
CommandCallable callable = we.getPlatformManager().getCommandManager().getDispatcher(); CommandManager manager = we.getPlatformManager().getPlatformCommandMananger().getCommandManager();
// TODO this will be implemented as a special utility in the manager
/*
int page = 0; int page = 0;
final int perPage = actor instanceof Player ? 8 : 20; // More pages for console final int perPage = actor instanceof Player ? 8 : 20; // More pages for console
@ -626,15 +630,15 @@ public class UtilityCommands {
for (int i = 0; i < effectiveLength; i++) { for (int i = 0; i < effectiveLength; i++) {
String command = args.getString(i); String command = args.getString(i);
if (callable instanceof Dispatcher) { if (manager instanceof Dispatcher) {
// Chop off the beginning / if we're are the root level // Chop off the beginning / if we're are the root level
if (isRootLevel && command.length() > 1 && command.charAt(0) == '/') { if (isRootLevel && command.length() > 1 && command.charAt(0) == '/') {
command = command.substring(1); command = command.substring(1);
} }
CommandMapping mapping = detectCommand((Dispatcher) callable, command, isRootLevel); CommandMapping mapping = detectCommand((Dispatcher) manager, command, isRootLevel);
if (mapping != null) { if (mapping != null) {
callable = mapping.getCallable(); manager = mapping.getCallable();
} else { } else {
if (isRootLevel) { if (isRootLevel) {
actor.printError(String.format("The command '%s' could not be found.", args.getString(i))); actor.printError(String.format("The command '%s' could not be found.", args.getString(i)));
@ -656,12 +660,12 @@ public class UtilityCommands {
} }
// Create the message // Create the message
if (callable instanceof Dispatcher) { if (manager instanceof Dispatcher) {
Dispatcher dispatcher = (Dispatcher) callable; Dispatcher dispatcher = (Dispatcher) manager;
// Get a list of aliases // Get a list of aliases
List<CommandMapping> aliases = new ArrayList<>(dispatcher.getCommands()); List<CommandMapping> aliases = new ArrayList<>(dispatcher.getCommands());
aliases.sort(new PrimaryAliasComparator(CommandManager.COMMAND_CLEAN_PATTERN)); aliases.sort(new PrimaryAliasComparator(PlatformCommandMananger.COMMAND_CLEAN_PATTERN));
// Calculate pagination // Calculate pagination
int offset = perPage * page; int offset = perPage * page;
@ -698,9 +702,10 @@ public class UtilityCommands {
actor.printRaw(ColorCodeBuilder.asColorCodes(box)); actor.printRaw(ColorCodeBuilder.asColorCodes(box));
} else { } else {
CommandUsageBox box = new CommandUsageBox(callable, Joiner.on(" ").join(visited)); CommandUsageBox box = new CommandUsageBox(manager, Joiner.on(" ").join(visited));
actor.printRaw(ColorCodeBuilder.asColorCodes(box)); actor.printRaw(ColorCodeBuilder.asColorCodes(box));
} }
*/
} }
} }

View File

@ -113,7 +113,7 @@ public class WorldEditCommands {
actor.checkPermission("worldedit.report.pastebin"); actor.checkPermission("worldedit.report.pastebin");
ActorCallbackPaste.pastebin( ActorCallbackPaste.pastebin(
we.getSupervisor(), actor, result, "WorldEdit report: %s.report", we.getSupervisor(), actor, result, "WorldEdit report: %s.report",
WorldEdit.getInstance().getPlatformManager().getCommandManager().getExceptionConverter() WorldEdit.getInstance().getPlatformManager().getPlatformCommandMananger().getExceptionConverter()
); );
} }
} }

View File

@ -0,0 +1,31 @@
/*
* 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 org.enginehub.piston.InjectedValueAccess;
/**
* Key-interface for {@link InjectedValueAccess} for the String arguments.
*/
public interface Arguments {
String get();
}

View File

@ -0,0 +1,87 @@
/*
* 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.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Player;
import java.util.concurrent.locks.StampedLock;
/**
* Lazily-created {@link EditSession}.
*/
public class EditSessionHolder {
private final StampedLock lock = new StampedLock();
private final WorldEdit worldEdit;
private final Player player;
public EditSessionHolder(WorldEdit worldEdit, Player player) {
this.worldEdit = worldEdit;
this.player = player;
}
private EditSession session;
/**
* Get the session, but does not create it if it doesn't exist.
*/
public EditSession getSession() {
long stamp = lock.tryOptimisticRead();
EditSession result = session;
if (!lock.validate(stamp)) {
stamp = lock.readLock();
try {
result = session;
} finally {
lock.unlockRead(stamp);
}
}
return result;
}
public EditSession getOrCreateSession() {
// use the already-generated result if possible
EditSession result = getSession();
if (result != null) {
return result;
}
// otherwise, acquire write lock
long stamp = lock.writeLock();
try {
// check session field again -- maybe another writer hit it in between
result = session;
if (result != null) {
return result;
}
// now we can do the actual creation
LocalSession localSession = worldEdit.getSessionManager().get(player);
EditSession editSession = localSession.createEditSession(player);
editSession.enableStandardMode();
localSession.tellVersion(player);
return session = editSession;
} finally {
lock.unlockWrite(stamp);
}
}
}

View File

@ -94,7 +94,7 @@ public class SelectionCommand extends SimpleCommand<Operation> {
return operation; return operation;
} catch (IncompleteRegionException e) { } catch (IncompleteRegionException e) {
WorldEdit.getInstance().getPlatformManager().getCommandManager().getExceptionConverter().convert(e); WorldEdit.getInstance().getPlatformManager().getPlatformCommandMananger().getExceptionConverter().convert(e);
return null; return null;
} }
} else { } else {

View File

@ -77,7 +77,7 @@ public class ShapedBrushCommand extends SimpleCommand<Object> {
tool.setFill(null); tool.setFill(null);
tool.setBrush(new OperationFactoryBrush(factory, regionFactory, session), permission); tool.setBrush(new OperationFactoryBrush(factory, regionFactory, session), permission);
} catch (MaxBrushRadiusException | InvalidToolBindException e) { } catch (MaxBrushRadiusException | InvalidToolBindException e) {
WorldEdit.getInstance().getPlatformManager().getCommandManager().getExceptionConverter().convert(e); WorldEdit.getInstance().getPlatformManager().getPlatformCommandMananger().getExceptionConverter().convert(e);
} }
player.print("Set brush to " + factory); player.print("Set brush to " + factory);

View File

@ -34,15 +34,11 @@ import static com.google.common.base.Preconditions.checkNotNull;
@NonnullByDefault @NonnullByDefault
public class CommandPermissionsConditionGenerator implements CommandConditionGenerator { public class CommandPermissionsConditionGenerator implements CommandConditionGenerator {
private static final Key<Actor> ACTOR_KEY = Key.get(Actor.class);
@Override @Override
public Command.Condition generateCondition(Method commandMethod) { public Command.Condition generateCondition(Method commandMethod) {
CommandPermissions annotation = commandMethod.getAnnotation(CommandPermissions.class); CommandPermissions annotation = commandMethod.getAnnotation(CommandPermissions.class);
checkNotNull(annotation, "Annotation is missing from commandMethod"); checkNotNull(annotation, "Annotation is missing from commandMethod");
Set<String> permissions = ImmutableSet.copyOf(annotation.value()); Set<String> permissions = ImmutableSet.copyOf(annotation.value());
return p -> p.injectedValue(ACTOR_KEY) return new PermissionCondition(permissions);
.map(actor -> permissions.stream().anyMatch(actor::hasPermission))
.orElse(false);
} }
} }

View File

@ -22,9 +22,9 @@ package com.sk89q.worldedit.command.util;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.FutureCallback;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.util.command.parametric.ExceptionConverter; import com.sk89q.worldedit.util.command.parametric.ExceptionConverter;
import org.enginehub.piston.exception.CommandException;
import javax.annotation.Nullable; import javax.annotation.Nullable;

View File

@ -0,0 +1,49 @@
/*
* 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.util;
import com.google.inject.Key;
import com.sk89q.worldedit.extension.platform.Actor;
import org.enginehub.piston.Command;
import org.enginehub.piston.CommandParameters;
import java.util.Set;
public final class PermissionCondition implements Command.Condition {
private static final Key<Actor> ACTOR_KEY = Key.get(Actor.class);
private final Set<String> permissions;
PermissionCondition(Set<String> permissions) {
this.permissions = permissions;
}
public Set<String> getPermissions() {
return permissions;
}
@Override
public boolean satisfied(CommandParameters parameters) {
return parameters.injectedValue(ACTOR_KEY)
.map(actor -> permissions.stream().anyMatch(actor::hasPermission))
.orElse(false);
}
}

View File

@ -50,12 +50,12 @@ public enum Capability {
USER_COMMANDS { USER_COMMANDS {
@Override @Override
void initialize(PlatformManager platformManager, Platform platform) { void initialize(PlatformManager platformManager, Platform platform) {
platformManager.getCommandManager().register(platform); platformManager.getPlatformCommandMananger().register(platform);
} }
@Override @Override
void unload(PlatformManager platformManager, Platform platform) { void unload(PlatformManager platformManager, Platform platform) {
platformManager.getCommandManager().unregister(); platformManager.getPlatformCommandMananger().unregister();
} }
}, },

View File

@ -1,96 +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.extension.platform;
import com.google.common.base.Splitter;
import com.google.inject.Key;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.util.command.CommandCallable;
import com.sk89q.worldedit.util.command.Description;
import org.enginehub.piston.CommandManager;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
/**
* Hack to get {@link CommandManager} working under {@link CommandCallable}.
*/
public class CommandManagerCallable implements CommandCallable {
private final WorldEdit worldEdit;
private final CommandManager manager;
private final Description description;
public CommandManagerCallable(WorldEdit worldEdit, CommandManager manager, Description description) {
this.worldEdit = worldEdit;
this.manager = manager;
this.description = description;
}
@Override
public Object call(String arguments, CommandLocals locals, String[] parentCommands) throws CommandException {
manager.injectValue(Key.get(Actor.class), access -> Optional.of(locals.get(Actor.class)));
manager.injectValue(Key.get(Player.class), access -> {
Actor actor = locals.get(Actor.class);
return actor instanceof Player ? Optional.of(((Player) actor)) : Optional.empty();
});
manager.injectValue(Key.get(LocalSession.class), access ->
access.injectedValue(Key.get(Player.class))
.map(worldEdit.getSessionManager()::get)
);
manager.injectValue(Key.get(EditSession.class), access ->
access.injectedValue(Key.get(Player.class))
.map(sender -> {
LocalSession session = worldEdit.getSessionManager().get(sender);
EditSession editSession = session.createEditSession(sender);
editSession.enableStandardMode();
session.tellVersion(sender);
return editSession;
})
);
return manager.execute(Splitter.on(' ').splitToList(arguments));
}
private Player getPlayer(CommandLocals locals) {
Actor actor = locals.get(Actor.class);
return actor instanceof Player ? (Player) actor : null;
}
@Override
public Description getDescription() {
return description;
}
@Override
public boolean testPermission(CommandLocals locals) {
return true;
}
@Override
public List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException {
return Collections.emptyList();
}
}

View File

@ -24,6 +24,7 @@ import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.util.command.Dispatcher; import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.registry.Registries; import com.sk89q.worldedit.world.registry.Registries;
import org.enginehub.piston.CommandManager;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -97,11 +98,11 @@ public interface Platform {
@Nullable World matchWorld(World world); @Nullable World matchWorld(World world);
/** /**
* Register the commands contained within the given command dispatcher. * Register the commands contained within the given command manager.
* *
* @param dispatcher the dispatcher * @param commandManager the command manager
*/ */
void registerCommands(Dispatcher dispatcher); void registerCommands(CommandManager commandManager);
/** /**
* Register game hooks. * Register game hooks.

View File

@ -19,9 +19,8 @@
package com.sk89q.worldedit.extension.platform; package com.sk89q.worldedit.extension.platform;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.sk89q.minecraft.util.commands.CommandException; import com.google.inject.Key;
import com.sk89q.minecraft.util.commands.CommandLocals; import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.minecraft.util.commands.CommandPermissionsException; import com.sk89q.minecraft.util.commands.CommandPermissionsException;
import com.sk89q.minecraft.util.commands.WrappedCommandException; import com.sk89q.minecraft.util.commands.WrappedCommandException;
@ -30,51 +29,25 @@ import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.BiomeCommands; import com.sk89q.worldedit.command.BiomeCommands;
import com.sk89q.worldedit.command.BrushCommands; import com.sk89q.worldedit.command.BiomeCommandsRegistration;
import com.sk89q.worldedit.command.ChunkCommands;
import com.sk89q.worldedit.command.ClipboardCommands;
import com.sk89q.worldedit.command.GeneralCommands;
import com.sk89q.worldedit.command.GenerationCommands;
import com.sk89q.worldedit.command.HistoryCommands;
import com.sk89q.worldedit.command.NavigationCommands;
import com.sk89q.worldedit.command.RegionCommands;
import com.sk89q.worldedit.command.SchematicCommands; import com.sk89q.worldedit.command.SchematicCommands;
import com.sk89q.worldedit.command.SchematicCommandsRegistration; import com.sk89q.worldedit.command.SchematicCommandsRegistration;
import com.sk89q.worldedit.command.ScriptingCommands; import com.sk89q.worldedit.command.argument.Arguments;
import com.sk89q.worldedit.command.SelectionCommands; import com.sk89q.worldedit.command.argument.EditSessionHolder;
import com.sk89q.worldedit.command.SnapshotCommands;
import com.sk89q.worldedit.command.SnapshotUtilCommands;
import com.sk89q.worldedit.command.SuperPickaxeCommands;
import com.sk89q.worldedit.command.ToolCommands;
import com.sk89q.worldedit.command.ToolUtilCommands;
import com.sk89q.worldedit.command.UtilityCommands;
import com.sk89q.worldedit.command.WorldEditCommands;
import com.sk89q.worldedit.command.argument.ReplaceParser;
import com.sk89q.worldedit.command.argument.TreeGeneratorParser;
import com.sk89q.worldedit.command.composition.ApplyCommand;
import com.sk89q.worldedit.command.composition.DeformCommand;
import com.sk89q.worldedit.command.composition.PaintCommand;
import com.sk89q.worldedit.command.composition.SelectionCommand;
import com.sk89q.worldedit.command.composition.ShapedBrushCommand;
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
import com.sk89q.worldedit.command.util.PermissionCondition;
import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.platform.CommandEvent; import com.sk89q.worldedit.event.platform.CommandEvent;
import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.event.platform.CommandSuggestionEvent;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.factory.Deform;
import com.sk89q.worldedit.function.factory.Deform.Mode;
import com.sk89q.worldedit.internal.command.ActorAuthorizer; import com.sk89q.worldedit.internal.command.ActorAuthorizer;
import com.sk89q.worldedit.internal.command.CommandLoggingHandler;
import com.sk89q.worldedit.internal.command.UserCommandCompleter; import com.sk89q.worldedit.internal.command.UserCommandCompleter;
import com.sk89q.worldedit.internal.command.WorldEditBinding; import com.sk89q.worldedit.internal.command.WorldEditBinding;
import com.sk89q.worldedit.internal.command.WorldEditExceptionConverter; import com.sk89q.worldedit.internal.command.WorldEditExceptionConverter;
import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.session.request.Request;
import com.sk89q.worldedit.util.command.CommandCallable;
import com.sk89q.worldedit.util.command.Dispatcher; import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.util.command.InvalidUsageException; import com.sk89q.worldedit.util.command.InvalidUsageException;
import com.sk89q.worldedit.util.command.SimpleDescription;
import com.sk89q.worldedit.util.command.composition.ProvidedValue;
import com.sk89q.worldedit.util.command.fluent.CommandGraph;
import com.sk89q.worldedit.util.command.parametric.ExceptionConverter; import com.sk89q.worldedit.util.command.parametric.ExceptionConverter;
import com.sk89q.worldedit.util.command.parametric.LegacyCommandsHandler; import com.sk89q.worldedit.util.command.parametric.LegacyCommandsHandler;
import com.sk89q.worldedit.util.command.parametric.ParametricBuilder; import com.sk89q.worldedit.util.command.parametric.ParametricBuilder;
@ -84,35 +57,44 @@ import com.sk89q.worldedit.util.formatting.component.CommandUsageBox;
import com.sk89q.worldedit.util.logging.DynamicStreamHandler; import com.sk89q.worldedit.util.logging.DynamicStreamHandler;
import com.sk89q.worldedit.util.logging.LogFormat; import com.sk89q.worldedit.util.logging.LogFormat;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import org.enginehub.piston.Command;
import org.enginehub.piston.CommandManager;
import org.enginehub.piston.DefaultCommandManagerService; import org.enginehub.piston.DefaultCommandManagerService;
import org.enginehub.piston.exception.CommandException;
import org.enginehub.piston.exception.CommandExecutionException;
import org.enginehub.piston.exception.ConditionFailedException;
import org.enginehub.piston.exception.UsageException;
import org.enginehub.piston.part.SubCommandPart;
import org.enginehub.piston.util.ValueProvider;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Optional;
import java.util.logging.FileHandler; import java.util.logging.FileHandler;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.worldedit.util.command.composition.LegacyCommandAdapter.adapt;
/** /**
* Handles the registration and invocation of commands. * Handles the registration and invocation of commands.
* *
* <p>This class is primarily for internal usage.</p> * <p>This class is primarily for internal usage.</p>
*/ */
public final class CommandManager { public final class PlatformCommandMananger {
public static final Pattern COMMAND_CLEAN_PATTERN = Pattern.compile("^[/]+"); public static final Pattern COMMAND_CLEAN_PATTERN = Pattern.compile("^[/]+");
private static final Logger log = LoggerFactory.getLogger(CommandManager.class); private static final Logger log = LoggerFactory.getLogger(PlatformCommandMananger.class);
private static final java.util.logging.Logger commandLog = private static final java.util.logging.Logger commandLog =
java.util.logging.Logger.getLogger(CommandManager.class.getCanonicalName() + ".CommandLog"); java.util.logging.Logger.getLogger(PlatformCommandMananger.class.getCanonicalName() + ".CommandLog");
private static final Pattern numberFormatExceptionPattern = Pattern.compile("^For input string: \"(.*)\"$"); private static final Pattern numberFormatExceptionPattern = Pattern.compile("^For input string: \"(.*)\"$");
private final WorldEdit worldEdit; private final WorldEdit worldEdit;
private final PlatformManager platformManager; private final PlatformManager platformManager;
private final Dispatcher dispatcher; private final CommandManager commandManager;
private final DynamicStreamHandler dynamicHandler = new DynamicStreamHandler(); private final DynamicStreamHandler dynamicHandler = new DynamicStreamHandler();
private final ExceptionConverter exceptionConverter; private final ExceptionConverter exceptionConverter;
@ -121,12 +103,14 @@ public final class CommandManager {
* *
* @param worldEdit the WorldEdit instance * @param worldEdit the WorldEdit instance
*/ */
CommandManager(final WorldEdit worldEdit, PlatformManager platformManager) { PlatformCommandMananger(final WorldEdit worldEdit, PlatformManager platformManager) {
checkNotNull(worldEdit); checkNotNull(worldEdit);
checkNotNull(platformManager); checkNotNull(platformManager);
this.worldEdit = worldEdit; this.worldEdit = worldEdit;
this.platformManager = platformManager; this.platformManager = platformManager;
this.exceptionConverter = new WorldEditExceptionConverter(worldEdit); this.exceptionConverter = new WorldEditExceptionConverter(worldEdit);
this.commandManager = DefaultCommandManagerService.getInstance()
.newCommandManager();
// Register this instance for command events // Register this instance for command events
worldEdit.getEventBus().register(this); worldEdit.getEventBus().register(this);
@ -140,12 +124,41 @@ public final class CommandManager {
builder.setDefaultCompleter(new UserCommandCompleter(platformManager)); builder.setDefaultCompleter(new UserCommandCompleter(platformManager));
builder.addBinding(new WorldEditBinding(worldEdit)); builder.addBinding(new WorldEditBinding(worldEdit));
builder.addInvokeListener(new LegacyCommandsHandler()); builder.addInvokeListener(new LegacyCommandsHandler());
builder.addInvokeListener(new CommandLoggingHandler(worldEdit, commandLog));
CommandPermissionsConditionGenerator permsGenerator =
new CommandPermissionsConditionGenerator();
commandManager.register("schematic", cmd -> {
cmd.aliases(ImmutableList.of("schem", "/schematic", "/schem"));
cmd.description("Schematic commands for saving/loading areas");
cmd.action(Command.Action.NULL_ACTION);
CommandManager manager = DefaultCommandManagerService.getInstance()
.newCommandManager();
SchematicCommandsRegistration.builder()
.commandManager(manager)
.containerInstance(new SchematicCommands(worldEdit))
.commandPermissionsConditionGenerator(
permsGenerator
).build();
cmd.addPart(SubCommandPart.builder("action", "Sub-command to run.")
.withCommands(manager.getAllCommands().collect(Collectors.toList()))
.required()
.build());
});
BiomeCommandsRegistration.builder()
.commandManager(commandManager)
.containerInstance(new BiomeCommands())
.commandPermissionsConditionGenerator(permsGenerator)
.build();
// Unported commands are below. Delete once they're added to the main manager above.
/*
dispatcher = new CommandGraph() dispatcher = new CommandGraph()
.builder(builder) .builder(builder)
.commands() .commands()
.registerMethods(new BiomeCommands())
.registerMethods(new ChunkCommands(worldEdit)) .registerMethods(new ChunkCommands(worldEdit))
.registerMethods(new ClipboardCommands(worldEdit)) .registerMethods(new ClipboardCommands(worldEdit))
.registerMethods(new GeneralCommands(worldEdit)) .registerMethods(new GeneralCommands(worldEdit))
@ -164,7 +177,6 @@ public final class CommandManager {
.describeAs("WorldEdit commands") .describeAs("WorldEdit commands")
.registerMethods(new WorldEditCommands(worldEdit)) .registerMethods(new WorldEditCommands(worldEdit))
.parent() .parent()
.register(schematicCommands(),"schematic", "schem", "/schematic", "/schem")
.group("snapshot", "snap") .group("snapshot", "snap")
.describeAs("Schematic commands for saving/loading areas") .describeAs("Schematic commands for saving/loading areas")
.registerMethods(new SnapshotCommands(worldEdit)) .registerMethods(new SnapshotCommands(worldEdit))
@ -190,22 +202,7 @@ public final class CommandManager {
.parent() .parent()
.graph() .graph()
.getDispatcher(); .getDispatcher();
} */
private CommandCallable schematicCommands() {
SimpleDescription desc = new SimpleDescription();
desc.setDescription("Schematic commands for saving/loading areas");
desc.setPermissions(ImmutableList.of());
org.enginehub.piston.CommandManager manager = DefaultCommandManagerService.getInstance()
.newCommandManager();
SchematicCommandsRegistration.builder()
.commandManager(manager)
.containerInstance(new SchematicCommands(worldEdit))
.commandPermissionsConditionGenerator(
new CommandPermissionsConditionGenerator()
).build();
return new CommandManagerCallable(worldEdit, manager, desc);
} }
public ExceptionConverter getExceptionConverter() { public ExceptionConverter getExceptionConverter() {
@ -238,7 +235,7 @@ public final class CommandManager {
dynamicHandler.setFormatter(new LogFormat(config.logFormat)); dynamicHandler.setFormatter(new LogFormat(config.logFormat));
} }
platform.registerCommands(dispatcher); platform.registerCommands(commandManager);
} }
void unregister() { void unregister() {
@ -258,10 +255,10 @@ public final class CommandManager {
String searchCmd = split[0].toLowerCase(); String searchCmd = split[0].toLowerCase();
// Try to detect the command // Try to detect the command
if (!dispatcher.contains(searchCmd)) { if (!commandManager.containsCommand(searchCmd)) {
if (worldEdit.getConfiguration().noDoubleSlash && dispatcher.contains("/" + searchCmd)) { if (worldEdit.getConfiguration().noDoubleSlash && commandManager.containsCommand("/" + searchCmd)) {
split[0] = "/" + split[0]; split[0] = "/" + split[0];
} else if (searchCmd.length() >= 2 && searchCmd.charAt(0) == '/' && dispatcher.contains(searchCmd.substring(1))) { } else if (searchCmd.length() >= 2 && searchCmd.charAt(0) == '/' && commandManager.containsCommand(searchCmd.substring(1))) {
split[0] = split[0].substring(1); split[0] = split[0].substring(1);
} }
} }
@ -277,7 +274,7 @@ public final class CommandManager {
String[] split = commandDetection(event.getArguments().split(" ")); String[] split = commandDetection(event.getArguments().split(" "));
// No command found! // No command found!
if (!dispatcher.contains(split[0])) { if (!commandManager.containsCommand(split[0])) {
return; return;
} }
@ -291,9 +288,13 @@ public final class CommandManager {
} }
LocalConfiguration config = worldEdit.getConfiguration(); LocalConfiguration config = worldEdit.getConfiguration();
CommandLocals locals = new CommandLocals(); commandManager.injectValue(Key.get(Actor.class), ValueProvider.constant(actor));
locals.put(Actor.class, actor); commandManager.injectValue(Key.get(Arguments.class), ValueProvider.constant(event::getArguments));
locals.put("arguments", event.getArguments()); commandManager.injectValue(Key.get(EditSessionHolder.class),
context -> context.injectedValue(Key.get(Actor.class))
.filter(Player.class::isInstance)
.map(Player.class::cast)
.map(p -> new EditSessionHolder(worldEdit, p)));
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
@ -303,7 +304,7 @@ public final class CommandManager {
// exceptions without writing a hook into every dispatcher, we need to unwrap these // exceptions without writing a hook into every dispatcher, we need to unwrap these
// exceptions and rethrow their converted form, if their is one. // exceptions and rethrow their converted form, if their is one.
try { try {
dispatcher.call(Joiner.on(" ").join(split), locals, new String[0]); commandManager.execute(ImmutableList.copyOf(split));
} catch (Throwable t) { } catch (Throwable t) {
// Use the exception converter to convert the exception if any of its causes // Use the exception converter to convert the exception if any of its causes
// can be converted, otherwise throw the original exception // can be converted, otherwise throw the original exception
@ -315,21 +316,14 @@ public final class CommandManager {
throw t; throw t;
} }
} catch (CommandPermissionsException e) { } catch (ConditionFailedException e) {
actor.printError("You are not permitted to do that. Are you in the right mode?"); if (e.getCondition() instanceof PermissionCondition) {
} catch (InvalidUsageException e) { actor.printError("You are not permitted to do that. Are you in the right mode?");
if (e.isFullHelpSuggested()) {
actor.printRaw(ColorCodeBuilder.asColorCodes(new CommandUsageBox(e.getCommand(), e.getCommandUsed("/", ""), locals)));
String message = e.getMessage();
if (message != null) {
actor.printError(message);
}
} else {
String message = e.getMessage();
actor.printError(message != null ? message : "The command was not used properly (no more help available).");
actor.printError("Usage: " + e.getSimpleUsageString("/"));
} }
} catch (WrappedCommandException e) { } catch (UsageException e) {
String message = e.getMessage();
actor.printError(message != null ? message : "The command was not used properly (no more help available).");
} catch (CommandExecutionException e) {
Throwable t = e.getCause(); Throwable t = e.getCause();
actor.printError("Please report this error: [See console]"); actor.printError("Please report this error: [See console]");
actor.printRaw(t.getClass().getName() + ": " + t.getMessage()); actor.printRaw(t.getClass().getName() + ": " + t.getMessage());
@ -343,9 +337,11 @@ public final class CommandManager {
log.error("An unknown error occurred", e); log.error("An unknown error occurred", e);
} }
} finally { } finally {
EditSession editSession = locals.get(EditSession.class); Optional<EditSession> editSessionOpt = commandManager.injectedValue(Key.get(EditSessionHolder.class))
.map(EditSessionHolder::getSession);
if (editSession != null) { if (editSessionOpt.isPresent()) {
EditSession editSession = editSessionOpt.get();
session.remember(editSession); session.remember(editSession);
editSession.flushSession(); editSession.flushSession();
@ -373,22 +369,21 @@ public final class CommandManager {
@Subscribe @Subscribe
public void handleCommandSuggestion(CommandSuggestionEvent event) { public void handleCommandSuggestion(CommandSuggestionEvent event) {
try { try {
CommandLocals locals = new CommandLocals(); commandManager.injectValue(Key.get(Actor.class), ValueProvider.constant(event.getActor()));
locals.put(Actor.class, event.getActor()); commandManager.injectValue(Key.get(Arguments.class), ValueProvider.constant(event::getArguments));
locals.put("arguments", event.getArguments()); // TODO suggestions
event.setSuggestions(dispatcher.getSuggestions(event.getArguments(), locals));
} catch (CommandException e) { } catch (CommandException e) {
event.getActor().printError(e.getMessage()); event.getActor().printError(e.getMessage());
} }
} }
/** /**
* Get the command dispatcher instance. * Get the command manager instance.
* *
* @return the command dispatcher * @return the command manager
*/ */
public Dispatcher getDispatcher() { public CommandManager getCommandManager() {
return dispatcher; return commandManager;
} }
public static java.util.logging.Logger getLogger() { public static java.util.logging.Logger getLogger() {

View File

@ -68,7 +68,7 @@ public class PlatformManager {
private static final Logger logger = LoggerFactory.getLogger(PlatformManager.class); private static final Logger logger = LoggerFactory.getLogger(PlatformManager.class);
private final WorldEdit worldEdit; private final WorldEdit worldEdit;
private final CommandManager commandManager; private final PlatformCommandMananger platformCommandMananger;
private final List<Platform> platforms = new ArrayList<>(); private final List<Platform> platforms = new ArrayList<>();
private final Map<Capability, Platform> preferences = new EnumMap<>(Capability.class); private final Map<Capability, Platform> preferences = new EnumMap<>(Capability.class);
private @Nullable String firstSeenVersion; private @Nullable String firstSeenVersion;
@ -83,7 +83,7 @@ public class PlatformManager {
public PlatformManager(WorldEdit worldEdit) { public PlatformManager(WorldEdit worldEdit) {
checkNotNull(worldEdit); checkNotNull(worldEdit);
this.worldEdit = worldEdit; this.worldEdit = worldEdit;
this.commandManager = new CommandManager(worldEdit, this); this.platformCommandMananger = new PlatformCommandMananger(worldEdit, this);
// Register this instance for events // Register this instance for events
worldEdit.getEventBus().register(this); worldEdit.getEventBus().register(this);
@ -277,8 +277,8 @@ public class PlatformManager {
* *
* @return the command manager * @return the command manager
*/ */
public CommandManager getCommandManager() { public PlatformCommandMananger getPlatformCommandMananger() {
return commandManager; return platformCommandMananger;
} }
/** /**

View File

@ -19,8 +19,7 @@
package com.sk89q.worldedit.internal.command; package com.sk89q.worldedit.internal.command;
import com.sk89q.minecraft.util.commands.CommandContext; import com.google.inject.Key;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
@ -28,22 +27,22 @@ import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.util.command.parametric.AbstractInvokeListener; import org.enginehub.piston.CommandParameters;
import com.sk89q.worldedit.util.command.parametric.InvokeHandler; import org.enginehub.piston.gen.CommandCallListener;
import com.sk89q.worldedit.util.command.parametric.ParameterData;
import com.sk89q.worldedit.util.command.parametric.ParameterException;
import java.io.Closeable;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Optional;
import java.util.logging.Handler; import java.util.logging.Handler;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* Logs called commands to a logger. * Logs called commands to a logger.
*/ */
public class CommandLoggingHandler extends AbstractInvokeListener implements InvokeHandler, Closeable { public class CommandLoggingHandler implements CommandCallListener, AutoCloseable {
private final WorldEdit worldEdit; private final WorldEdit worldEdit;
private final Logger logger; private final Logger logger;
@ -62,93 +61,77 @@ public class CommandLoggingHandler extends AbstractInvokeListener implements Inv
} }
@Override @Override
public void preProcess(Object object, Method method, ParameterData[] parameters, CommandContext context) throws CommandException, ParameterException { public void beforeCall(Method method, CommandParameters parameters) {
}
@Override
public void preInvoke(Object object, Method method, ParameterData[] parameters, Object[] args, CommandContext context) throws CommandException {
Logging loggingAnnotation = method.getAnnotation(Logging.class); Logging loggingAnnotation = method.getAnnotation(Logging.class);
Logging.LogMode logMode; Logging.LogMode logMode;
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
if (loggingAnnotation == null) { if (loggingAnnotation == null) {
logMode = null; logMode = null;
} else { } else {
logMode = loggingAnnotation.value(); logMode = loggingAnnotation.value();
} }
Actor sender = context.getLocals().get(Actor.class); Optional<Player> playerOpt = parameters.injectedValue(Key.get(Actor.class))
Player player; .filter(Player.class::isInstance)
.map(Player.class::cast);
if (sender == null) { if (!playerOpt.isPresent()) {
return; return;
} }
if (sender instanceof Player) { Player player = playerOpt.get();
player = (Player) sender;
} else {
return;
}
builder.append("WorldEdit: ").append(sender.getName()); builder.append("WorldEdit: ").append(player.getName());
if (sender.isPlayer()) { builder.append(" (in \"").append(player.getWorld().getName()).append("\")");
builder.append(" (in \"").append(player.getWorld().getName()).append("\")");
}
builder.append(": ").append(context.getCommand()); builder.append(": ").append(parameters.getMetadata().getCalledName());
if (context.argsLength() > 0) { builder.append(": ")
builder.append(" ").append(context.getJoinedStrings(0)); .append(Stream.concat(
} Stream.of(parameters.getMetadata().getCalledName()),
parameters.getMetadata().getArguments().stream()
if (logMode != null && sender.isPlayer()) { ).collect(Collectors.joining(" ")));
if (logMode != null) {
Vector3 position = player.getLocation().toVector(); Vector3 position = player.getLocation().toVector();
LocalSession session = worldEdit.getSessionManager().get(player); LocalSession session = worldEdit.getSessionManager().get(player);
switch (logMode) { switch (logMode) {
case PLACEMENT: case PLACEMENT:
try { try {
position = session.getPlacementPosition(player).toVector3(); position = session.getPlacementPosition(player).toVector3();
} catch (IncompleteRegionException e) { } catch (IncompleteRegionException e) {
break;
}
/* FALL-THROUGH */
case POSITION:
builder.append(" - Position: ").append(position);
break; break;
}
/* FALL-THROUGH */
case POSITION: case ALL:
builder.append(" - Position: ").append(position); builder.append(" - Position: ").append(position);
break; /* FALL-THROUGH */
case ALL: case ORIENTATION_REGION:
builder.append(" - Position: ").append(position); builder.append(" - Orientation: ").append(player.getCardinalDirection().name());
/* FALL-THROUGH */ /* FALL-THROUGH */
case ORIENTATION_REGION: case REGION:
builder.append(" - Orientation: ").append(player.getCardinalDirection().name()); try {
/* FALL-THROUGH */ builder.append(" - Region: ")
case REGION:
try {
builder.append(" - Region: ")
.append(session.getSelection(player.getWorld())); .append(session.getSelection(player.getWorld()));
} catch (IncompleteRegionException e) { } catch (IncompleteRegionException e) {
break;
}
break; break;
}
break;
} }
} }
logger.info(builder.toString()); logger.info(builder.toString());
} }
@Override
public void postInvoke(Object object, Method method, ParameterData[] parameters, Object[] args, CommandContext context) throws CommandException {
}
@Override
public InvokeHandler createInvokeHandler() {
return this;
}
@Override @Override
public void close() { public void close() {
for (Handler h : logger.getHandlers()) { for (Handler h : logger.getHandlers()) {

View File

@ -21,7 +21,6 @@ package com.sk89q.worldedit.internal.command;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldedit.DisallowedItemException; import com.sk89q.worldedit.DisallowedItemException;
import com.sk89q.worldedit.EmptyClipboardException; import com.sk89q.worldedit.EmptyClipboardException;
import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.IncompleteRegionException;
@ -35,6 +34,7 @@ import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.command.InsufficientArgumentsException; import com.sk89q.worldedit.command.InsufficientArgumentsException;
import com.sk89q.worldedit.command.tool.InvalidToolBindException; import com.sk89q.worldedit.command.tool.InvalidToolBindException;
import com.sk89q.worldedit.command.util.PermissionCondition;
import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.regions.RegionOperationException; import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.util.command.parametric.ExceptionConverterHelper; import com.sk89q.worldedit.util.command.parametric.ExceptionConverterHelper;
@ -42,6 +42,8 @@ import com.sk89q.worldedit.util.command.parametric.ExceptionMatch;
import com.sk89q.worldedit.util.io.file.FileSelectionAbortedException; import com.sk89q.worldedit.util.io.file.FileSelectionAbortedException;
import com.sk89q.worldedit.util.io.file.FilenameResolutionException; import com.sk89q.worldedit.util.io.file.FilenameResolutionException;
import com.sk89q.worldedit.util.io.file.InvalidFilenameException; import com.sk89q.worldedit.util.io.file.InvalidFilenameException;
import org.enginehub.piston.exception.CommandException;
import org.enginehub.piston.exception.ConditionFailedException;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -65,99 +67,106 @@ public class WorldEditExceptionConverter extends ExceptionConverterHelper {
if (matcher.matches()) { if (matcher.matches()) {
throw new CommandException("Number expected; string \"" + matcher.group(1) throw new CommandException("Number expected; string \"" + matcher.group(1)
+ "\" given."); + "\" given.", e, null);
} else { } else {
throw new CommandException("Number expected; string given."); throw new CommandException("Number expected; string given.", e, null);
} }
} }
@ExceptionMatch @ExceptionMatch
public void convert(IncompleteRegionException e) throws CommandException { public void convert(IncompleteRegionException e) throws CommandException {
throw new CommandException("Make a region selection first."); throw new CommandException("Make a region selection first.", e, null);
} }
@ExceptionMatch @ExceptionMatch
public void convert(UnknownItemException e) throws CommandException { public void convert(UnknownItemException e) throws CommandException {
throw new CommandException("Block name '" + e.getID() + "' was not recognized."); throw new CommandException("Block name '" + e.getID() + "' was not recognized.", e, null);
} }
@ExceptionMatch @ExceptionMatch
public void convert(InvalidItemException e) throws CommandException { public void convert(InvalidItemException e) throws CommandException {
throw new CommandException(e.getMessage()); throw new CommandException(e.getMessage(), e, null);
} }
@ExceptionMatch @ExceptionMatch
public void convert(DisallowedItemException e) throws CommandException { public void convert(DisallowedItemException e) throws CommandException {
throw new CommandException("Block '" + e.getID() throw new CommandException("Block '" + e.getID()
+ "' not allowed (see WorldEdit configuration)."); + "' not allowed (see WorldEdit configuration).", e, null);
} }
@ExceptionMatch @ExceptionMatch
public void convert(MaxChangedBlocksException e) throws CommandException { public void convert(MaxChangedBlocksException e) throws CommandException {
throw new CommandException("Max blocks changed in an operation reached (" throw new CommandException("Max blocks changed in an operation reached ("
+ e.getBlockLimit() + ")."); + e.getBlockLimit() + ").", e, null);
} }
@ExceptionMatch @ExceptionMatch
public void convert(MaxBrushRadiusException e) throws CommandException { public void convert(MaxBrushRadiusException e) throws CommandException {
throw new CommandException("Maximum brush radius (in configuration): " + worldEdit.getConfiguration().maxBrushRadius); throw new CommandException("Maximum brush radius (in configuration): " + worldEdit.getConfiguration().maxBrushRadius, e, null);
} }
@ExceptionMatch @ExceptionMatch
public void convert(MaxRadiusException e) throws CommandException { public void convert(MaxRadiusException e) throws CommandException {
throw new CommandException("Maximum radius (in configuration): " + worldEdit.getConfiguration().maxRadius); throw new CommandException("Maximum radius (in configuration): " + worldEdit.getConfiguration().maxRadius, e, null);
} }
@ExceptionMatch @ExceptionMatch
public void convert(UnknownDirectionException e) throws CommandException { public void convert(UnknownDirectionException e) throws CommandException {
throw new CommandException("Unknown direction: " + e.getDirection()); throw new CommandException("Unknown direction: " + e.getDirection(), e, null);
} }
@ExceptionMatch @ExceptionMatch
public void convert(InsufficientArgumentsException e) throws CommandException { public void convert(InsufficientArgumentsException e) throws CommandException {
throw new CommandException(e.getMessage()); throw new CommandException(e.getMessage(), e, null);
} }
@ExceptionMatch @ExceptionMatch
public void convert(RegionOperationException e) throws CommandException { public void convert(RegionOperationException e) throws CommandException {
throw new CommandException(e.getMessage()); throw new CommandException(e.getMessage(), e, null);
} }
@ExceptionMatch @ExceptionMatch
public void convert(ExpressionException e) throws CommandException { public void convert(ExpressionException e) throws CommandException {
throw new CommandException(e.getMessage()); throw new CommandException(e.getMessage(), e, null);
} }
@ExceptionMatch @ExceptionMatch
public void convert(EmptyClipboardException e) throws CommandException { public void convert(EmptyClipboardException e) throws CommandException {
throw new CommandException("Your clipboard is empty. Use //copy first."); throw new CommandException("Your clipboard is empty. Use //copy first.", e, null);
} }
@ExceptionMatch @ExceptionMatch
public void convert(InvalidFilenameException e) throws CommandException { public void convert(InvalidFilenameException e) throws CommandException {
throw new CommandException("Filename '" + e.getFilename() + "' invalid: " throw new CommandException("Filename '" + e.getFilename() + "' invalid: "
+ e.getMessage()); + e.getMessage(), e, null);
} }
@ExceptionMatch @ExceptionMatch
public void convert(FilenameResolutionException e) throws CommandException { public void convert(FilenameResolutionException e) throws CommandException {
throw new CommandException( throw new CommandException(
"File '" + e.getFilename() + "' resolution error: " + e.getMessage()); "File '" + e.getFilename() + "' resolution error: " + e.getMessage(), e, null);
} }
@ExceptionMatch @ExceptionMatch
public void convert(InvalidToolBindException e) throws CommandException { public void convert(InvalidToolBindException e) throws CommandException {
throw new CommandException("Can't bind tool to " + e.getItemType().getName() + ": " + e.getMessage()); throw new CommandException("Can't bind tool to " + e.getItemType().getName() + ": " + e.getMessage(), e, null);
} }
@ExceptionMatch @ExceptionMatch
public void convert(FileSelectionAbortedException e) throws CommandException { public void convert(FileSelectionAbortedException e) throws CommandException {
throw new CommandException("File selection aborted."); throw new CommandException("File selection aborted.", e, null);
} }
@ExceptionMatch @ExceptionMatch
public void convert(WorldEditException e) throws CommandException { public void convert(WorldEditException e) throws CommandException {
throw new CommandException(e.getMessage(), e); throw new CommandException(e.getMessage(), e, null);
}
@ExceptionMatch
public void convert(ConditionFailedException e) throws CommandException {
if (e.getCondition() instanceof PermissionCondition) {
throw new CommandException("You are not permitted to do that. Are you in the right mode?", e, null);
}
} }
} }

View File

@ -19,8 +19,9 @@
package com.sk89q.worldedit.util.command.parametric; package com.sk89q.worldedit.util.command.parametric;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.WrappedCommandException; 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
@ -29,7 +30,7 @@ import com.sk89q.minecraft.util.commands.WrappedCommandException;
* <p>Methods (when invoked by a {@link ParametricBuilder}-created command) may throw * <p>Methods (when invoked by a {@link ParametricBuilder}-created command) may throw
* relevant exceptions that are not caught by the command manager, but translate * relevant exceptions that are not caught by the command manager, but translate
* into reasonable exceptions for an application. However, unknown exceptions are * into reasonable exceptions for an application. However, unknown exceptions are
* normally simply wrapped in a {@link WrappedCommandException} and bubbled up. Only * normally simply wrapped in a {@link CommandExecutionException} and bubbled up. Only
* normal {@link CommandException}s will be printed correctly, so a converter translates * normal {@link CommandException}s will be printed correctly, so a converter translates
* one of these unknown exceptions into an appropriate {@link CommandException}.</p> * one of these unknown exceptions into an appropriate {@link CommandException}.</p>
* *

View File

@ -19,8 +19,9 @@
package com.sk89q.worldedit.util.command.parametric; package com.sk89q.worldedit.util.command.parametric;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.WrappedCommandException; import com.sk89q.minecraft.util.commands.WrappedCommandException;
import org.enginehub.piston.exception.CommandException;
import org.enginehub.piston.exception.CommandExecutionException;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -75,9 +76,9 @@ public abstract class ExceptionConverterHelper implements ExceptionConverter {
if (e.getCause() instanceof CommandException) { if (e.getCause() instanceof CommandException) {
throw (CommandException) e.getCause(); throw (CommandException) e.getCause();
} }
throw new WrappedCommandException(e); throw new CommandExecutionException(e, null);
} catch (IllegalArgumentException | IllegalAccessException e) { } catch (IllegalArgumentException | IllegalAccessException e) {
throw new WrappedCommandException(e); throw new CommandExecutionException(e, null);
} }
} }
} }

View File

@ -22,7 +22,7 @@ package com.sk89q.worldedit.util.formatting.component;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.minecraft.util.commands.CommandLocals; import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.extension.platform.CommandManager; import com.sk89q.worldedit.extension.platform.PlatformCommandMananger;
import com.sk89q.worldedit.util.command.CommandCallable; import com.sk89q.worldedit.util.command.CommandCallable;
import com.sk89q.worldedit.util.command.CommandMapping; import com.sk89q.worldedit.util.command.CommandMapping;
import com.sk89q.worldedit.util.command.Description; import com.sk89q.worldedit.util.command.Description;
@ -72,7 +72,7 @@ public class CommandUsageBox extends StyledFragment {
String prefix = !commandString.isEmpty() ? commandString + " " : ""; String prefix = !commandString.isEmpty() ? commandString + " " : "";
List<CommandMapping> list = new ArrayList<>(dispatcher.getCommands()); List<CommandMapping> list = new ArrayList<>(dispatcher.getCommands());
list.sort(new PrimaryAliasComparator(CommandManager.COMMAND_CLEAN_PATTERN)); list.sort(new PrimaryAliasComparator(PlatformCommandMananger.COMMAND_CLEAN_PATTERN));
for (CommandMapping mapping : list) { for (CommandMapping mapping : list) {
if (locals == null || mapping.getCallable().testPermission(locals)) { if (locals == null || mapping.getCallable().testPermission(locals)) {

View File

@ -19,15 +19,17 @@
package com.sk89q.worldedit.forge; package com.sk89q.worldedit.forge;
import com.google.common.collect.ImmutableList;
import com.mojang.brigadier.Command; import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.tree.LiteralCommandNode; import com.sk89q.worldedit.command.util.PermissionCondition;
import com.sk89q.worldedit.util.command.CommandMapping;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.EntityPlayerMP;
import java.util.Set;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Stream;
import static net.minecraft.command.Commands.literal; import static net.minecraft.command.Commands.literal;
@ -35,11 +37,14 @@ public final class CommandWrapper {
private CommandWrapper() { private CommandWrapper() {
} }
public static void register(CommandDispatcher<CommandSource> dispatcher, CommandMapping command) { public static void register(CommandDispatcher<CommandSource> dispatcher, org.enginehub.piston.Command command) {
for (String alias : command.getAllAliases()) { ImmutableList.Builder<String> aliases = ImmutableList.builder();
aliases.add(command.getName()).addAll(command.getAliases());
for (String alias : aliases.build()) {
LiteralArgumentBuilder<CommandSource> base = literal(alias) LiteralArgumentBuilder<CommandSource> base = literal(alias)
.executes(FAKE_COMMAND); .executes(FAKE_COMMAND);
if (command.getDescription().getPermissions().size() > 0) { if (command.getCondition().as(PermissionCondition.class)
.filter(p -> p.getPermissions().size() > 0).isPresent()) {
base.requires(requirementsFor(command)); base.requires(requirementsFor(command));
} }
dispatcher.register(base); dispatcher.register(base);
@ -54,11 +59,14 @@ public final class CommandWrapper {
return 1; return 1;
}; };
private static Predicate<CommandSource> requirementsFor(CommandMapping mapping) { private static Predicate<CommandSource> requirementsFor(org.enginehub.piston.Command mapping) {
return ctx -> { return ctx -> {
ForgePermissionsProvider permsProvider = ForgeWorldEdit.inst.getPermissionsProvider(); ForgePermissionsProvider permsProvider = ForgeWorldEdit.inst.getPermissionsProvider();
return ctx.getEntity() instanceof EntityPlayerMP && return ctx.getEntity() instanceof EntityPlayerMP &&
mapping.getDescription().getPermissions().stream() mapping.getCondition().as(PermissionCondition.class)
.map(PermissionCondition::getPermissions)
.map(Set::stream)
.orElseGet(Stream::empty)
.allMatch(perm -> permsProvider.hasPermission( .allMatch(perm -> permsProvider.hasPermission(
(EntityPlayerMP) ctx.getEntity(), perm (EntityPlayerMP) ctx.getEntity(), perm
)); ));

View File

@ -19,14 +19,13 @@
package com.sk89q.worldedit.forge; package com.sk89q.worldedit.forge;
import com.sk89q.worldedit.command.util.PermissionCondition;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.AbstractPlatform; import com.sk89q.worldedit.extension.platform.AbstractPlatform;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.MultiUserPlatform; import com.sk89q.worldedit.extension.platform.MultiUserPlatform;
import com.sk89q.worldedit.extension.platform.Preference; import com.sk89q.worldedit.extension.platform.Preference;
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.World;
import com.sk89q.worldedit.world.registry.Registries; import com.sk89q.worldedit.world.registry.Registries;
import net.minecraft.command.Commands; import net.minecraft.command.Commands;
@ -36,13 +35,19 @@ import net.minecraft.server.management.PlayerList;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.WorldServer; import net.minecraft.world.WorldServer;
import net.minecraftforge.fml.server.ServerLifecycleHooks; import net.minecraftforge.fml.server.ServerLifecycleHooks;
import org.enginehub.piston.Command;
import org.enginehub.piston.CommandManager;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import static java.util.stream.Collectors.toList;
class ForgePlatform extends AbstractPlatform implements MultiUserPlatform { class ForgePlatform extends AbstractPlatform implements MultiUserPlatform {
@ -117,16 +122,17 @@ class ForgePlatform extends AbstractPlatform implements MultiUserPlatform {
} }
@Override @Override
public void registerCommands(Dispatcher dispatcher) { public void registerCommands(CommandManager manager) {
if (server == null) return; if (server == null) return;
Commands mcMan = server.getCommandManager(); Commands mcMan = server.getCommandManager();
for (final CommandMapping command : dispatcher.getCommands()) { for (Command command : manager.getAllCommands().collect(toList())) {
CommandWrapper.register(mcMan.getDispatcher(), command); CommandWrapper.register(mcMan.getDispatcher(), command);
if (command.getDescription().getPermissions().size() > 0) { Set<String> perms = command.getCondition().as(PermissionCondition.class)
for (int i = 1; i < command.getDescription().getPermissions().size(); i++) { .map(PermissionCondition::getPermissions)
ForgeWorldEdit.inst.getPermissionsProvider().registerPermission(command.getDescription().getPermissions().get(i)); .orElseGet(Collections::emptySet);
} if (perms.size() > 0) {
perms.forEach(ForgeWorldEdit.inst.getPermissionsProvider()::registerPermission);
} }
} }
} }

View File

@ -19,23 +19,29 @@
package com.sk89q.worldedit.sponge; package com.sk89q.worldedit.sponge;
import com.sk89q.worldedit.util.command.CommandMapping; import com.sk89q.worldedit.command.util.PermissionCondition;
import org.enginehub.piston.Command;
import org.spongepowered.api.command.CommandCallable; import org.spongepowered.api.command.CommandCallable;
import org.spongepowered.api.command.CommandSource; import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.text.Text; import org.spongepowered.api.text.Text;
import java.util.Collections;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
public abstract class CommandAdapter implements CommandCallable { public abstract class CommandAdapter implements CommandCallable {
private CommandMapping command; private Command command;
protected CommandAdapter(CommandMapping command) { protected CommandAdapter(Command command) {
this.command = command; this.command = command;
} }
@Override @Override
public boolean testPermission(CommandSource source) { public boolean testPermission(CommandSource source) {
for (String perm : command.getDescription().getPermissions()) { Set<String> permissions = command.getCondition().as(PermissionCondition.class)
.map(PermissionCondition::getPermissions)
.orElseGet(Collections::emptySet);
for (String perm : permissions) {
if (!source.hasPermission(perm)) { if (!source.hasPermission(perm)) {
return false; return false;
} }
@ -45,8 +51,8 @@ public abstract class CommandAdapter implements CommandCallable {
@Override @Override
public Optional<Text> getShortDescription(CommandSource source) { public Optional<Text> getShortDescription(CommandSource source) {
String description = command.getDescription().getDescription(); String description = command.getDescription();
if (description != null && !description.isEmpty()) { if (!description.isEmpty()) {
return Optional.of(Text.of(description)); return Optional.of(Text.of(description));
} }
return Optional.empty(); return Optional.empty();
@ -54,8 +60,8 @@ public abstract class CommandAdapter implements CommandCallable {
@Override @Override
public Optional<Text> getHelp(CommandSource source) { public Optional<Text> getHelp(CommandSource source) {
String help = command.getDescription().getHelp(); String help = command.getFullHelp();
if (help != null && !help.isEmpty()) { if (!help.isEmpty()) {
return Optional.of(Text.of(help)); return Optional.of(Text.of(help));
} }
return Optional.empty(); return Optional.empty();
@ -63,6 +69,6 @@ public abstract class CommandAdapter implements CommandCallable {
@Override @Override
public Text getUsage(CommandSource source) { public Text getUsage(CommandSource source) {
return Text.of(command.getDescription().getUsage()); return Text.of(command.getUsage());
} }
} }

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.sponge; package com.sk89q.worldedit.sponge;
import com.google.common.collect.ImmutableList;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.platform.CommandEvent; import com.sk89q.worldedit.event.platform.CommandEvent;
@ -33,6 +34,8 @@ import com.sk89q.worldedit.util.command.CommandMapping;
import com.sk89q.worldedit.util.command.Dispatcher; import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.registry.Registries; import com.sk89q.worldedit.world.registry.Registries;
import org.enginehub.piston.Command;
import org.enginehub.piston.CommandManager;
import org.spongepowered.api.Sponge; import org.spongepowered.api.Sponge;
import org.spongepowered.api.command.CommandException; import org.spongepowered.api.command.CommandException;
import org.spongepowered.api.command.CommandResult; import org.spongepowered.api.command.CommandResult;
@ -50,6 +53,8 @@ import java.util.Optional;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static java.util.stream.Collectors.toList;
class SpongePlatform extends AbstractPlatform implements MultiUserPlatform { class SpongePlatform extends AbstractPlatform implements MultiUserPlatform {
private final SpongeWorldEdit mod; private final SpongeWorldEdit mod;
@ -122,24 +127,26 @@ class SpongePlatform extends AbstractPlatform implements MultiUserPlatform {
} }
@Override @Override
public void registerCommands(Dispatcher dispatcher) { public void registerCommands(CommandManager manager) {
for (CommandMapping command : dispatcher.getCommands()) { for (Command command : manager.getAllCommands().collect(toList())) {
CommandAdapter adapter = new CommandAdapter(command) { CommandAdapter adapter = new CommandAdapter(command) {
@Override @Override
public CommandResult process(CommandSource source, String arguments) throws org.spongepowered.api.command.CommandException { public CommandResult process(CommandSource source, String arguments) throws org.spongepowered.api.command.CommandException {
CommandEvent weEvent = new CommandEvent(SpongeWorldEdit.inst().wrapCommandSource(source), command.getPrimaryAlias() + " " + arguments); CommandEvent weEvent = new CommandEvent(SpongeWorldEdit.inst().wrapCommandSource(source), command.getName() + " " + arguments);
WorldEdit.getInstance().getEventBus().post(weEvent); WorldEdit.getInstance().getEventBus().post(weEvent);
return weEvent.isCancelled() ? CommandResult.success() : CommandResult.empty(); return weEvent.isCancelled() ? CommandResult.success() : CommandResult.empty();
} }
@Override @Override
public List<String> getSuggestions(CommandSource source, String arguments, @Nullable Location<org.spongepowered.api.world.World> targetPosition) throws CommandException { public List<String> getSuggestions(CommandSource source, String arguments, @Nullable Location<org.spongepowered.api.world.World> targetPosition) throws CommandException {
CommandSuggestionEvent weEvent = new CommandSuggestionEvent(SpongeWorldEdit.inst().wrapCommandSource(source), command.getPrimaryAlias() + " " + arguments); CommandSuggestionEvent weEvent = new CommandSuggestionEvent(SpongeWorldEdit.inst().wrapCommandSource(source), command.getName() + " " + arguments);
WorldEdit.getInstance().getEventBus().post(weEvent); WorldEdit.getInstance().getEventBus().post(weEvent);
return weEvent.getSuggestions(); return weEvent.getSuggestions();
} }
}; };
Sponge.getCommandManager().register(SpongeWorldEdit.inst(), adapter, command.getAllAliases()); ImmutableList.Builder<String> aliases = ImmutableList.builder();
aliases.add(command.getName()).addAll(command.getAliases());
Sponge.getCommandManager().register(SpongeWorldEdit.inst(), adapter, aliases.build());
} }
} }