Work on adding converters for some arguments

This commit is contained in:
Kenzie Togami 2019-04-18 19:11:57 -07:00
parent 37c993be16
commit ac03de89cc
No known key found for this signature in database
GPG Key ID: 5D200B325E157A81
9 changed files with 260 additions and 25 deletions

View File

@ -17,7 +17,6 @@
<allow pkg="org.json.simple" />
<allow pkg="org.slf4j"/>
<allow pkg="org.enginehub"/>
<allow class="com.google.inject.Key"/>
<subpackage name="util.yaml">
<allow pkg="org.yaml.snakeyaml"/>
@ -40,6 +39,7 @@
<subpackage name="worldedit">
<allow pkg="org.mozilla.javascript"/>
<allow pkg="de.schlichtherle"/>
<allow pkg="com.google.auto"/>
<subpackage name="bukkit">
<allow pkg="org.bukkit"/>

View File

@ -27,7 +27,10 @@ import org.bukkit.command.CommandSender;
import org.enginehub.piston.CommandManager;
import org.enginehub.piston.CommandParameters;
import org.enginehub.piston.NoInputCommandParameters;
import org.enginehub.piston.inject.InjectedValueStore;
import org.enginehub.piston.inject.Key;
import org.enginehub.piston.inject.MapBackedValueStore;
import org.enginehub.piston.inject.MemoizingValueAccess;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -74,10 +77,11 @@ class BukkitCommandInspector implements CommandInspector {
public boolean testPermission(CommandSender sender, Command command) {
Optional<org.enginehub.piston.Command> mapping = dispatcher.getCommand(command.getName());
if (mapping.isPresent()) {
InjectedValueStore store = MapBackedValueStore.create();
store.injectValue(Key.of(Actor.class), context ->
Optional.of(plugin.wrapCommandSender(sender)));
CommandParameters parameters = NoInputCommandParameters.builder()
.injectedValues(ImmutableMap.of(
Key.of(Actor.class), plugin.wrapCommandSender(sender)
))
.injectedValues(MemoizingValueAccess.wrap(store))
.build();
return mapping.get().getCondition().satisfied(parameters);
} else {

View File

@ -21,7 +21,6 @@
package com.sk89q.worldedit.bukkit;
import com.google.common.collect.ImmutableMap;
import com.sk89q.util.StringUtil;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Player;
@ -42,7 +41,12 @@ import org.bukkit.inventory.EquipmentSlot;
import org.enginehub.piston.CommandManager;
import org.enginehub.piston.CommandParameters;
import org.enginehub.piston.NoInputCommandParameters;
import org.enginehub.piston.inject.InjectedValueStore;
import org.enginehub.piston.inject.Key;
import org.enginehub.piston.inject.MapBackedValueStore;
import org.enginehub.piston.inject.MemoizingValueAccess;
import java.util.Optional;
/**
* Handles all events thrown in relation to a Player
@ -108,17 +112,18 @@ public class WorldEditListener implements Listener {
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerCommand(PlayerCommandSendEvent event) {
InjectedValueStore store = MapBackedValueStore.create();
store.injectValue(Key.of(Actor.class), context ->
Optional.of(plugin.wrapCommandSender(event.getPlayer())));
CommandParameters parameters = NoInputCommandParameters.builder()
.injectedValues(ImmutableMap.of(
Key.of(Actor.class), plugin.wrapCommandSender(event.getPlayer())
))
.injectedValues(MemoizingValueAccess.wrap(store))
.build();
CommandManager commandManager = plugin.getWorldEdit().getPlatformManager().getPlatformCommandMananger().getCommandManager();
event.getCommands().removeIf(name ->
// remove if in the manager and not satisfied
commandManager.getCommand(name)
.filter(command -> !command.getCondition().satisfied(parameters))
.isPresent()
.filter(command -> !command.getCondition().satisfied(parameters))
.isPresent()
);
}

View File

@ -33,6 +33,9 @@ dependencies {
implementation "org.enginehub.piston.core-ap:runtime:$pistonVersion"
annotationProcessor "org.enginehub.piston.core-ap:processor:$pistonVersion"
api "org.enginehub.piston:default-impl:$pistonVersion"
def avVersion = "1.6.5"
compileOnly "com.google.auto.value:auto-value-annotations:$avVersion"
annotationProcessor "com.google.auto.value:auto-value:$avVersion"
//compile 'net.sf.trove4j:trove4j:3.0.3'
testCompile 'org.mockito:mockito-core:1.9.0-rc1'
}

View File

@ -0,0 +1,109 @@
/*
* 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.auto.value.AutoAnnotation;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.sk89q.worldedit.UnknownDirectionException;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.internal.annotation.Direction;
import com.sk89q.worldedit.math.BlockVector3;
import org.enginehub.piston.CommandManager;
import org.enginehub.piston.converter.ArgumentConverter;
import org.enginehub.piston.converter.ConversionResult;
import org.enginehub.piston.converter.FailedConversion;
import org.enginehub.piston.converter.SuccessfulConversion;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.enginehub.piston.inject.Key;
import java.util.List;
import static java.util.stream.Collectors.toList;
public class DirectionConverter implements ArgumentConverter<BlockVector3> {
@AutoAnnotation
private static Direction direction(boolean includeDiagonals) {
return new AutoAnnotation_DirectionConverter_direction(includeDiagonals);
}
public static void register(WorldEdit worldEdit, CommandManager commandManager) {
commandManager.registerConverter(
Key.of(BlockVector3.class, direction(false)),
new DirectionConverter(worldEdit, false)
);
commandManager.registerConverter(
Key.of(BlockVector3.class, direction(true)),
new DirectionConverter(worldEdit, true)
);
}
private static final ImmutableSet<String> NON_DIAGONALS = ImmutableSet.of(
"north", "south", "east", "west", "up", "down"
);
private static final ImmutableSet<String> RELATIVE = ImmutableSet.of(
"me", "forward", "back", "left", "right"
);
private static final ImmutableSet<String> DIAGONALS = ImmutableSet.of(
"northeast", "northwest", "southeast", "southwest"
);
private final WorldEdit worldEdit;
private final boolean includeDiagonals;
private final ImmutableList<String> suggestions;
private DirectionConverter(WorldEdit worldEdit, boolean includeDiagonals) {
this.worldEdit = worldEdit;
this.includeDiagonals = includeDiagonals;
suggestions = ImmutableList.<String>builder()
.addAll(NON_DIAGONALS)
.addAll(RELATIVE)
.addAll(includeDiagonals ? DIAGONALS : ImmutableList.of())
.build();
}
@Override
public ConversionResult<BlockVector3> convert(String argument, InjectedValueAccess context) {
Player player = context.injectedValue(Key.of(Player.class))
.orElseThrow(() -> new IllegalStateException("No player available"));
try {
return SuccessfulConversion.fromSingle(includeDiagonals
? worldEdit.getDiagonalDirection(player, argument)
: worldEdit.getDirection(player, argument));
} catch (UnknownDirectionException e) {
return FailedConversion.from(e);
}
}
@Override
public String describeAcceptableArguments() {
return "`me` to use facing direction, or any "
+ (includeDiagonals ? "direction" : "non-diagonal direction");
}
@Override
public List<String> getSuggestions(String input) {
return suggestions.stream()
.filter(s -> s.startsWith(input))
.collect(toList());
}
}

View File

@ -0,0 +1,58 @@
package com.sk89q.worldedit.command.argument;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extension.input.InputParseException;
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.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.world.World;
import org.enginehub.piston.CommandManager;
import org.enginehub.piston.converter.ArgumentConverter;
import org.enginehub.piston.converter.ConversionResult;
import org.enginehub.piston.converter.FailedConversion;
import org.enginehub.piston.converter.SuccessfulConversion;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.enginehub.piston.inject.Key;
public class MaskConverter implements ArgumentConverter<Mask> {
public static void register(WorldEdit worldEdit, CommandManager commandManager) {
commandManager.registerConverter(Key.of(Mask.class), new MaskConverter(worldEdit));
}
private final WorldEdit worldEdit;
private MaskConverter(WorldEdit worldEdit) {
this.worldEdit = worldEdit;
}
@Override
public ConversionResult<Mask> convert(String argument, InjectedValueAccess context) {
Actor actor = context.injectedValue(Key.of(Actor.class))
.orElseThrow(() -> new IllegalStateException("No actor"));
ParserContext parserContext = new ParserContext();
parserContext.setActor(actor);
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 SuccessfulConversion.fromSingle(
worldEdit.getMaskFactory().parseFromInput(argument, parserContext)
);
} catch (InputParseException e) {
return FailedConversion.from(e);
}
}
@Override
public String describeAcceptableArguments() {
return "any mask";
}
}

View File

@ -0,0 +1,21 @@
/*
* 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/>.
*/
@org.enginehub.piston.util.NonnullByDefault
package com.sk89q.worldedit.command.argument;

View File

@ -21,6 +21,7 @@ package com.sk89q.worldedit.extension.platform;
import com.google.common.collect.ImmutableList;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
@ -35,6 +36,8 @@ import com.sk89q.worldedit.command.ClipboardCommandsRegistration;
import com.sk89q.worldedit.command.SchematicCommands;
import com.sk89q.worldedit.command.SchematicCommandsRegistration;
import com.sk89q.worldedit.command.argument.Arguments;
import com.sk89q.worldedit.command.argument.DirectionConverter;
import com.sk89q.worldedit.command.argument.MaskConverter;
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
import com.sk89q.worldedit.command.util.PermissionCondition;
import com.sk89q.worldedit.entity.Entity;
@ -42,11 +45,13 @@ import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.platform.CommandEvent;
import com.sk89q.worldedit.event.platform.CommandSuggestionEvent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.internal.annotation.Selection;
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.WorldEditBinding;
import com.sk89q.worldedit.internal.command.WorldEditExceptionConverter;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.session.request.Request;
import com.sk89q.worldedit.util.command.parametric.ExceptionConverter;
import com.sk89q.worldedit.util.command.parametric.LegacyCommandsHandler;
@ -103,7 +108,7 @@ public final class PlatformCommandMananger {
private final PlatformManager platformManager;
private final CommandManager commandManager;
private final DynamicStreamHandler dynamicHandler = new DynamicStreamHandler();
private final ExceptionConverter exceptionConverter;
private final WorldEditExceptionConverter exceptionConverter;
private final List<CommandCallListener> callListeners;
/**
@ -153,6 +158,45 @@ public final class PlatformCommandMananger {
builder.addBinding(new WorldEditBinding(worldEdit));
builder.addInvokeListener(new LegacyCommandsHandler());
registerAlwaysInjectedValues();
registerArgumentConverters();
registerAllCommands();
}
private void registerArgumentConverters() {
DirectionConverter.register(worldEdit, commandManager);
MaskConverter.register(worldEdit, commandManager);
}
private void registerAlwaysInjectedValues() {
commandManager.injectValue(Key.of(Region.class, Selection.class),
context -> {
LocalSession localSession = context.injectedValue(Key.of(LocalSession.class))
.orElseThrow(() -> new IllegalStateException("No LocalSession"));
return context.injectedValue(Key.of(Player.class))
.map(player -> {
try {
return localSession.getSelection(player.getWorld());
} catch (IncompleteRegionException e) {
exceptionConverter.convert(e);
throw new AssertionError("Should have thrown a new exception.");
}
});
});
commandManager.injectValue(Key.of(EditSession.class),
context -> {
LocalSession localSession = context.injectedValue(Key.of(LocalSession.class))
.orElseThrow(() -> new IllegalStateException("No LocalSession"));
return context.injectedValue(Key.of(Player.class))
.map(player -> {
EditSession editSession = localSession.createEditSession(player);
editSession.enableStandardMode();
return editSession;
});
});
}
private void registerAllCommands() {
commandManager.register("schematic", cmd -> {
cmd.aliases(ImmutableList.of("schem", "/schematic", "/schem"));
cmd.description("Schematic commands for saving/loading areas");
@ -348,17 +392,6 @@ public final class PlatformCommandMananger {
localSession.tellVersion(actor);
return Optional.of(localSession);
});
store.injectValue(Key.of(EditSession.class),
context -> {
LocalSession localSession = context.injectedValue(Key.of(LocalSession.class))
.orElseThrow(() -> new IllegalStateException("No LocalSession"));
return context.injectedValue(Key.of(Player.class))
.map(player -> {
EditSession editSession = localSession.createEditSession(player);
editSession.enableStandardMode();
return editSession;
});
});
MemoizingValueAccess context = MemoizingValueAccess.wrap(store);

View File

@ -19,7 +19,8 @@
package com.sk89q.worldedit.internal.annotation;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.BlockVector3;
import org.enginehub.piston.inject.InjectAnnotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@ -27,12 +28,13 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotates a {@link Vector3} parameter to inject a direction.
* Annotates a {@link BlockVector3} parameter to inject a direction.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@InjectAnnotation
public @interface Direction {
String AIM = "me";
boolean includeDiagonals() default false;