From f2f9c266029123869dfd04b1fc9220dbcadccd77 Mon Sep 17 00:00:00 2001 From: wizjany Date: Sun, 9 Jun 2019 00:30:57 -0400 Subject: [PATCH] Expanded the scope of item brushes (/br apply item, /br paint item). They now additionally take a direction in which the simulated item usage should be facing. Also allow the item parser to parse "hand" and "offhand" as items, to allow platforms with NBT item support return items with NBT (since parsing is a slightly more complex task). --- .../worldedit/blocks/MobSpawnerBlock.java | 7 +- .../com/sk89q/worldedit/blocks/SignBlock.java | 6 +- .../java/com/sk89q/worldedit/WorldEdit.java | 36 +++--- .../worldedit/command/ApplyBrushCommands.java | 20 ++- .../worldedit/command/PaintBrushCommands.java | 20 ++- .../argument/AbstractDirectionConverter.java | 119 ++++++++++++++++++ .../command/argument/DirectionConverter.java | 92 +++----------- .../argument/DirectionVectorConverter.java | 49 ++++++++ .../command/factory/ItemUseFactory.java | 9 +- .../factory/parser/DefaultBlockParser.java | 9 +- .../factory/parser/DefaultItemParser.java | 18 +++ .../platform/PlatformCommandManager.java | 2 + .../worldedit/function/ItemUseFunction.java | 9 +- .../world/registry/LegacyMapper.java | 9 +- 14 files changed, 287 insertions(+), 118 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/AbstractDirectionConverter.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionVectorConverter.java diff --git a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java index cde191e64..b68120948 100644 --- a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java +++ b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java @@ -116,7 +116,7 @@ public class MobSpawnerBlock extends BaseBlock { @Override public String getNbtId() { - return "MobSpawner"; + return "minecraft:mob_spawner"; } @Override @@ -154,8 +154,8 @@ public class MobSpawnerBlock extends BaseBlock { Map values = rootTag.getValue(); Tag t = values.get("id"); - if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("MobSpawner")) { - throw new RuntimeException("'MobSpawner' tile entity expected"); + if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals(getNbtId())) { + throw new RuntimeException(String.format("'%s' tile entity expected", getNbtId())); } CompoundTag spawnDataTag; @@ -169,6 +169,7 @@ public class MobSpawnerBlock extends BaseBlock { throw new InvalidFormatException("No spawn id."); } this.mobType = mobType; + this.spawnData = spawnDataTag; } catch (InvalidFormatException ignored) { throw new RuntimeException("Invalid mob spawner data: no SpawnData and/or no Delay"); } diff --git a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SignBlock.java b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SignBlock.java index 4cc0e5bcb..0f1811e13 100644 --- a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SignBlock.java +++ b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SignBlock.java @@ -88,7 +88,7 @@ public class SignBlock extends BaseBlock { @Override public String getNbtId() { - return "Sign"; + return "minecraft:sign"; } @Override @@ -114,8 +114,8 @@ public class SignBlock extends BaseBlock { text = new String[] { EMPTY, EMPTY, EMPTY, EMPTY }; t = values.get("id"); - if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Sign")) { - throw new RuntimeException("'Sign' tile entity expected"); + if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals(getNbtId())) { + throw new RuntimeException(String.format("'%s' tile entity expected", getNbtId())); } t = values.get("Text1"); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java b/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java index c9e926222..fa60eb72f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java @@ -408,15 +408,14 @@ public final class WorldEdit { } /** - * Get the direction vector for a player's direction. May return - * null if a direction could not be found. + * Get the direction vector for a player's direction. * * @param player the player * @param dirStr the direction string * @return a direction vector - * @throws UnknownDirectionException thrown if the direction is not known + * @throws UnknownDirectionException thrown if the direction is not known, or a relative direction is used with null player */ - public BlockVector3 getDirection(Player player, String dirStr) throws UnknownDirectionException { + public BlockVector3 getDirection(@Nullable Player player, String dirStr) throws UnknownDirectionException { dirStr = dirStr.toLowerCase(Locale.ROOT); final Direction dir = getPlayerDirection(player, dirStr); @@ -429,15 +428,14 @@ public final class WorldEdit { } /** - * Get the direction vector for a player's direction. May return - * null if a direction could not be found. + * Get the direction vector for a player's direction. * * @param player the player * @param dirStr the direction string * @return a direction vector - * @throws UnknownDirectionException thrown if the direction is not known + * @throws UnknownDirectionException thrown if the direction is not known, or a relative direction is used with null player */ - public BlockVector3 getDiagonalDirection(Player player, String dirStr) throws UnknownDirectionException { + public BlockVector3 getDiagonalDirection(@Nullable Player player, String dirStr) throws UnknownDirectionException { dirStr = dirStr.toLowerCase(Locale.ROOT); final Direction dir = getPlayerDirection(player, dirStr); @@ -450,15 +448,14 @@ public final class WorldEdit { } /** - * Get the direction vector for a player's direction. May return - * null if a direction could not be found. + * Get the direction vector for a player's direction. * * @param player the player * @param dirStr the direction string * @return a direction enum value - * @throws UnknownDirectionException thrown if the direction is not known + * @throws UnknownDirectionException thrown if the direction is not known, or a relative direction is used with null player */ - private Direction getPlayerDirection(Player player, String dirStr) throws UnknownDirectionException { + private Direction getPlayerDirection(@Nullable Player player, String dirStr) throws UnknownDirectionException { final Direction dir; switch (dirStr.charAt(0)) { @@ -502,19 +499,19 @@ public final class WorldEdit { case 'm': // me case 'f': // forward - dir = player.getCardinalDirection(0); + dir = getDirectionRelative(player, 0); break; case 'b': // back - dir = player.getCardinalDirection(180); + dir = getDirectionRelative(player, 180); break; case 'l': // left - dir = player.getCardinalDirection(-90); + dir = getDirectionRelative(player, -90); break; case 'r': // right - dir = player.getCardinalDirection(90); + dir = getDirectionRelative(player, 90); break; default: @@ -523,6 +520,13 @@ public final class WorldEdit { return dir; } + private Direction getDirectionRelative(Player player, int yawOffset) throws UnknownDirectionException { + if (player != null) { + return player.getCardinalDirection(yawOffset); + } + throw new UnknownDirectionException("Only a player can use relative directions"); + } + /** * Flush a block bag's changes to a player. * diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java index 25c1dbdc1..67bb630bd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java @@ -27,17 +27,22 @@ import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.command.factory.ItemUseFactory; import com.sk89q.worldedit.command.factory.ReplaceFactory; import com.sk89q.worldedit.command.factory.TreeGeneratorFactory; +import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.function.Contextual; import com.sk89q.worldedit.function.RegionFunction; import com.sk89q.worldedit.function.factory.Apply; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.internal.annotation.Direction; +import com.sk89q.worldedit.internal.command.CommandRegistrationHandler; import com.sk89q.worldedit.regions.factory.RegionFactory; import com.sk89q.worldedit.util.TreeGenerator; -import com.sk89q.worldedit.internal.command.CommandRegistrationHandler; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; +import com.sk89q.worldedit.util.formatting.text.format.TextDecoration; import org.enginehub.piston.CommandManager; import org.enginehub.piston.CommandManagerService; import org.enginehub.piston.CommandParameters; @@ -53,7 +58,7 @@ import java.util.stream.Collectors; import static java.util.Objects.requireNonNull; import static org.enginehub.piston.part.CommandParts.arg; -@CommandContainer +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class ApplyBrushCommands { private static final CommandArgument REGION_FACTORY = arg(TranslatableComponent.of("shape"), TextComponent.of("The shape of the region")) @@ -111,11 +116,18 @@ public class ApplyBrushCommands { name = "item", desc = "Use an item" ) + @CommandPermissions("worldedit.brush.item") public void item(CommandParameters parameters, Player player, LocalSession localSession, @Arg(desc = "The type of item to use") - BaseItem item) throws WorldEditException { - setApplyBrush(parameters, player, localSession, new ItemUseFactory(item)); + BaseItem item, + @Arg(desc = "The direction in which the item will be applied", def = "up") + @Direction(includeDiagonals = true) + com.sk89q.worldedit.util.Direction direction) throws WorldEditException { + player.print(TextComponent.builder().append("WARNING: ", TextColor.RED, TextDecoration.BOLD) + .append("This brush simulates item usages. Its effects may not work on all platforms, may not be undo-able," + + " and may cause strange interactions with other mods/plugins. Use at your own risk.").build()); + setApplyBrush(parameters, player, localSession, new ItemUseFactory(item, direction)); } @Command( diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java index e3c92236b..ea929ec49 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java @@ -27,17 +27,22 @@ import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.command.factory.ItemUseFactory; import com.sk89q.worldedit.command.factory.ReplaceFactory; import com.sk89q.worldedit.command.factory.TreeGeneratorFactory; +import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.function.Contextual; import com.sk89q.worldedit.function.RegionFunction; import com.sk89q.worldedit.function.factory.Paint; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.internal.annotation.Direction; +import com.sk89q.worldedit.internal.command.CommandRegistrationHandler; import com.sk89q.worldedit.regions.factory.RegionFactory; import com.sk89q.worldedit.util.TreeGenerator; -import com.sk89q.worldedit.internal.command.CommandRegistrationHandler; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; +import com.sk89q.worldedit.util.formatting.text.format.TextDecoration; import org.enginehub.piston.CommandManager; import org.enginehub.piston.CommandManagerService; import org.enginehub.piston.CommandParameters; @@ -53,7 +58,7 @@ import java.util.stream.Collectors; import static java.util.Objects.requireNonNull; import static org.enginehub.piston.part.CommandParts.arg; -@CommandContainer +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class PaintBrushCommands { private static final CommandArgument REGION_FACTORY = arg(TranslatableComponent.of("shape"), TextComponent.of("The shape of the region")) @@ -117,11 +122,18 @@ public class PaintBrushCommands { name = "item", desc = "Use an item" ) + @CommandPermissions("worldedit.brush.item") public void item(CommandParameters parameters, Player player, LocalSession localSession, @Arg(desc = "The type of item to use") - BaseItem item) throws WorldEditException { - setPaintBrush(parameters, player, localSession, new ItemUseFactory(item)); + BaseItem item, + @Arg(desc = "The direction in which the item will be applied", def = "up") + @Direction(includeDiagonals = true) + com.sk89q.worldedit.util.Direction direction) throws WorldEditException { + player.print(TextComponent.builder().append("WARNING: ", TextColor.RED, TextDecoration.BOLD) + .append("This brush simulates item usages. Its effects may not work on all platforms, may not be undo-able," + + " and may cause strange interactions with other mods/plugins. Use at your own risk.").build()); + setPaintBrush(parameters, player, localSession, new ItemUseFactory(item, direction)); } @Command( diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/AbstractDirectionConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/AbstractDirectionConverter.java new file mode 100644 index 000000000..bd2a28067 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/AbstractDirectionConverter.java @@ -0,0 +1,119 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * 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 . + */ + +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.internal.annotation.MultiDirection; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +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 javax.annotation.Nullable; +import java.util.List; + +import static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix; + +public abstract class AbstractDirectionConverter implements ArgumentConverter { + + @AutoAnnotation + private static Direction direction(boolean includeDiagonals) { + return new AutoAnnotation_AbstractDirectionConverter_direction(includeDiagonals); + } + + @AutoAnnotation + private static MultiDirection multiDirection(boolean includeDiagonals) { + return new AutoAnnotation_AbstractDirectionConverter_multiDirection(includeDiagonals); + } + + protected static void register(CommandManager commandManager, AbstractDirectionConverter converter, + Class keyClass, boolean includeDiagonals) { + commandManager.registerConverter( + Key.of(keyClass, direction(includeDiagonals)), + converter + ); + commandManager.registerConverter( + Key.of(keyClass, multiDirection(includeDiagonals)), + CommaSeparatedValuesConverter.wrap(converter) + ); + } + + private static final ImmutableSet ORTHOGONAL = ImmutableSet.of( + "north", "south", "east", "west", "up", "down" + ); + private static final ImmutableSet RELATIVE = ImmutableSet.of( + "me", "forward", "back", "left", "right" + ); + private static final ImmutableSet DIAGONAL = ImmutableSet.of( + "northeast", "northwest", "southeast", "southwest" + ); + + private final WorldEdit worldEdit; + private final boolean includeDiagonals; + private final ImmutableList suggestions; + + protected AbstractDirectionConverter(WorldEdit worldEdit, boolean includeDiagonals) { + this.worldEdit = worldEdit; + this.includeDiagonals = includeDiagonals; + suggestions = ImmutableList.builder() + .addAll(ORTHOGONAL) + .addAll(RELATIVE) + .addAll(includeDiagonals ? DIAGONAL : ImmutableList.of()) + .build(); + } + + @Override + public ConversionResult convert(String argument, InjectedValueAccess context) { + Player player = context.injectedValue(Key.of(Player.class)).orElse(null); + try { + return SuccessfulConversion.fromSingle(convertDirection(argument, player, includeDiagonals)); + } catch (Exception e) { + return FailedConversion.from(e); + } + } + + protected abstract D convertDirection(String argument, @Nullable Player player, boolean includeDiagonals) throws UnknownDirectionException; + + @Override + public Component describeAcceptableArguments() { + return TextComponent.of("`me` to use facing direction, or any " + + (includeDiagonals ? "direction" : "non-diagonal direction")); + } + + @Override + public List getSuggestions(String input) { + return limitByPrefix(suggestions.stream(), input); + } + + protected WorldEdit getWorldEdit() { + return worldEdit; + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionConverter.java index 78d702aa9..22e0b2fbe 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionConverter.java @@ -19,101 +19,37 @@ 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.internal.annotation.MultiDirection; +import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.Direction; 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 javax.annotation.Nullable; +import java.util.Optional; -import static java.util.stream.Collectors.toList; -import static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix; +public final class DirectionConverter extends AbstractDirectionConverter { -public class DirectionConverter implements ArgumentConverter { - - @AutoAnnotation - private static Direction direction(boolean includeDiagonals) { - return new AutoAnnotation_DirectionConverter_direction(includeDiagonals); - } - - @AutoAnnotation - private static MultiDirection multiDirection(boolean includeDiagonals) { - return new AutoAnnotation_DirectionConverter_multiDirection(includeDiagonals); + private DirectionConverter(WorldEdit worldEdit, boolean includeDiagonals) { + super(worldEdit, includeDiagonals); } public static void register(WorldEdit worldEdit, CommandManager commandManager) { for (boolean includeDiagonals : new boolean[] { false, true }) { DirectionConverter directionConverter = new DirectionConverter(worldEdit, includeDiagonals); - commandManager.registerConverter( - Key.of(BlockVector3.class, direction(includeDiagonals)), - directionConverter - ); - commandManager.registerConverter( - Key.of(BlockVector3.class, multiDirection(includeDiagonals)), - CommaSeparatedValuesConverter.wrap(directionConverter) - ); - } - } - - private static final ImmutableSet NON_DIAGONALS = ImmutableSet.of( - "north", "south", "east", "west", "up", "down" - ); - private static final ImmutableSet RELATIVE = ImmutableSet.of( - "me", "forward", "back", "left", "right" - ); - private static final ImmutableSet DIAGONALS = ImmutableSet.of( - "northeast", "northwest", "southeast", "southwest" - ); - - private final WorldEdit worldEdit; - private final boolean includeDiagonals; - private final ImmutableList suggestions; - - private DirectionConverter(WorldEdit worldEdit, boolean includeDiagonals) { - this.worldEdit = worldEdit; - this.includeDiagonals = includeDiagonals; - suggestions = ImmutableList.builder() - .addAll(NON_DIAGONALS) - .addAll(RELATIVE) - .addAll(includeDiagonals ? DIAGONALS : ImmutableList.of()) - .build(); - } - - @Override - public ConversionResult 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 (Exception e) { - return FailedConversion.from(e); + register(commandManager, directionConverter, Direction.class, includeDiagonals); } } @Override - public Component describeAcceptableArguments() { - return TextComponent.of("`me` to use facing direction, or any " - + (includeDiagonals ? "direction" : "non-diagonal direction")); + protected Direction convertDirection(String argument, @Nullable Player player, boolean includeDiagonals) throws UnknownDirectionException { + final BlockVector3 vec = includeDiagonals + ? getWorldEdit().getDiagonalDirection(player, argument) + : getWorldEdit().getDirection(player, argument); + return Optional.ofNullable(Direction.findClosest(vec.toVector3(), Direction.Flag.ALL)) + .orElseThrow(() -> new UnknownDirectionException(argument)); } - @Override - public List getSuggestions(String input) { - return limitByPrefix(suggestions.stream(), input); - } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionVectorConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionVectorConverter.java new file mode 100644 index 000000000..1295fbceb --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionVectorConverter.java @@ -0,0 +1,49 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * 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 . + */ + +package com.sk89q.worldedit.command.argument; + +import com.sk89q.worldedit.UnknownDirectionException; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.math.BlockVector3; +import org.enginehub.piston.CommandManager; + +import javax.annotation.Nullable; + +public final class DirectionVectorConverter extends AbstractDirectionConverter { + + private DirectionVectorConverter(WorldEdit worldEdit, boolean includeDiagonals) { + super(worldEdit, includeDiagonals); + } + + public static void register(WorldEdit worldEdit, CommandManager commandManager) { + for (boolean includeDiagonals : new boolean[] { false, true }) { + DirectionVectorConverter directionConverter = new DirectionVectorConverter(worldEdit, includeDiagonals); + register(commandManager, directionConverter, BlockVector3.class, includeDiagonals); + } + } + + @Override + protected BlockVector3 convertDirection(String argument, @Nullable Player player, boolean includeDiagonals) throws UnknownDirectionException { + return includeDiagonals + ? getWorldEdit().getDiagonalDirection(player, argument) + : getWorldEdit().getDirection(player, argument); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ItemUseFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ItemUseFactory.java index a099a78a1..7ad8866c3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ItemUseFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ItemUseFactory.java @@ -25,19 +25,26 @@ import com.sk89q.worldedit.function.ItemUseFunction; import com.sk89q.worldedit.function.Contextual; import com.sk89q.worldedit.function.EditContext; import com.sk89q.worldedit.function.RegionFunction; +import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.world.World; public final class ItemUseFactory implements Contextual { private final BaseItem item; + private final Direction dir; public ItemUseFactory(BaseItem item) { + this(item, Direction.UP); + } + + public ItemUseFactory(BaseItem item, Direction dir) { this.item = item; + this.dir = dir; } @Override public RegionFunction createFromContext(EditContext input) { World world = ((EditSession) input.getDestination()).getWorld(); - return new ItemUseFunction(world, item); + return new ItemUseFunction(world, item, dir); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java index 9f4402715..55a9089b0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java @@ -41,6 +41,7 @@ import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; +import com.sk89q.worldedit.world.block.BlockCategory; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; @@ -170,9 +171,9 @@ public class DefaultBlockParser extends InputParser { Property propertyKey = (Property) type.getPropertyMap().get(parts[0]); if (propertyKey == null) { if (context.getActor() != null) { - throw new NoMatchException("Unknown property " + parts[0] + " for block " + type.getName()); + throw new NoMatchException("Unknown property " + parts[0] + " for block " + type.getId()); } else { - WorldEdit.logger.warn("Unknown property " + parts[0] + " for block " + type.getName()); + WorldEdit.logger.warn("Unknown property " + parts[0] + " for block " + type.getId()); } return Maps.newHashMap(); } @@ -345,7 +346,9 @@ public class DefaultBlockParser extends InputParser { } } - if (blockType == BlockTypes.SIGN || blockType == BlockTypes.WALL_SIGN) { + final BlockCategory signCategory = BlockCategory.REGISTRY.get("minecraft:signs"); + if (blockType == BlockTypes.SIGN || blockType == BlockTypes.WALL_SIGN + || signCategory != null && signCategory.contains(blockType)) { // Allow special sign text syntax String[] text = new String[4]; text[0] = blockAndExtraData.length > 1 ? blockAndExtraData[1] : ""; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultItemParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultItemParser.java index 450538f28..631fed2dd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultItemParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultItemParser.java @@ -21,10 +21,14 @@ package com.sk89q.worldedit.extension.factory.parser; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.blocks.BaseItem; +import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.command.util.SuggestionHelper; +import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.internal.registry.InputParser; +import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.registry.LegacyMapper; @@ -65,6 +69,12 @@ public class DefaultItemParser extends InputParser { } } + if ("hand".equalsIgnoreCase(input)) { + return getItemInHand(context.requireActor(), HandSide.MAIN_HAND); + } else if ("offhand".equalsIgnoreCase(input)) { + return getItemInHand(context.requireActor(), HandSide.OFF_HAND); + } + if (item == null) { ItemType type = ItemTypes.get(input.toLowerCase(Locale.ROOT)); if (type != null) { @@ -79,4 +89,12 @@ public class DefaultItemParser extends InputParser { } } + private BaseItemStack getItemInHand(Actor actor, HandSide handSide) throws InputParseException { + if (actor instanceof Player) { + return ((Player) actor).getItemInHand(handSide); + } else { + throw new InputParseException("The user is not a player!"); + } + } + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java index 2de667d08..3086613ec 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java @@ -72,6 +72,7 @@ import com.sk89q.worldedit.command.argument.Arguments; import com.sk89q.worldedit.command.argument.BooleanConverter; import com.sk89q.worldedit.command.argument.CommaSeparatedValuesConverter; import com.sk89q.worldedit.command.argument.DirectionConverter; +import com.sk89q.worldedit.command.argument.DirectionVectorConverter; import com.sk89q.worldedit.command.argument.EntityRemoverConverter; import com.sk89q.worldedit.command.argument.EnumConverter; import com.sk89q.worldedit.command.argument.FactoryConverter; @@ -200,6 +201,7 @@ public final class PlatformCommandManager { } private void registerArgumentConverters() { + DirectionVectorConverter.register(worldEdit, commandManager); DirectionConverter.register(worldEdit, commandManager); FactoryConverter.register(worldEdit, commandManager); for (int count = 2; count <= 3; count++) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/ItemUseFunction.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/ItemUseFunction.java index 4e439f0c3..905ccd3e6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/ItemUseFunction.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/ItemUseFunction.java @@ -21,7 +21,6 @@ package com.sk89q.worldedit.function; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; -import com.sk89q.worldedit.function.RegionFunction; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.world.World; @@ -29,14 +28,20 @@ import com.sk89q.worldedit.world.World; public final class ItemUseFunction implements RegionFunction { private final World world; private final BaseItem item; + private final Direction dir; public ItemUseFunction(World world, BaseItem item) { + this(world, item, Direction.UP); + } + + public ItemUseFunction(World world, BaseItem item, Direction dir) { this.world = world; this.item = item; + this.dir = dir; } @Override public boolean apply(BlockVector3 position) throws WorldEditException { - return world.useItem(position, item, Direction.UP); + return world.useItem(position, item, dir); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/LegacyMapper.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/LegacyMapper.java index d12503f19..e48444094 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/LegacyMapper.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/LegacyMapper.java @@ -93,15 +93,16 @@ public final class LegacyMapper { for (Map.Entry blockEntry : dataFile.blocks.entrySet()) { String id = blockEntry.getKey(); - blockEntries.put(id, blockEntry.getValue()); + final String value = blockEntry.getValue(); + blockEntries.put(id, value); try { - BlockState state = WorldEdit.getInstance().getBlockFactory().parseFromInput(blockEntry.getValue(), parserContext).toImmutableState(); + BlockState state = WorldEdit.getInstance().getBlockFactory().parseFromInput(value, parserContext).toImmutableState(); blockToStringMap.put(state, id); stringToBlockMap.put(id, state); } catch (InputParseException e) { boolean fixed = false; if (fixer != null) { - String newEntry = fixer.fixUp(DataFixer.FixTypes.BLOCK_STATE, blockEntry.getValue(), 1631); + String newEntry = fixer.fixUp(DataFixer.FixTypes.BLOCK_STATE, value, 1631); try { BlockState state = WorldEdit.getInstance().getBlockFactory().parseFromInput(newEntry, parserContext).toImmutableState(); blockToStringMap.put(state, id); @@ -111,7 +112,7 @@ public final class LegacyMapper { } } if (!fixed) { - log.warn("Unknown block: " + blockEntry.getValue()); + log.warn("Unknown block: " + value); } } }