mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-07-12 04:28:34 +00:00
Copy paste/merge FAWE classes to this WorldEdit fork
- so certain people can look at the diff and complain about my sloppy code :( Signed-off-by: Jesse Boyd <jessepaleg@gmail.com>
This commit is contained in:
@ -19,43 +19,97 @@
|
||||
|
||||
package com.sk89q.worldedit.util;
|
||||
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* A collection of cardinal, ordinal, and secondary-ordinal directions.
|
||||
*/
|
||||
public enum Direction {
|
||||
|
||||
NORTH(new Vector(0, 0, -1), Flag.CARDINAL),
|
||||
EAST(new Vector(1, 0, 0), Flag.CARDINAL),
|
||||
SOUTH(new Vector(0, 0, 1), Flag.CARDINAL),
|
||||
WEST(new Vector(-1, 0, 0), Flag.CARDINAL),
|
||||
NORTH(new Vector(0, 0, -1), Flag.CARDINAL, 3, 1),
|
||||
EAST(new Vector(1, 0, 0), Flag.CARDINAL, 0, 2),
|
||||
SOUTH(new Vector(0, 0, 1), Flag.CARDINAL, 1, 3),
|
||||
WEST(new Vector(-1, 0, 0), Flag.CARDINAL, 2, 0),
|
||||
|
||||
UP(new Vector(0, 1, 0), Flag.UPRIGHT),
|
||||
DOWN(new Vector(0, -1, 0), Flag.UPRIGHT),
|
||||
UP(new Vector(0, 1, 0), Flag.UPRIGHT, -1, -1),
|
||||
DOWN(new Vector(0, -1, 0), Flag.UPRIGHT, -1, -1),
|
||||
|
||||
NORTHEAST(new Vector(1, 0, -1), Flag.ORDINAL),
|
||||
NORTHWEST(new Vector(-1, 0, -1), Flag.ORDINAL),
|
||||
SOUTHEAST(new Vector(1, 0, 1), Flag.ORDINAL),
|
||||
SOUTHWEST(new Vector(-1, 0, 1), Flag.ORDINAL),
|
||||
NORTHEAST(new Vector(1, 0, -1), Flag.ORDINAL, 7, 8),
|
||||
NORTHWEST(new Vector(-1, 0, -1), Flag.ORDINAL, 9, 6),
|
||||
SOUTHEAST(new Vector(1, 0, 1), Flag.ORDINAL, 6, 9),
|
||||
SOUTHWEST(new Vector(-1, 0, 1), Flag.ORDINAL, 8, 7),
|
||||
|
||||
WEST_NORTHWEST(new Vector(-Math.cos(Math.PI / 8), 0, -Math.sin(Math.PI / 8)), Flag.SECONDARY_ORDINAL),
|
||||
WEST_SOUTHWEST(new Vector(-Math.cos(Math.PI / 8), 0, Math.sin(Math.PI / 8)), Flag.SECONDARY_ORDINAL),
|
||||
NORTH_NORTHWEST(new Vector(-Math.sin(Math.PI / 8), 0, -Math.cos(Math.PI / 8)), Flag.SECONDARY_ORDINAL),
|
||||
NORTH_NORTHEAST(new Vector(Math.sin(Math.PI / 8), 0, -Math.cos(Math.PI / 8)), Flag.SECONDARY_ORDINAL),
|
||||
EAST_NORTHEAST(new Vector(Math.cos(Math.PI / 8), 0, -Math.sin(Math.PI / 8)), Flag.SECONDARY_ORDINAL),
|
||||
EAST_SOUTHEAST(new Vector(Math.cos(Math.PI / 8), 0, Math.sin(Math.PI / 8)), Flag.SECONDARY_ORDINAL),
|
||||
SOUTH_SOUTHEAST(new Vector(Math.sin(Math.PI / 8), 0, Math.cos(Math.PI / 8)), Flag.SECONDARY_ORDINAL),
|
||||
SOUTH_SOUTHWEST(new Vector(-Math.sin(Math.PI / 8), 0, Math.cos(Math.PI / 8)), Flag.SECONDARY_ORDINAL);
|
||||
WEST_NORTHWEST(new Vector(-Math.cos(Math.PI / 8), 0, -Math.sin(Math.PI / 8)), Flag.SECONDARY_ORDINAL, 9, 6),
|
||||
WEST_SOUTHWEST(new Vector(-Math.cos(Math.PI / 8), 0, Math.sin(Math.PI / 8)), Flag.SECONDARY_ORDINAL, 8, 7),
|
||||
NORTH_NORTHWEST(new Vector(-Math.sin(Math.PI / 8), 0, -Math.cos(Math.PI / 8)), Flag.SECONDARY_ORDINAL, 9, 6),
|
||||
NORTH_NORTHEAST(new Vector(Math.sin(Math.PI / 8), 0, -Math.cos(Math.PI / 8)), Flag.SECONDARY_ORDINAL, 7, 8),
|
||||
EAST_NORTHEAST(new Vector(Math.cos(Math.PI / 8), 0, -Math.sin(Math.PI / 8)), Flag.SECONDARY_ORDINAL, 7, 8),
|
||||
EAST_SOUTHEAST(new Vector(Math.cos(Math.PI / 8), 0, Math.sin(Math.PI / 8)), Flag.SECONDARY_ORDINAL, 6, 9),
|
||||
SOUTH_SOUTHEAST(new Vector(Math.sin(Math.PI / 8), 0, Math.cos(Math.PI / 8)), Flag.SECONDARY_ORDINAL, 6, 9),
|
||||
SOUTH_SOUTHWEST(new Vector(-Math.sin(Math.PI / 8), 0, Math.cos(Math.PI / 8)), Flag.SECONDARY_ORDINAL, 8, 7);
|
||||
|
||||
private final Vector direction;
|
||||
private final int flags;
|
||||
private final BlockVector blockVector;
|
||||
private final int flags, left, right;
|
||||
|
||||
Direction(Vector vector, int flags) {
|
||||
|
||||
private static HashMap<String, Direction> map = new HashMap<>();
|
||||
public static final Direction[] values = values();
|
||||
public static final Direction[] cardinal = new Direction[]{ NORTH, EAST, SOUTH, WEST };
|
||||
|
||||
static {
|
||||
for (Direction dir : Direction.values()) {
|
||||
map.put(dir.name(), dir);
|
||||
map.put(dir.name().toLowerCase(), dir);
|
||||
}
|
||||
}
|
||||
|
||||
private Direction(Vector vector, int flags, int left, int right) {
|
||||
this.direction = vector.normalize();
|
||||
this.blockVector = new BlockVector(Math.signum(vector.getX()), Math.signum(vector.getY()), Math.signum(vector.getZ()));
|
||||
this.flags = flags;
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
}
|
||||
|
||||
public static Direction get(CharSequence sequence) {
|
||||
return map.get(sequence);
|
||||
}
|
||||
|
||||
public Direction getLeft() {
|
||||
return left != -1 ? values[left] : null;
|
||||
}
|
||||
|
||||
public Direction getRight() {
|
||||
return right != -1 ? values[right] : null;
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return direction.getX();
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return direction.getY();
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return direction.getZ();
|
||||
}
|
||||
|
||||
public int getBlockX() {
|
||||
return blockVector.getBlockX();
|
||||
}
|
||||
|
||||
public int getBlockY() {
|
||||
return blockVector.getBlockY();
|
||||
}
|
||||
|
||||
public int getBlockZ() {
|
||||
return blockVector.getBlockZ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -109,6 +163,15 @@ public enum Direction {
|
||||
return direction;
|
||||
}
|
||||
|
||||
public BlockVector toBlockVector() {
|
||||
return this.blockVector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the closest direction to the given direction vector.
|
||||
*
|
||||
|
@ -19,10 +19,10 @@
|
||||
|
||||
package com.sk89q.worldedit.util;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Helper methods for enums.
|
||||
*/
|
||||
|
@ -21,14 +21,13 @@ package com.sk89q.worldedit.util;
|
||||
|
||||
import com.sk89q.util.StringUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
|
||||
public final class FileDialogUtil {
|
||||
private FileDialogUtil() {
|
||||
}
|
||||
|
@ -19,10 +19,10 @@
|
||||
|
||||
package com.sk89q.worldedit.util;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public final class GuavaUtil {
|
||||
|
||||
private GuavaUtil() {}
|
||||
|
@ -19,10 +19,11 @@
|
||||
|
||||
package com.sk89q.worldedit.util;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.world.NullWorld;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Represents a location in a world with has a direction.
|
||||
@ -34,10 +35,9 @@ import com.sk89q.worldedit.extent.Extent;
|
||||
* {@link #equals(Object)} are subject to minor differences caused by
|
||||
* floating point errors.</p>
|
||||
*/
|
||||
public class Location {
|
||||
public class Location extends Vector {
|
||||
|
||||
private final Extent extent;
|
||||
private final Vector position;
|
||||
private final float pitch;
|
||||
private final float yaw;
|
||||
|
||||
@ -126,10 +126,9 @@ public class Location {
|
||||
* @param pitch the pitch, in degrees
|
||||
*/
|
||||
public Location(Extent extent, Vector position, float yaw, float pitch) {
|
||||
super(position);
|
||||
checkNotNull(extent);
|
||||
checkNotNull(position);
|
||||
this.extent = extent;
|
||||
this.position = position;
|
||||
this.pitch = pitch;
|
||||
this.yaw = yaw;
|
||||
}
|
||||
@ -150,7 +149,7 @@ public class Location {
|
||||
* @return the new instance
|
||||
*/
|
||||
public Location setExtent(Extent extent) {
|
||||
return new Location(extent, position, getDirection());
|
||||
return new Location(extent, this, getDirection());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,7 +168,7 @@ public class Location {
|
||||
* @return the new instance
|
||||
*/
|
||||
public Location setYaw(float yaw) {
|
||||
return new Location(extent, position, yaw, pitch);
|
||||
return new Location(extent, this, yaw, pitch);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -188,7 +187,7 @@ public class Location {
|
||||
* @return the new instance
|
||||
*/
|
||||
public Location setPitch(float pitch) {
|
||||
return new Location(extent, position, yaw, pitch);
|
||||
return new Location(extent, this, yaw, pitch);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -199,7 +198,7 @@ public class Location {
|
||||
* @return the new instance
|
||||
*/
|
||||
public Location setDirection(float yaw, float pitch) {
|
||||
return new Location(extent, position, yaw, pitch);
|
||||
return new Location(extent, this, yaw, pitch);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -233,7 +232,7 @@ public class Location {
|
||||
* @return the new instance
|
||||
*/
|
||||
public Location setDirection(Vector direction) {
|
||||
return new Location(extent, position, direction.toYaw(), direction.toPitch());
|
||||
return new Location(extent, this, direction.toYaw(), direction.toPitch());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -242,25 +241,7 @@ public class Location {
|
||||
* @return a vector
|
||||
*/
|
||||
public Vector toVector() {
|
||||
return position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the X component of the position vector.
|
||||
*
|
||||
* @return the X component
|
||||
*/
|
||||
public double getX() {
|
||||
return position.getX();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rounded X component of the position vector.
|
||||
*
|
||||
* @return the rounded X component
|
||||
*/
|
||||
public int getBlockX() {
|
||||
return position.getBlockX();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -271,7 +252,7 @@ public class Location {
|
||||
* @return a new immutable instance
|
||||
*/
|
||||
public Location setX(double x) {
|
||||
return new Location(extent, position.setX(x), yaw, pitch);
|
||||
return new Location(extent, super.setX(x), yaw, pitch);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -282,25 +263,7 @@ public class Location {
|
||||
* @return a new immutable instance
|
||||
*/
|
||||
public Location setX(int x) {
|
||||
return new Location(extent, position.setX(x), yaw, pitch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Y component of the position vector.
|
||||
*
|
||||
* @return the Y component
|
||||
*/
|
||||
public double getY() {
|
||||
return position.getY();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rounded Y component of the position vector.
|
||||
*
|
||||
* @return the rounded Y component
|
||||
*/
|
||||
public int getBlockY() {
|
||||
return position.getBlockY();
|
||||
return new Location(extent, super.setX(x), yaw, pitch);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -311,7 +274,7 @@ public class Location {
|
||||
* @return a new immutable instance
|
||||
*/
|
||||
public Location setY(double y) {
|
||||
return new Location(extent, position.setY(y), yaw, pitch);
|
||||
return new Location(extent, super.setY(y), yaw, pitch);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -322,25 +285,7 @@ public class Location {
|
||||
* @return a new immutable instance
|
||||
*/
|
||||
public Location setY(int y) {
|
||||
return new Location(extent, position.setY(y), yaw, pitch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Z component of the position vector.
|
||||
*
|
||||
* @return the Z component
|
||||
*/
|
||||
public double getZ() {
|
||||
return position.getZ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rounded Z component of the position vector.
|
||||
*
|
||||
* @return the rounded Z component
|
||||
*/
|
||||
public int getBlockZ() {
|
||||
return position.getBlockZ();
|
||||
return new Location(extent, super.setY(y), yaw, pitch);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -351,7 +296,7 @@ public class Location {
|
||||
* @return a new immutable instance
|
||||
*/
|
||||
public Location setZ(double z) {
|
||||
return new Location(extent, position.setZ(z), yaw, pitch);
|
||||
return new Location(extent, super.setZ(z), yaw, pitch);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -362,7 +307,7 @@ public class Location {
|
||||
* @return a new immutable instance
|
||||
*/
|
||||
public Location setZ(int z) {
|
||||
return new Location(extent, position.setZ(z), yaw, pitch);
|
||||
return new Location(extent, super.setZ(z), yaw, pitch);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -384,7 +329,9 @@ public class Location {
|
||||
|
||||
if (Double.doubleToLongBits(pitch) != Double.doubleToLongBits(location.pitch)) return false;
|
||||
if (Double.doubleToLongBits(yaw) != Double.doubleToLongBits(location.yaw)) return false;
|
||||
if (!position.equals(location.position)) return false;
|
||||
if (this.getX() != location.getX()) return false;
|
||||
if (this.getZ() != location.getZ()) return false;
|
||||
if (this.getY() != location.getY()) return false;
|
||||
if (!extent.equals(location.extent)) return false;
|
||||
|
||||
return true;
|
||||
@ -393,7 +340,7 @@ public class Location {
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = extent.hashCode();
|
||||
result = 31 * result + position.hashCode();
|
||||
result = 31 * result + this.hashCode();
|
||||
result = 31 * result + Float.floatToIntBits(this.pitch);
|
||||
result = 31 * result + Float.floatToIntBits(this.yaw);
|
||||
return result;
|
||||
|
@ -21,9 +21,12 @@
|
||||
|
||||
package com.sk89q.worldedit.util;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sk89q.util.StringUtil;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.sk89q.worldedit.world.item.ItemTypes;
|
||||
import com.sk89q.worldedit.world.registry.LegacyMapper;
|
||||
import com.sk89q.worldedit.world.snapshot.SnapshotRepository;
|
||||
|
||||
@ -40,6 +43,7 @@ import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Simple LocalConfiguration that loads settings using
|
||||
@ -75,7 +79,13 @@ public class PropertiesConfiguration extends LocalConfiguration {
|
||||
loadExtra();
|
||||
|
||||
profile = getBool("profile", profile);
|
||||
disallowedBlocks = getStringSet("disallowed-blocks", defaultDisallowedBlocks);
|
||||
|
||||
disallowedBlocks =
|
||||
new HashSet<>(getStringSet("limits.disallowed-blocks", defaultDisallowedBlocks))
|
||||
.stream().map(e -> BlockTypes.parse(e)).collect(Collectors.toSet());
|
||||
allowedDataCycleBlocks =
|
||||
new HashSet<>(getStringSet("limits.allowed-data-cycle-blocks", null))
|
||||
.stream().map(e -> BlockTypes.parse(e)).collect(Collectors.toSet());
|
||||
defaultChangeLimit = getInt("default-max-changed-blocks", defaultChangeLimit);
|
||||
maxChangeLimit = getInt("max-changed-blocks", maxChangeLimit);
|
||||
defaultMaxPolygonalPoints = getInt("default-max-polygon-points", defaultMaxPolygonalPoints);
|
||||
@ -90,22 +100,14 @@ public class PropertiesConfiguration extends LocalConfiguration {
|
||||
logFile = getString("log-file", logFile);
|
||||
logFormat = getString("log-format", logFormat);
|
||||
registerHelp = getBool("register-help", registerHelp);
|
||||
wandItem = getString("wand-item", wandItem);
|
||||
try {
|
||||
wandItem = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(wandItem)).getId();
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
wandItem = ItemTypes.parse(getString("wand-item", wandItem.getId()));
|
||||
superPickaxeDrop = getBool("super-pickaxe-drop-items", superPickaxeDrop);
|
||||
superPickaxeManyDrop = getBool("super-pickaxe-many-drop-items", superPickaxeManyDrop);
|
||||
noDoubleSlash = getBool("no-double-slash", noDoubleSlash);
|
||||
useInventory = getBool("use-inventory", useInventory);
|
||||
useInventoryOverride = getBool("use-inventory-override", useInventoryOverride);
|
||||
useInventoryCreativeOverride = getBool("use-inventory-creative-override", useInventoryCreativeOverride);
|
||||
navigationWand = getString("nav-wand-item", navigationWand);
|
||||
try {
|
||||
navigationWand = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(navigationWand)).getId();
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
navigationWand = ItemTypes.parse(getString("navigation-wand.item", navigationWand.getId()));
|
||||
navigationWandMaxDistance = getInt("nav-wand-distance", navigationWandMaxDistance);
|
||||
navigationUseGlass = getBool("nav-use-glass", navigationUseGlass);
|
||||
scriptTimeout = getInt("scripting-timeout", scriptTimeout);
|
||||
|
@ -19,15 +19,14 @@
|
||||
|
||||
package com.sk89q.worldedit.util;
|
||||
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
/**
|
||||
* This class uses an inefficient method to figure out what block a player
|
||||
* is looking towards.
|
||||
*
|
||||
*
|
||||
* <p>Originally written by toi. It was ported to WorldEdit and trimmed down by
|
||||
* sk89q. Thanks to Raphfrk for optimization of toi's original class.</p>
|
||||
*/
|
||||
@ -43,13 +42,12 @@ public class TargetBlock {
|
||||
|
||||
/**
|
||||
* Constructor requiring a player, uses default values
|
||||
*
|
||||
*
|
||||
* @param player player to work with
|
||||
*/
|
||||
public TargetBlock(Player player) {
|
||||
this.world = player.getWorld();
|
||||
this.setValues(player.getLocation().toVector(), player.getLocation().getYaw(), player.getLocation().getPitch(),
|
||||
300, 1.65, 0.2);
|
||||
this.setValues(player.getLocation().toVector(), player.getLocation().getYaw(), player.getLocation().getPitch(), 300, 1.65, 0.2);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,7 +64,7 @@ public class TargetBlock {
|
||||
|
||||
/**
|
||||
* Set the values, all constructors uses this function
|
||||
*
|
||||
*
|
||||
* @param loc location of the view
|
||||
* @param xRotation the X rotation
|
||||
* @param yRotation the Y rotation
|
||||
@ -74,7 +72,8 @@ public class TargetBlock {
|
||||
* @param viewHeight where the view is positioned in y-axis
|
||||
* @param checkDistance how often to check for blocks, the smaller the more precise
|
||||
*/
|
||||
private void setValues(Vector loc, double xRotation, double yRotation, int maxDistance, double viewHeight, double checkDistance) {
|
||||
private void setValues(Vector loc, double xRotation, double yRotation,
|
||||
int maxDistance, double viewHeight, double checkDistance) {
|
||||
this.maxDistance = maxDistance;
|
||||
this.checkDistance = checkDistance;
|
||||
this.curDistance = 0;
|
||||
@ -84,8 +83,8 @@ public class TargetBlock {
|
||||
double h = (checkDistance * Math.cos(Math.toRadians(yRotation)));
|
||||
|
||||
offset = new Vector((h * Math.cos(Math.toRadians(xRotation))),
|
||||
(checkDistance * Math.sin(Math.toRadians(yRotation))),
|
||||
(h * Math.sin(Math.toRadians(xRotation))));
|
||||
(checkDistance * Math.sin(Math.toRadians(yRotation))),
|
||||
(h * Math.sin(Math.toRadians(xRotation))));
|
||||
|
||||
targetPosDouble = loc.add(0, viewHeight, 0);
|
||||
targetPos = targetPosDouble.toBlockPoint();
|
||||
@ -95,14 +94,14 @@ public class TargetBlock {
|
||||
/**
|
||||
* Returns any block at the sight. Returns null if out of range or if no
|
||||
* viable target was found. Will try to return the last valid air block it finds.
|
||||
*
|
||||
*
|
||||
* @return Block
|
||||
*/
|
||||
public Location getAnyTargetBlock() {
|
||||
boolean searchForLastBlock = true;
|
||||
Location lastBlock = null;
|
||||
while (getNextBlock() != null) {
|
||||
if (world.getBlock(getCurrentBlock().toVector()).getBlockType() == BlockTypes.AIR) {
|
||||
if (world.getLazyBlock(getCurrentBlock().toVector()).getBlockType().getMaterial().isAir()) {
|
||||
if (searchForLastBlock) {
|
||||
lastBlock = getCurrentBlock();
|
||||
if (lastBlock.getBlockY() <= 0 || lastBlock.getBlockY() >= world.getMaxY()) {
|
||||
@ -120,18 +119,18 @@ public class TargetBlock {
|
||||
/**
|
||||
* Returns the block at the sight. Returns null if out of range or if no
|
||||
* viable target was found
|
||||
*
|
||||
*
|
||||
* @return Block
|
||||
*/
|
||||
public Location getTargetBlock() {
|
||||
while (getNextBlock() != null && world.getBlock(getCurrentBlock().toVector()).getBlockType() == BlockTypes.AIR) ;
|
||||
while (getNextBlock() != null && world.getLazyBlock(getCurrentBlock().toVector()).getBlockType().getMaterial().isAir()) ;
|
||||
return getCurrentBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the block at the sight. Returns null if out of range or if no
|
||||
* viable target was found
|
||||
*
|
||||
*
|
||||
* @return Block
|
||||
*/
|
||||
public Location getSolidTargetBlock() {
|
||||
@ -141,7 +140,7 @@ public class TargetBlock {
|
||||
|
||||
/**
|
||||
* Get next block
|
||||
*
|
||||
*
|
||||
* @return next block position
|
||||
*/
|
||||
public Location getNextBlock() {
|
||||
@ -150,8 +149,8 @@ public class TargetBlock {
|
||||
curDistance += checkDistance;
|
||||
|
||||
targetPosDouble = offset.add(targetPosDouble.getX(),
|
||||
targetPosDouble.getY(),
|
||||
targetPosDouble.getZ());
|
||||
targetPosDouble.getY(),
|
||||
targetPosDouble.getZ());
|
||||
targetPos = targetPosDouble.toBlockPoint();
|
||||
} while (curDistance <= maxDistance
|
||||
&& targetPos.getBlockX() == prevPos.getBlockX()
|
||||
@ -167,7 +166,7 @@ public class TargetBlock {
|
||||
|
||||
/**
|
||||
* Returns the current block along the line of vision
|
||||
*
|
||||
*
|
||||
* @return block position
|
||||
*/
|
||||
public Location getCurrentBlock() {
|
||||
@ -180,7 +179,7 @@ public class TargetBlock {
|
||||
|
||||
/**
|
||||
* Returns the previous block in the aimed path
|
||||
*
|
||||
*
|
||||
* @return block position
|
||||
*/
|
||||
public Location getPreviousBlock() {
|
||||
|
@ -23,8 +23,8 @@ import com.google.common.collect.Sets;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
import java.util.Collections;
|
||||
@ -179,8 +179,8 @@ public class TreeGenerator {
|
||||
int trunkHeight = (int) Math.floor(Math.random() * 2) + 3;
|
||||
int height = (int) Math.floor(Math.random() * 5) + 8;
|
||||
|
||||
BlockState logBlock = BlockTypes.OAK_LOG.getDefaultState();
|
||||
BlockState leavesBlock = BlockTypes.OAK_LEAVES.getDefaultState();
|
||||
BlockStateHolder logBlock = BlockTypes.OAK_LOG.getDefaultState();
|
||||
BlockStateHolder leavesBlock = BlockTypes.OAK_LEAVES.getDefaultState();
|
||||
|
||||
// Create trunk
|
||||
for (int i = 0; i < trunkHeight; ++i) {
|
||||
|
@ -24,12 +24,15 @@ import com.sk89q.util.yaml.YAMLProcessor;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.session.SessionManager;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.sk89q.worldedit.world.item.ItemTypes;
|
||||
import com.sk89q.worldedit.world.snapshot.SnapshotRepository;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* A less simple implementation of {@link LocalConfiguration}
|
||||
@ -49,12 +52,13 @@ public class YAMLConfiguration extends LocalConfiguration {
|
||||
public void load() {
|
||||
try {
|
||||
config.load();
|
||||
} catch (IOException e) {
|
||||
} catch (Throwable e) {
|
||||
logger.log(Level.WARNING, "Error loading WorldEdit configuration", e);
|
||||
}
|
||||
|
||||
// TODO FIXME use Config class with comments / bindings
|
||||
profile = config.getBoolean("debug", profile);
|
||||
wandItem = convertLegacyItem(config.getString("wand-item", wandItem));
|
||||
wandItem = ItemTypes.parse(config.getString("wand-item", wandItem.getId()));
|
||||
|
||||
defaultChangeLimit = Math.max(-1, config.getInt(
|
||||
"limits.max-blocks-changed.default", defaultChangeLimit));
|
||||
@ -77,8 +81,12 @@ public class YAMLConfiguration extends LocalConfiguration {
|
||||
butcherDefaultRadius = Math.max(-1, config.getInt("limits.butcher-radius.default", butcherDefaultRadius));
|
||||
butcherMaxRadius = Math.max(-1, config.getInt("limits.butcher-radius.maximum", butcherMaxRadius));
|
||||
|
||||
disallowedBlocks = new HashSet<>(config.getStringList("limits.disallowed-blocks", Lists.newArrayList(defaultDisallowedBlocks)));
|
||||
allowedDataCycleBlocks = new HashSet<>(config.getStringList("limits.allowed-data-cycle-blocks", null));
|
||||
disallowedBlocks =
|
||||
new HashSet<>(config.getStringList("limits.disallowed-blocks", Lists.newArrayList(defaultDisallowedBlocks)))
|
||||
.stream().map(e -> BlockTypes.parse(e)).collect(Collectors.toSet());
|
||||
allowedDataCycleBlocks =
|
||||
new HashSet<>(config.getStringList("limits.allowed-data-cycle-blocks", null))
|
||||
.stream().map(e -> BlockTypes.parse(e)).collect(Collectors.toSet());
|
||||
|
||||
registerHelp = config.getBoolean("register-help", true);
|
||||
logCommands = config.getBoolean("logging.log-commands", logCommands);
|
||||
@ -98,7 +106,7 @@ public class YAMLConfiguration extends LocalConfiguration {
|
||||
useInventoryCreativeOverride = config.getBoolean("use-inventory.creative-mode-overrides",
|
||||
useInventoryCreativeOverride);
|
||||
|
||||
navigationWand = convertLegacyItem(config.getString("navigation-wand.item", navigationWand));
|
||||
navigationWand = ItemTypes.parse(config.getString("navigation-wand.item", navigationWand.getId()));
|
||||
navigationWandMaxDistance = config.getInt("navigation-wand.max-distance", navigationWandMaxDistance);
|
||||
navigationUseGlass = config.getBoolean("navigation.use-glass", navigationUseGlass);
|
||||
|
||||
|
@ -19,11 +19,11 @@
|
||||
|
||||
package com.sk89q.worldedit.util.collection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Iterator;
|
||||
import java.util.ListIterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
|
@ -19,13 +19,13 @@
|
||||
|
||||
package com.sk89q.worldedit.util.collection;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* A fast iterator for lists that uses an internal index integer
|
||||
* and caches the size of the list. The size of the list cannot change
|
||||
|
@ -0,0 +1,12 @@
|
||||
package com.sk89q.worldedit.util.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
|
||||
public interface CallableProcessor<T> {
|
||||
public Object process(CommandLocals locals, T value) throws CommandException, WorldEditException;
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package com.sk89q.worldedit.util.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import java.util.List;
|
||||
|
||||
public class DelegateCallable implements CommandCallable {
|
||||
private final CommandCallable parent;
|
||||
|
||||
public CommandCallable getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public DelegateCallable(CommandCallable parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object call(String arguments, CommandLocals locals, String[] parentCommands) throws CommandException {
|
||||
return parent.call(arguments, locals, parentCommands);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Description getDescription() {
|
||||
return parent.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testPermission(CommandLocals locals) {
|
||||
return parent.testPermission(locals);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException {
|
||||
return parent.getSuggestions(arguments, locals);
|
||||
}
|
||||
}
|
@ -19,11 +19,10 @@
|
||||
|
||||
package com.sk89q.worldedit.util.command;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Executes a command based on user input.
|
||||
*/
|
||||
|
@ -19,12 +19,12 @@
|
||||
|
||||
package com.sk89q.worldedit.util.command;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Thrown when a command is not used properly.
|
||||
*
|
||||
|
@ -19,11 +19,10 @@
|
||||
|
||||
package com.sk89q.worldedit.util.command;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Comparator;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Compares the primary aliases of two {@link CommandMapping} using
|
||||
* {@link String#compareTo(String)}.
|
||||
|
@ -0,0 +1,27 @@
|
||||
package com.sk89q.worldedit.util.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class ProcessedCallable extends DelegateCallable {
|
||||
private final CallableProcessor processor;
|
||||
|
||||
public ProcessedCallable(CommandCallable parent, CallableProcessor processor) {
|
||||
super(parent);
|
||||
checkNotNull(processor);
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object call(String arguments, CommandLocals locals, String[] parentCommands) throws CommandException {
|
||||
try {
|
||||
return processor.process(locals, super.call(arguments, locals, parentCommands));
|
||||
} catch (WorldEditException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -19,19 +19,21 @@
|
||||
|
||||
package com.sk89q.worldedit.util.command;
|
||||
|
||||
import com.sk89q.worldedit.util.command.parametric.ParametricCallable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Tracks a command registration.
|
||||
*/
|
||||
public class SimpleCommandMapping implements CommandMapping {
|
||||
|
||||
|
||||
private final String[] aliases;
|
||||
private final CommandCallable callable;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
*
|
||||
* @param callable the command callable
|
||||
* @param alias a list of all aliases, where the first one is the primary one
|
||||
*/
|
||||
@ -45,12 +47,12 @@ public class SimpleCommandMapping implements CommandMapping {
|
||||
public String getPrimaryAlias() {
|
||||
return aliases[0];
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String[] getAllAliases() {
|
||||
return aliases;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CommandCallable getCallable() {
|
||||
return callable;
|
||||
@ -61,6 +63,30 @@ public class SimpleCommandMapping implements CommandMapping {
|
||||
return getCallable().getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getPrimaryAlias().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null || !(obj instanceof CommandMapping)) {
|
||||
return false;
|
||||
}
|
||||
CommandMapping other = (CommandMapping) obj;
|
||||
if (other.getCallable() != getCallable()) {
|
||||
if (other.getCallable().getClass() != getCallable().getClass() || !(getCallable() instanceof ParametricCallable)) {
|
||||
return false;
|
||||
}
|
||||
Method oMeth = ((ParametricCallable) other.getCallable()).getMethod();
|
||||
Method meth = ((ParametricCallable) getCallable()).getMethod();
|
||||
if (!oMeth.equals(meth)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return other.getPrimaryAlias().equals(getPrimaryAlias());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CommandMapping{" +
|
||||
@ -69,4 +95,8 @@ public class SimpleCommandMapping implements CommandMapping {
|
||||
'}';
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return SimpleCommandMapping.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,13 +19,13 @@
|
||||
|
||||
package com.sk89q.worldedit.util.command;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.util.StringMan;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
|
||||
import com.sk89q.minecraft.util.commands.WrappedCommandException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@ -40,7 +40,7 @@ import java.util.Set;
|
||||
*/
|
||||
public class SimpleDispatcher implements Dispatcher {
|
||||
|
||||
private final Map<String, CommandMapping> commands = new HashMap<>();
|
||||
private final Map<String, CommandMapping> commands = new HashMap<String, CommandMapping>();
|
||||
private final SimpleDescription description = new SimpleDescription();
|
||||
|
||||
/**
|
||||
@ -56,35 +56,42 @@ public class SimpleDispatcher implements Dispatcher {
|
||||
@Override
|
||||
public void registerCommand(CommandCallable callable, String... alias) {
|
||||
CommandMapping mapping = new SimpleCommandMapping(callable, alias);
|
||||
|
||||
|
||||
// Check for replacements
|
||||
for (String a : alias) {
|
||||
String lower = a.toLowerCase();
|
||||
if (commands.containsKey(lower)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Replacing commands is currently undefined behavior");
|
||||
CommandMapping existing = commands.get(lower);
|
||||
if (existing != null) {
|
||||
CommandCallable existingCallable = existing.getCallable();
|
||||
if (existingCallable instanceof Dispatcher && callable instanceof Dispatcher) {
|
||||
Dispatcher existingDispatcher = (Dispatcher) existingCallable;
|
||||
Dispatcher newDispatcher = (Dispatcher) callable;
|
||||
for (CommandMapping add : newDispatcher.getCommands()) {
|
||||
existingDispatcher.registerCommand(add.getCallable(), add.getAllAliases());
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
Fawe.debug("Replacing commands is currently undefined behavior: " + StringMan.getString(alias));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String a : alias) {
|
||||
String lower = a.toLowerCase();
|
||||
commands.put(lower, mapping);
|
||||
commands.putIfAbsent(lower, mapping);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<CommandMapping> getCommands() {
|
||||
return Collections.unmodifiableSet(new HashSet<>(commands.values()));
|
||||
return Collections.unmodifiableSet(new HashSet<CommandMapping>(commands.values()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Set<String> getAliases() {
|
||||
return Collections.unmodifiableSet(commands.keySet());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Set<String> getPrimaryAliases() {
|
||||
Set<String> aliases = new HashSet<>();
|
||||
Set<String> aliases = new HashSet<String>();
|
||||
for (CommandMapping mapping : getCommands()) {
|
||||
aliases.add(mapping.getPrimaryAlias());
|
||||
}
|
||||
@ -108,7 +115,7 @@ public class SimpleDispatcher implements Dispatcher {
|
||||
throw new CommandPermissionsException();
|
||||
}
|
||||
|
||||
String[] split = CommandContext.split(arguments);
|
||||
String[] split = arguments.split(" ", -1);
|
||||
Set<String> aliases = getPrimaryAliases();
|
||||
|
||||
if (aliases.isEmpty()) {
|
||||
@ -138,12 +145,12 @@ public class SimpleDispatcher implements Dispatcher {
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException {
|
||||
String[] split = CommandContext.split(arguments);
|
||||
String[] split = arguments.split(" ", -1);
|
||||
|
||||
if (split.length <= 1) {
|
||||
String prefix = split.length > 0 ? split[0] : "";
|
||||
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
List<String> suggestions = new ArrayList<String>();
|
||||
|
||||
for (CommandMapping mapping : getCommands()) {
|
||||
if (mapping.getCallable().testPermission(locals)) {
|
||||
@ -177,13 +184,12 @@ public class SimpleDispatcher implements Dispatcher {
|
||||
|
||||
@Override
|
||||
public boolean testPermission(CommandLocals locals) {
|
||||
for (CommandMapping mapping : getCommands()) {
|
||||
if (mapping.getCallable().testPermission(locals)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
// Checking every perm in the class here was unnecessarily stupid
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
public static Class<SimpleDispatcher> inject() {
|
||||
return SimpleDispatcher.class;
|
||||
}
|
||||
|
||||
}
|
@ -28,9 +28,8 @@ import com.sk89q.worldedit.util.command.parametric.BindingHelper;
|
||||
import com.sk89q.worldedit.util.command.parametric.BindingMatch;
|
||||
import com.sk89q.worldedit.util.command.parametric.ParameterException;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
/**
|
||||
* Handles basic Java types such as {@link String}s, {@link Byte}s, etc.
|
||||
|
@ -25,16 +25,15 @@ import com.google.common.collect.Maps;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.util.command.argument.CommandArgs;
|
||||
import com.sk89q.worldedit.util.command.argument.MissingArgumentException;
|
||||
import com.sk89q.worldedit.util.command.composition.FlagParser.FlagData;
|
||||
import com.sk89q.worldedit.util.command.argument.MissingArgumentException;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class FlagParser implements CommandExecutor<FlagData> {
|
||||
|
||||
private final Map<Character, CommandExecutor<?>> flags = Maps.newHashMap();
|
||||
|
@ -19,10 +19,15 @@
|
||||
|
||||
package com.sk89q.worldedit.util.command.fluent;
|
||||
|
||||
import com.boydti.fawe.config.Commands;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.worldedit.util.command.CallableProcessor;
|
||||
import com.sk89q.worldedit.util.command.CommandCallable;
|
||||
import com.sk89q.worldedit.util.command.Dispatcher;
|
||||
import com.sk89q.worldedit.util.command.SimpleDispatcher;
|
||||
import com.sk89q.worldedit.util.command.parametric.ParametricBuilder;
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
/**
|
||||
* A collection of commands.
|
||||
@ -32,27 +37,27 @@ public class DispatcherNode {
|
||||
private final CommandGraph graph;
|
||||
private final DispatcherNode parent;
|
||||
private final SimpleDispatcher dispatcher;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param graph the root fluent graph object
|
||||
* @param parent the parent node, or null
|
||||
*
|
||||
* @param graph the root fluent graph object
|
||||
* @param parent the parent node, or null
|
||||
* @param dispatcher the dispatcher for this node
|
||||
*/
|
||||
DispatcherNode(CommandGraph graph, DispatcherNode parent,
|
||||
SimpleDispatcher dispatcher) {
|
||||
public DispatcherNode(CommandGraph graph, DispatcherNode parent,
|
||||
SimpleDispatcher dispatcher) {
|
||||
this.graph = graph;
|
||||
this.parent = parent;
|
||||
this.dispatcher = dispatcher;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the description.
|
||||
*
|
||||
* <p>
|
||||
* <p>This can only be used on {@link DispatcherNode}s returned by
|
||||
* {@link #group(String...)}.</p>
|
||||
*
|
||||
*
|
||||
* @param description the description
|
||||
* @return this object
|
||||
*/
|
||||
@ -63,9 +68,9 @@ public class DispatcherNode {
|
||||
|
||||
/**
|
||||
* Register a command with this dispatcher.
|
||||
*
|
||||
*
|
||||
* @param callable the executor
|
||||
* @param alias the list of aliases, where the first alias is the primary one
|
||||
* @param alias the list of aliases, where the first alias is the primary one
|
||||
*/
|
||||
public DispatcherNode register(CommandCallable callable, String... alias) {
|
||||
dispatcher.registerCommand(callable, alias);
|
||||
@ -73,40 +78,90 @@ public class DispatcherNode {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and register a command with this dispatcher using the
|
||||
* Build and register a command with this dispatcher using the
|
||||
* {@link ParametricBuilder} assigned on the root {@link CommandGraph}.
|
||||
*
|
||||
*
|
||||
* @param object the object provided to the {@link ParametricBuilder}
|
||||
* @return this object
|
||||
* @see ParametricBuilder#registerMethodsAsCommands(com.sk89q.worldedit.util.command.Dispatcher, Object)
|
||||
*/
|
||||
public DispatcherNode registerMethods(Object object) {
|
||||
return registerMethods(object, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and register a command with this dispatcher using the
|
||||
* {@link ParametricBuilder} assigned on the root {@link CommandGraph}.
|
||||
*
|
||||
* @param object the object provided to the {@link ParametricBuilder}
|
||||
* @return this object
|
||||
* @see ParametricBuilder#registerMethodsAsCommands(com.sk89q.worldedit.util.command.Dispatcher, Object)
|
||||
*/
|
||||
public DispatcherNode registerMethods(Object object, @Nullable CallableProcessor processor) {
|
||||
ParametricBuilder builder = graph.getBuilder();
|
||||
if (builder == null) {
|
||||
throw new RuntimeException("No ParametricBuilder set");
|
||||
}
|
||||
builder.registerMethodsAsCommands(getDispatcher(), object);
|
||||
builder.registerMethodsAsCommands(getDispatcher(), object, processor);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build and register sub commands with this dispatcher using the
|
||||
* {@link ParametricBuilder} assigned on the objects registered command aliases {@link com.sk89q.minecraft.util.commands.Command}.
|
||||
*
|
||||
* @param object the object provided to the {@link ParametricBuilder}
|
||||
* @return this object
|
||||
*/
|
||||
public DispatcherNode registerSubMethods(Object object) {
|
||||
return registerSubMethods(object, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and register sub commands with this dispatcher using the
|
||||
* {@link ParametricBuilder} assigned on the objects registered command aliases {@link com.sk89q.minecraft.util.commands.Command}.
|
||||
*
|
||||
* @param object the object provided to the {@link ParametricBuilder}
|
||||
* @param processor the command processor
|
||||
* @return this object
|
||||
*/
|
||||
public DispatcherNode registerSubMethods(Object object, @Nullable CallableProcessor processor) {
|
||||
Class<? extends Object> clazz = object.getClass();
|
||||
return groupAndDescribe(clazz).registerMethods(object, processor).parent();
|
||||
}
|
||||
|
||||
public DispatcherNode groupAndDescribe(Class clazz) {
|
||||
Command cmd = (Command) clazz.getAnnotation(Command.class);
|
||||
if (cmd == null) {
|
||||
throw new RuntimeException("This class does not have any command annotations");
|
||||
}
|
||||
cmd = Commands.translate(clazz, cmd);
|
||||
DispatcherNode res = group(cmd.aliases());
|
||||
if (cmd.desc() != null && !cmd.desc().isEmpty()) {
|
||||
res = res.describeAs(cmd.desc());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new command that will contain sub-commands.
|
||||
*
|
||||
* <p>
|
||||
* <p>The object returned by this method can be used to add sub-commands. To
|
||||
* return to this "parent" context, use {@link DispatcherNode#graph()}.</p>
|
||||
*
|
||||
*
|
||||
* @param alias the list of aliases, where the first alias is the primary one
|
||||
* @return an object to place sub-commands
|
||||
*/
|
||||
public DispatcherNode group(String... alias) {
|
||||
SimpleDispatcher command = new SimpleDispatcher();
|
||||
getDispatcher().registerCommand(command, alias);
|
||||
return new DispatcherNode(graph, this, command);
|
||||
DispatcherNode res = new DispatcherNode(graph, this, command);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the parent node.
|
||||
*
|
||||
*
|
||||
* @return the parent node
|
||||
* @throws RuntimeException if there is no parent node.
|
||||
*/
|
||||
@ -114,26 +169,29 @@ public class DispatcherNode {
|
||||
if (parent != null) {
|
||||
return parent;
|
||||
}
|
||||
|
||||
|
||||
throw new RuntimeException("This node does not have a parent");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the root command graph.
|
||||
*
|
||||
*
|
||||
* @return the root command graph
|
||||
*/
|
||||
public CommandGraph graph() {
|
||||
return graph;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the underlying dispatcher of this object.
|
||||
*
|
||||
*
|
||||
* @return the dispatcher
|
||||
*/
|
||||
public Dispatcher getDispatcher() {
|
||||
return dispatcher;
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return DispatcherNode.class;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,296 @@
|
||||
package com.sk89q.worldedit.util.command.parametric;
|
||||
|
||||
import com.boydti.fawe.command.SuggestInputParseException;
|
||||
import com.sk89q.minecraft.util.commands.*;
|
||||
import com.sk89q.worldedit.util.command.*;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class AParametricCallable implements CommandCallable {
|
||||
// private final ParametricBuilder builder;
|
||||
// private ParameterData[] parameters;
|
||||
// private Set<Character> valueFlags = new HashSet<Character>();
|
||||
// private boolean anyFlags;
|
||||
// private Set<Character> legacyFlags = new HashSet<Character>();
|
||||
// private SimpleDescription description = new SimpleDescription();
|
||||
// private String permission;
|
||||
// private Command command;
|
||||
|
||||
public abstract ParameterData[] getParameters();
|
||||
public abstract Set<Character> getValueFlags();
|
||||
public abstract Set<Character> getLegacyFlags();
|
||||
public abstract SimpleDescription getDescription();
|
||||
public abstract String[] getPermissions();
|
||||
public abstract ParametricBuilder getBuilder();
|
||||
public abstract boolean anyFlags();
|
||||
public abstract Command getCommand();
|
||||
public abstract String getGroup();
|
||||
@Override
|
||||
public abstract String toString();
|
||||
|
||||
/**
|
||||
* Get the right {@link ArgumentStack}.
|
||||
*
|
||||
* @param parameter the parameter
|
||||
* @param existing the existing scoped context
|
||||
* @return the context to use
|
||||
*/
|
||||
public static ArgumentStack getScopedContext(Parameter parameter, ArgumentStack existing) {
|
||||
if (parameter.getFlag() != null) {
|
||||
CommandContext context = existing.getContext();
|
||||
|
||||
if (parameter.isValueFlag()) {
|
||||
return new StringArgumentStack(context, context.getFlag(parameter.getFlag()), false);
|
||||
} else {
|
||||
String v = context.hasFlag(parameter.getFlag()) ? "true" : "false";
|
||||
return new StringArgumentStack(context, v, true);
|
||||
}
|
||||
}
|
||||
|
||||
return existing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether a parameter is allowed to consume arguments.
|
||||
*
|
||||
* @param i the index of the parameter
|
||||
* @param scoped the scoped context
|
||||
* @return true if arguments may be consumed
|
||||
*/
|
||||
public boolean mayConsumeArguments(int i, ContextArgumentStack scoped) {
|
||||
CommandContext context = scoped.getContext();
|
||||
ParameterData parameter = getParameters()[i];
|
||||
|
||||
// Flag parameters: Always consume
|
||||
// Required non-flag parameters: Always consume
|
||||
// Optional non-flag parameters:
|
||||
// - Before required parameters: Consume if there are 'left over' args
|
||||
// - At the end: Always consumes
|
||||
|
||||
if (parameter.isOptional()) {
|
||||
if (parameter.getFlag() != null) {
|
||||
return !parameter.isValueFlag() || context.hasFlag(parameter.getFlag());
|
||||
} else {
|
||||
int numberFree = context.argsLength() - scoped.position();
|
||||
for (int j = i; j < getParameters().length; j++) {
|
||||
if (getParameters()[j].isNonFlagConsumer() && !getParameters()[j].isOptional()) {
|
||||
// We already checked if the consumed count was > -1
|
||||
// when we created this object
|
||||
numberFree -= getParameters()[j].getConsumedCount();
|
||||
}
|
||||
}
|
||||
|
||||
// Skip this optional parameter
|
||||
if (numberFree < 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default value for a parameter.
|
||||
*
|
||||
* @param i the index of the parameter
|
||||
* @param scoped the scoped context
|
||||
* @return a value
|
||||
* @throws ParameterException on an error
|
||||
* @throws CommandException on an error
|
||||
*/
|
||||
public Object getDefaultValue(int i, ContextArgumentStack scoped) throws ParameterException, CommandException, InvocationTargetException {
|
||||
CommandContext context = scoped.getContext();
|
||||
ParameterData parameter = getParameters()[i];
|
||||
|
||||
String[] defaultValue = parameter.getDefaultValue();
|
||||
if (defaultValue != null) {
|
||||
try {
|
||||
return parameter.getBinding().bind(parameter, new StringArgumentStack(context, defaultValue, false), false);
|
||||
} catch (MissingParameterException e) {
|
||||
throw new ParametricException(
|
||||
"The default value of the parameter using the binding " +
|
||||
parameter.getBinding().getClass() + " in the method\n" +
|
||||
toString() + "\nis invalid");
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check to see if all arguments, including flag arguments, were consumed.
|
||||
*
|
||||
* @param scoped the argument scope
|
||||
* @throws UnconsumedParameterException thrown if parameters were not consumed
|
||||
*/
|
||||
public void checkUnconsumed(ContextArgumentStack scoped) throws UnconsumedParameterException {
|
||||
CommandContext context = scoped.getContext();
|
||||
String unconsumed;
|
||||
String unconsumedFlags = getUnusedFlags(context);
|
||||
|
||||
if ((unconsumed = scoped.getUnconsumed()) != null) {
|
||||
throw new UnconsumedParameterException(unconsumed + " " + unconsumedFlags);
|
||||
}
|
||||
|
||||
if (unconsumedFlags != null) {
|
||||
throw new UnconsumedParameterException(unconsumedFlags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any unused flag arguments.
|
||||
*
|
||||
* @param context the command context
|
||||
*/
|
||||
public String getUnusedFlags(CommandContext context) {
|
||||
if (!anyFlags()) {
|
||||
Set<Character> unusedFlags = null;
|
||||
for (char flag : context.getFlags()) {
|
||||
boolean found = false;
|
||||
|
||||
if (getLegacyFlags().contains(flag)) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (ParameterData parameter : getParameters()) {
|
||||
Character paramFlag = parameter.getFlag();
|
||||
if (paramFlag != null && flag == paramFlag) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
if (unusedFlags == null) {
|
||||
unusedFlags = new HashSet<Character>();
|
||||
}
|
||||
unusedFlags.add(flag);
|
||||
}
|
||||
}
|
||||
|
||||
if (unusedFlags != null) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (Character flag : unusedFlags) {
|
||||
builder.append("-").append(flag).append(" ");
|
||||
}
|
||||
|
||||
return builder.toString().trim();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testPermission(CommandLocals locals) {
|
||||
String[] perms = getPermissions();
|
||||
if (perms != null && perms.length != 0) {
|
||||
for (String perm : perms) {
|
||||
if (getBuilder().getAuthorizer().testPermission(locals, perm)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException {
|
||||
String[] split = ("ignored" + " " + arguments).split(" ", -1);
|
||||
CommandContext context = new CommandContext(split, getValueFlags(), !arguments.endsWith(" "), locals);
|
||||
ContextArgumentStack scoped = new ContextArgumentStack(context);
|
||||
SuggestionContext suggestable = context.getSuggestionContext();
|
||||
|
||||
|
||||
// For /command -f |
|
||||
// For /command -f flag|
|
||||
if (suggestable.forFlag()) {
|
||||
for (int i = 0; i < getParameters().length; i++) {
|
||||
ParameterData parameter = getParameters()[i];
|
||||
|
||||
if (parameter.getFlag() == suggestable.getFlag()) {
|
||||
String prefix = context.getFlag(parameter.getFlag());
|
||||
if (prefix == null) {
|
||||
prefix = "";
|
||||
}
|
||||
|
||||
return parameter.getBinding().getSuggestions(parameter, prefix);
|
||||
}
|
||||
}
|
||||
|
||||
// This should not happen
|
||||
return new ArrayList<String>();
|
||||
}
|
||||
|
||||
int consumerIndex = 0;
|
||||
ParameterData lastConsumer = null;
|
||||
String lastConsumed = null;
|
||||
|
||||
for (int i = 0; i < getParameters().length; i++) {
|
||||
ParameterData parameter = getParameters()[i];
|
||||
if (parameter.getFlag() != null) {
|
||||
continue; // We already handled flags
|
||||
}
|
||||
|
||||
try {
|
||||
scoped.mark();
|
||||
parameter.getBinding().bind(parameter, scoped, true);
|
||||
if (scoped.wasConsumed()) {
|
||||
lastConsumer = parameter;
|
||||
lastConsumed = context.getString(scoped.position() - 1);
|
||||
consumerIndex++;
|
||||
}
|
||||
} catch (MissingParameterException e) {
|
||||
// For /command value1 |value2
|
||||
// For /command |value1 value2
|
||||
if (suggestable.forHangingValue()) {
|
||||
return parameter.getBinding().getSuggestions(parameter, "");
|
||||
} else {
|
||||
// For /command value1| value2
|
||||
if (lastConsumer != null) {
|
||||
return lastConsumer.getBinding().getSuggestions(lastConsumer, lastConsumed);
|
||||
// For /command| value1 value2
|
||||
// This should never occur
|
||||
} else {
|
||||
throw new RuntimeException("Invalid suggestion context");
|
||||
}
|
||||
}
|
||||
} catch (ParameterException | InvocationTargetException e) {
|
||||
SuggestInputParseException suggestion = SuggestInputParseException.get(e);
|
||||
if (suggestion != null) {
|
||||
return suggestion.getSuggestions();
|
||||
}
|
||||
if (suggestable.forHangingValue()) {
|
||||
String name = getDescription().getParameters().get(consumerIndex).getName();
|
||||
throw new InvalidUsageException("For parameter '" + name + "': " + e.getMessage(), this);
|
||||
} else {
|
||||
return parameter.getBinding().getSuggestions(parameter, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
// For /command value1 value2 |
|
||||
if (suggestable.forHangingValue()) {
|
||||
// There's nothing that we can suggest because there's no more parameters
|
||||
// to add on, and we can't change the previous parameter
|
||||
return new ArrayList<String>();
|
||||
} else {
|
||||
// For /command value1 value2|
|
||||
if (lastConsumer != null) {
|
||||
return lastConsumer.getBinding().getSuggestions(lastConsumer, lastConsumed);
|
||||
// This should never occur
|
||||
} else {
|
||||
throw new RuntimeException("Invalid suggestion context");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ public interface ArgumentStack {
|
||||
|
||||
/**
|
||||
* Get the next string, which may come from the stack or a value flag.
|
||||
*
|
||||
*
|
||||
* @return the value
|
||||
* @throws ParameterException on a parameter error
|
||||
*/
|
||||
@ -33,7 +33,7 @@ public interface ArgumentStack {
|
||||
|
||||
/**
|
||||
* Get the next integer, which may come from the stack or a value flag.
|
||||
*
|
||||
*
|
||||
* @return the value
|
||||
* @throws ParameterException on a parameter error
|
||||
*/
|
||||
@ -41,7 +41,7 @@ public interface ArgumentStack {
|
||||
|
||||
/**
|
||||
* Get the next double, which may come from the stack or a value flag.
|
||||
*
|
||||
*
|
||||
* @return the value
|
||||
* @throws ParameterException on a parameter error
|
||||
*/
|
||||
@ -49,7 +49,7 @@ public interface ArgumentStack {
|
||||
|
||||
/**
|
||||
* Get the next boolean, which may come from the stack or a value flag.
|
||||
*
|
||||
*
|
||||
* @return the value
|
||||
* @throws ParameterException on a parameter error
|
||||
*/
|
||||
@ -57,7 +57,7 @@ public interface ArgumentStack {
|
||||
|
||||
/**
|
||||
* Get all remaining string values, which will consume the rest of the stack.
|
||||
*
|
||||
*
|
||||
* @return the value
|
||||
* @throws ParameterException on a parameter error
|
||||
*/
|
||||
@ -70,9 +70,29 @@ public interface ArgumentStack {
|
||||
|
||||
/**
|
||||
* Get the underlying context.
|
||||
*
|
||||
*
|
||||
* @return the context
|
||||
*/
|
||||
CommandContext getContext();
|
||||
|
||||
/**
|
||||
* Mark the current position of the stack.
|
||||
*
|
||||
* <p>The marked position initially starts at 0.</p>
|
||||
*/
|
||||
void mark();
|
||||
|
||||
/**
|
||||
* Reset to the previously {@link #mark()}ed position of the stack, and return
|
||||
* the arguments that were consumed between this point and that previous point.
|
||||
*
|
||||
* <p>The marked position initially starts at 0.</p>
|
||||
*
|
||||
* @return the consumed arguments
|
||||
*/
|
||||
String reset();
|
||||
|
||||
static Class<ArgumentStack> inject0() {
|
||||
return ArgumentStack.class;
|
||||
}
|
||||
}
|
@ -25,24 +25,24 @@ import com.sk89q.worldedit.util.command.MissingParameterException;
|
||||
/**
|
||||
* Makes an instance of a {@link CommandContext} into a stack of arguments
|
||||
* that can be consumed.
|
||||
*
|
||||
*
|
||||
* @see ParametricBuilder a user of this class
|
||||
*/
|
||||
public class ContextArgumentStack implements ArgumentStack {
|
||||
|
||||
|
||||
private final CommandContext context;
|
||||
private int index = 0;
|
||||
private int markedIndex = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance using the given context.
|
||||
*
|
||||
*
|
||||
* @param context the context
|
||||
*/
|
||||
public ContextArgumentStack(CommandContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String next() throws ParameterException {
|
||||
try {
|
||||
@ -94,14 +94,14 @@ public class ContextArgumentStack implements ArgumentStack {
|
||||
|
||||
/**
|
||||
* Get the unconsumed arguments left over, without touching the stack.
|
||||
*
|
||||
*
|
||||
* @return the unconsumed arguments
|
||||
*/
|
||||
public String getUnconsumed() {
|
||||
if (index >= context.argsLength()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return context.getJoinedStrings(index);
|
||||
}
|
||||
|
||||
@ -112,42 +112,44 @@ public class ContextArgumentStack implements ArgumentStack {
|
||||
|
||||
/**
|
||||
* Return the current position.
|
||||
*
|
||||
*
|
||||
* @return the position
|
||||
*/
|
||||
public int position() {
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mark the current position of the stack.
|
||||
*
|
||||
*
|
||||
* <p>The marked position initially starts at 0.</p>
|
||||
*/
|
||||
@Override
|
||||
public void mark() {
|
||||
markedIndex = index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reset to the previously {@link #mark()}ed position of the stack, and return
|
||||
* the arguments that were consumed between this point and that previous point.
|
||||
*
|
||||
*
|
||||
* <p>The marked position initially starts at 0.</p>
|
||||
*
|
||||
*
|
||||
* @return the consumed arguments
|
||||
*/
|
||||
@Override
|
||||
public String reset() {
|
||||
String value = context.getString(markedIndex, index);
|
||||
String value = context.getString(markedIndex, index - 1);
|
||||
index = markedIndex;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return whether any arguments were consumed between the marked position
|
||||
* and the current position.
|
||||
*
|
||||
*
|
||||
* <p>The marked position initially starts at 0.</p>
|
||||
*
|
||||
*
|
||||
* @return true if values were consumed.
|
||||
*/
|
||||
public boolean wasConsumed() {
|
||||
@ -156,18 +158,18 @@ public class ContextArgumentStack implements ArgumentStack {
|
||||
|
||||
/**
|
||||
* Return the arguments that were consumed between this point and that marked point.
|
||||
*
|
||||
*
|
||||
* <p>The marked position initially starts at 0.</p>
|
||||
*
|
||||
*
|
||||
* @return the consumed arguments
|
||||
*/
|
||||
public String getConsumed() {
|
||||
return context.getString(markedIndex, index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the underlying context.
|
||||
*
|
||||
*
|
||||
* @return the context
|
||||
*/
|
||||
@Override
|
||||
@ -175,4 +177,8 @@ public class ContextArgumentStack implements ArgumentStack {
|
||||
return context;
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return ContextArgumentStack.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,76 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 2007 Paul Hammant
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.thoughtworks.paranamer;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Parameter;
|
||||
|
||||
/**
|
||||
* Default implementation of Paranamer reads from a post-compile added field called '__PARANAMER_DATA'
|
||||
*
|
||||
* @author Paul Hammant
|
||||
* @author Mauro Talevi
|
||||
* @author Guilherme Silveira
|
||||
*/
|
||||
public class FaweParanamer extends CachingParanamer {
|
||||
|
||||
@Override
|
||||
public String[] lookupParameterNames(AccessibleObject methodOrConstructor, boolean throwExceptionIfMissing) {
|
||||
Parameter[] params;
|
||||
if (methodOrConstructor instanceof Constructor) {
|
||||
params = ((Constructor) methodOrConstructor).getParameters();
|
||||
} else if (methodOrConstructor instanceof Method) {
|
||||
params = ((Method) methodOrConstructor).getParameters();
|
||||
} else {
|
||||
return super.lookupParameterNames(methodOrConstructor, throwExceptionIfMissing);
|
||||
}
|
||||
String[] names = new String[params.length];
|
||||
String[] defNames = null;
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
Parameter param = params[i];
|
||||
if (param.isNamePresent()) {
|
||||
names[i] = param.getName();
|
||||
} else {
|
||||
if (defNames == null) {
|
||||
defNames = super.lookupParameterNames(methodOrConstructor, throwExceptionIfMissing);
|
||||
if (defNames.length == 0)
|
||||
return defNames;
|
||||
}
|
||||
names[i] = defNames[i];
|
||||
}
|
||||
}
|
||||
return names;
|
||||
}
|
||||
}
|
@ -0,0 +1,310 @@
|
||||
package com.sk89q.worldedit.util.command.parametric;
|
||||
|
||||
import com.boydti.fawe.util.StringMan;
|
||||
import com.google.common.primitives.Chars;
|
||||
import com.sk89q.minecraft.util.commands.*;
|
||||
import com.sk89q.worldedit.util.command.*;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class FunctionParametricCallable extends AParametricCallable {
|
||||
|
||||
private final ParametricBuilder builder;
|
||||
private final ParameterData[] parameters;
|
||||
private final Set<Character> valueFlags = new HashSet<Character>();
|
||||
private final boolean anyFlags;
|
||||
private final Set<Character> legacyFlags = new HashSet<Character>();
|
||||
private final SimpleDescription description = new SimpleDescription();
|
||||
private final String permission;
|
||||
private final Command command;
|
||||
private final Function<Object[], ?> function;
|
||||
private final String group;
|
||||
|
||||
public FunctionParametricCallable(ParametricBuilder builder, String group, Command command, String permission, List<String> arguments, Function<Object[], ?> function) {
|
||||
this.command = command;
|
||||
this.permission = permission;
|
||||
this.builder = builder;
|
||||
this.function = function;
|
||||
this.group = group;
|
||||
|
||||
List<String> paramNames = new ArrayList<>();
|
||||
List<String> typeStrings = new ArrayList<>();
|
||||
List<Type> types = new ArrayList<>();
|
||||
{
|
||||
boolean checkType = false;
|
||||
for (String argument : arguments) {
|
||||
if (checkType) {
|
||||
typeStrings.set(typeStrings.size() - 1, argument);
|
||||
} else {
|
||||
checkType = false;
|
||||
if (argument.equals("=")) {
|
||||
checkType = true;
|
||||
} else if (argument.length() == 1 && command.flags().contains(argument)) {
|
||||
typeStrings.add("java.lang.Boolean");
|
||||
paramNames.add(argument);
|
||||
} else {
|
||||
typeStrings.add("java.lang.String");
|
||||
paramNames.add(argument);
|
||||
}
|
||||
}
|
||||
}
|
||||
Map<Type, Binding> bindings = builder.getBindings();
|
||||
Map<String, Type> unqualified = new HashMap<>();
|
||||
for (Map.Entry<Type, Binding> entry : bindings.entrySet()) {
|
||||
Type type = entry.getKey();
|
||||
String typeStr = type.getTypeName();
|
||||
unqualified.put(typeStr, type);
|
||||
unqualified.put(typeStr.substring(typeStr.lastIndexOf('.') + 1), type);
|
||||
}
|
||||
for (String typeStr : typeStrings) {
|
||||
Type type = unqualified.get(typeStr);
|
||||
if (type == null) type = unqualified.get("java.lang.String");
|
||||
types.add(type);
|
||||
}
|
||||
}
|
||||
|
||||
parameters = new ParameterData[paramNames.size()];
|
||||
List<Parameter> userParameters = new ArrayList<Parameter>();
|
||||
|
||||
// This helps keep tracks of @Nullables that appear in the middle of a list
|
||||
// of parameters
|
||||
int numOptional = 0;
|
||||
//
|
||||
// Go through each parameter
|
||||
for (int i = 0; i < types.size(); i++) {
|
||||
Type type = types.get(i);
|
||||
|
||||
ParameterData parameter = new ParameterData();
|
||||
parameter.setType(type);
|
||||
parameter.setModifiers(new Annotation[0]);
|
||||
|
||||
String paramName = paramNames.get(i);
|
||||
boolean flag = paramName.length() == 1 && command.flags().contains(paramName);
|
||||
if (flag) {
|
||||
parameter.setFlag(paramName.charAt(0), type != boolean.class && type != Boolean.class);
|
||||
}
|
||||
|
||||
// TODO switch / Optional / Search for annotations /
|
||||
|
||||
parameter.setName(paramName);
|
||||
|
||||
// Track all value flags
|
||||
if (parameter.isValueFlag()) {
|
||||
valueFlags.add(parameter.getFlag());
|
||||
}
|
||||
|
||||
// No special @annotation binding... let's check for the type
|
||||
if (parameter.getBinding() == null) {
|
||||
parameter.setBinding(builder.getBindings().get(type));
|
||||
|
||||
// Don't know how to parse for this type of value
|
||||
if (parameter.getBinding() == null) {
|
||||
throw new ParametricException("Don't know how to handle the parameter type '" + type + "' in\n" + StringMan.getString(command.aliases()));
|
||||
}
|
||||
}
|
||||
|
||||
// Do some validation of this parameter
|
||||
parameter.validate(() -> StringMan.getString(command.aliases()), i + 1);
|
||||
|
||||
// Keep track of optional parameters
|
||||
if (parameter.isOptional() && parameter.getFlag() == null) {
|
||||
numOptional++;
|
||||
} else {
|
||||
if (numOptional > 0 && parameter.isNonFlagConsumer()) {
|
||||
if (parameter.getConsumedCount() < 0) {
|
||||
throw new ParametricException(
|
||||
"Found an parameter using the binding " +
|
||||
parameter.getBinding().getClass().getCanonicalName() +
|
||||
"\nthat does not know how many arguments it consumes, but " +
|
||||
"it follows an optional parameter\nMethod: " + StringMan.getString(command.aliases()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parameters[i] = parameter;
|
||||
|
||||
// Make a list of "real" parameters
|
||||
if (parameter.isUserInput()) {
|
||||
userParameters.add(parameter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Gather legacy flags
|
||||
anyFlags = command.anyFlags();
|
||||
legacyFlags.addAll(Chars.asList(command.flags().toCharArray()));
|
||||
|
||||
// Finish description
|
||||
description.setDescription(!command.desc().isEmpty() ? command.desc() : null);
|
||||
description.setHelp(!command.help().isEmpty() ? command.help() : null);
|
||||
description.overrideUsage(!command.usage().isEmpty() ? command.usage() : null);
|
||||
description.setPermissions(Arrays.asList(permission));
|
||||
|
||||
if (command.usage().isEmpty() && (command.min() > 0 || command.max() > 0)) {
|
||||
boolean hasUserParameters = false;
|
||||
|
||||
for (ParameterData parameter : parameters) {
|
||||
if (parameter.getBinding().getBehavior(parameter) != BindingBehavior.PROVIDES) {
|
||||
hasUserParameters = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasUserParameters) {
|
||||
description.overrideUsage("(unknown usage information)");
|
||||
}
|
||||
}
|
||||
|
||||
// Set parameters
|
||||
description.setParameters(userParameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Command getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParameterData[] getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public Set<Character> getValueFlags() {
|
||||
return valueFlags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Character> getLegacyFlags() {
|
||||
return legacyFlags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object call(String stringArguments, CommandLocals locals, String[] parentCommands) throws CommandException {
|
||||
// Test permission
|
||||
if (!testPermission(locals)) {
|
||||
throw new CommandPermissionsException();
|
||||
}
|
||||
|
||||
String calledCommand = parentCommands.length > 0 ? parentCommands[parentCommands.length - 1] : "_";
|
||||
String[] split = (calledCommand + " " + stringArguments).split(" ", -1);
|
||||
CommandContext context = new CommandContext(split, getValueFlags(), false, locals);
|
||||
|
||||
// Provide help if -? is specified
|
||||
if (context.hasFlag('?')) {
|
||||
throw new InvalidUsageException(null, this, true);
|
||||
}
|
||||
|
||||
Object[] args = new Object[parameters.length];
|
||||
ContextArgumentStack arguments = new ContextArgumentStack(context);
|
||||
ParameterData parameter = null;
|
||||
|
||||
try {
|
||||
// preProcess handlers
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Collect parameters
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
parameter = parameters[i];
|
||||
|
||||
if (mayConsumeArguments(i, arguments)) {
|
||||
// Parse the user input into a method argument
|
||||
ArgumentStack usedArguments = getScopedContext(parameter, arguments);
|
||||
|
||||
try {
|
||||
usedArguments.mark();
|
||||
args[i] = parameter.getBinding().bind(parameter, usedArguments, false);
|
||||
} catch (ParameterException e) {
|
||||
// Not optional? Then we can't execute this command
|
||||
if (!parameter.isOptional()) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
usedArguments.reset();
|
||||
args[i] = getDefaultValue(i, arguments);
|
||||
}
|
||||
} else {
|
||||
args[i] = getDefaultValue(i, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for unused arguments
|
||||
checkUnconsumed(arguments);
|
||||
|
||||
// preInvoke handlers
|
||||
{
|
||||
if (context.argsLength() < command.min()) {
|
||||
throw new MissingParameterException();
|
||||
}
|
||||
if (command.max() != -1 && context.argsLength() > command.max()) {
|
||||
throw new UnconsumedParameterException(context.getRemainingString(command.max()));
|
||||
}
|
||||
}
|
||||
|
||||
// Execute!
|
||||
Object result = function.apply(args);
|
||||
|
||||
// postInvoke handlers
|
||||
{
|
||||
|
||||
}
|
||||
return result;
|
||||
} catch (MissingParameterException e) {
|
||||
throw new InvalidUsageException("Too few parameters!", this, true);
|
||||
} catch (UnconsumedParameterException e) {
|
||||
throw new InvalidUsageException("Too many parameters! Unused parameters: " + e.getUnconsumed(), this, true);
|
||||
} catch (ParameterException e) {
|
||||
assert parameter != null;
|
||||
String name = parameter.getName();
|
||||
|
||||
throw new InvalidUsageException("For parameter '" + name + "': " + e.getMessage(), this, true);
|
||||
} catch (InvocationTargetException e) {
|
||||
if (e.getCause() instanceof CommandException) {
|
||||
throw (CommandException) e.getCause();
|
||||
}
|
||||
throw new WrappedCommandException(e);
|
||||
} catch (Throwable t) {
|
||||
throw new WrappedCommandException(t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testPermission(CommandLocals locals) {
|
||||
return permission != null ? (builder.getAuthorizer().testPermission(locals, permission)) : true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SimpleDescription getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPermissions() {
|
||||
return new String[]{permission};
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParametricBuilder getBuilder() {
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean anyFlags() {
|
||||
return anyFlags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return command.aliases()[0];
|
||||
}
|
||||
}
|
@ -24,9 +24,12 @@ import com.sk89q.worldedit.util.command.binding.PrimitiveBindings;
|
||||
import com.sk89q.worldedit.util.command.binding.Range;
|
||||
import com.sk89q.worldedit.util.command.binding.Text;
|
||||
|
||||
import javax.xml.ws.Provider;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Describes a parameter in detail.
|
||||
@ -37,10 +40,10 @@ public class ParameterData extends SimpleParameter {
|
||||
private Annotation classifier;
|
||||
private Annotation[] modifiers;
|
||||
private Type type;
|
||||
|
||||
|
||||
/**
|
||||
* Get the binding associated with this parameter.
|
||||
*
|
||||
*
|
||||
* @return the binding
|
||||
*/
|
||||
public Binding getBinding() {
|
||||
@ -49,67 +52,67 @@ public class ParameterData extends SimpleParameter {
|
||||
|
||||
/**
|
||||
* Set the binding associated with this parameter.
|
||||
*
|
||||
*
|
||||
* @param binding the binding
|
||||
*/
|
||||
void setBinding(Binding binding) {
|
||||
public void setBinding(Binding binding) {
|
||||
this.binding = binding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the main type of this parameter.
|
||||
*
|
||||
* <p>
|
||||
* <p>The type is normally that is used to determine which binding is used
|
||||
* for a particular method's parameter.</p>
|
||||
*
|
||||
*
|
||||
* @return the main type
|
||||
* @see #getClassifier() which can override the type
|
||||
*/
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the main type of this parameter.
|
||||
*
|
||||
*
|
||||
* @param type the main type
|
||||
*/
|
||||
void setType(Type type) {
|
||||
public void setType(Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the classifier annotation.
|
||||
*
|
||||
* <p>
|
||||
* <p>Normally, the type determines what binding is called, but classifiers
|
||||
* take precedence if one is found (and registered with
|
||||
* {@link ParametricBuilder#addBinding(Binding, Type...)}).
|
||||
* take precedence if one is found (and registered with
|
||||
* {@link ParametricBuilder#addBinding(Binding, Type...)}).
|
||||
* An example of a classifier annotation is {@link Text}.</p>
|
||||
*
|
||||
*
|
||||
* @return the classifier annotation, null is possible
|
||||
*/
|
||||
public Annotation getClassifier() {
|
||||
return classifier;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the classifier annotation.
|
||||
*
|
||||
*
|
||||
* @param classifier the classifier annotation, null is possible
|
||||
*/
|
||||
void setClassifier(Annotation classifier) {
|
||||
public void setClassifier(Annotation classifier) {
|
||||
this.classifier = classifier;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a list of modifier annotations.
|
||||
*
|
||||
* <p>
|
||||
* <p>Modifier annotations are not considered in the process of choosing a binding
|
||||
* for a method parameter, but they can be used to modify the behavior of a binding.
|
||||
* An example of a modifier annotation is {@link Range}, which can restrict
|
||||
* numeric values handled by {@link PrimitiveBindings} to be within a range. The list
|
||||
* of annotations may contain a classifier and other unrelated annotations.</p>
|
||||
*
|
||||
*
|
||||
* @return a list of annotations
|
||||
*/
|
||||
public Annotation[] getModifiers() {
|
||||
@ -118,44 +121,48 @@ public class ParameterData extends SimpleParameter {
|
||||
|
||||
/**
|
||||
* Set the list of modifiers.
|
||||
*
|
||||
*
|
||||
* @param modifiers a list of annotations
|
||||
*/
|
||||
void setModifiers(Annotation[] modifiers) {
|
||||
public void setModifiers(Annotation[] modifiers) {
|
||||
this.modifiers = modifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of arguments this binding consumes.
|
||||
*
|
||||
*
|
||||
* @return -1 if unknown or unavailable
|
||||
*/
|
||||
int getConsumedCount() {
|
||||
public int getConsumedCount() {
|
||||
return getBinding().getConsumedCount(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether this parameter is entered by the user.
|
||||
*
|
||||
*
|
||||
* @return true if this parameter is entered by the user.
|
||||
*/
|
||||
boolean isUserInput() {
|
||||
public boolean isUserInput() {
|
||||
return getBinding().getBehavior(this) != BindingBehavior.PROVIDES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether this parameter consumes non-flag arguments.
|
||||
*
|
||||
*
|
||||
* @return true if this parameter consumes non-flag arguments
|
||||
*/
|
||||
boolean isNonFlagConsumer() {
|
||||
public boolean isNonFlagConsumer() {
|
||||
return getBinding().getBehavior(this) != BindingBehavior.PROVIDES && !isValueFlag();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate this parameter and its binding.
|
||||
*/
|
||||
void validate(Method method, int parameterIndex) throws ParametricException {
|
||||
public void validate(Method method, int parameterIndex) throws ParametricException {
|
||||
validate(() -> method.toGenericString(), parameterIndex);
|
||||
}
|
||||
|
||||
public void validate(Supplier<String> method, int parameterIndex) throws ParametricException {
|
||||
// We can't have indeterminate consumers without @Switches otherwise
|
||||
// it may screw up parameter processing for later bindings
|
||||
BindingBehavior behavior = getBinding().getBehavior(this);
|
||||
@ -163,32 +170,35 @@ public class ParameterData extends SimpleParameter {
|
||||
if (!isValueFlag() && indeterminate) {
|
||||
throw new ParametricException(
|
||||
"@Switch missing for indeterminate consumer\n\n" +
|
||||
"Notably:\nFor the type " + type + ", the binding " +
|
||||
getBinding().getClass().getCanonicalName() +
|
||||
"\nmay or may not consume parameters (isIndeterminateConsumer(" + type + ") = true)" +
|
||||
"\nand therefore @Switch(flag) is required for parameter #" + parameterIndex + " of \n" +
|
||||
method.toGenericString());
|
||||
"Notably:\nFor the type " + type + ", the binding " +
|
||||
getBinding().getClass().getCanonicalName() +
|
||||
"\nmay or may not consume parameters (isIndeterminateConsumer(" + type + ") = true)" +
|
||||
"\nand therefore @Switch(flag) is required for parameter #" + parameterIndex + " of \n" +
|
||||
method.get());
|
||||
}
|
||||
|
||||
|
||||
// getConsumedCount() better return -1 if the BindingBehavior is not CONSUMES
|
||||
if (behavior != BindingBehavior.CONSUMES && binding.getConsumedCount(this) != -1) {
|
||||
throw new ParametricException(
|
||||
"getConsumedCount() does not return -1 for binding " +
|
||||
getBinding().getClass().getCanonicalName() +
|
||||
"\neven though its behavior type is " + behavior.name() +
|
||||
"\nfor parameter #" + parameterIndex + " of \n" +
|
||||
method.toGenericString());
|
||||
"getConsumedCount() does not return -1 for binding " +
|
||||
getBinding().getClass().getCanonicalName() +
|
||||
"\neven though its behavior type is " + behavior.name() +
|
||||
"\nfor parameter #" + parameterIndex + " of \n" +
|
||||
method.get());
|
||||
}
|
||||
|
||||
|
||||
// getConsumedCount() should not return 0 if the BindingBehavior is not PROVIDES
|
||||
if (behavior != BindingBehavior.PROVIDES && binding.getConsumedCount(this) == 0) {
|
||||
throw new ParametricException(
|
||||
"getConsumedCount() must not return 0 for binding " +
|
||||
getBinding().getClass().getCanonicalName() +
|
||||
"\nwhen its behavior type is " + behavior.name() + " and not PROVIDES " +
|
||||
"\nfor parameter #" + parameterIndex + " of \n" +
|
||||
method.toGenericString());
|
||||
"getConsumedCount() must not return 0 for binding " +
|
||||
getBinding().getClass().getCanonicalName() +
|
||||
"\nwhen its behavior type is " + behavior.name() + " and not PROVIDES " +
|
||||
"\nfor parameter #" + parameterIndex + " of \n" +
|
||||
method.get());
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return ParameterData.class;
|
||||
}
|
||||
}
|
||||
|
@ -19,25 +19,34 @@
|
||||
|
||||
package com.sk89q.worldedit.util.command.parametric;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.boydti.fawe.command.FawePrimitiveBinding;
|
||||
import com.boydti.fawe.command.MaskBinding;
|
||||
import com.boydti.fawe.command.PatternBinding;
|
||||
import com.boydti.fawe.config.Commands;
|
||||
import com.google.common.collect.ImmutableBiMap.Builder;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.command.MethodCommands;
|
||||
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.util.auth.Authorizer;
|
||||
import com.sk89q.worldedit.util.auth.NullAuthorizer;
|
||||
import com.sk89q.worldedit.util.command.CallableProcessor;
|
||||
import com.sk89q.worldedit.util.command.CommandCallable;
|
||||
import com.sk89q.worldedit.util.command.CommandCompleter;
|
||||
import com.sk89q.worldedit.util.command.Dispatcher;
|
||||
import com.sk89q.worldedit.util.command.NullCompleter;
|
||||
import com.sk89q.worldedit.util.command.ProcessedCallable;
|
||||
import com.sk89q.worldedit.util.command.binding.PrimitiveBindings;
|
||||
import com.sk89q.worldedit.util.command.binding.StandardBindings;
|
||||
import com.sk89q.worldedit.util.command.binding.Switch;
|
||||
import com.thoughtworks.paranamer.CachingParanamer;
|
||||
import com.thoughtworks.paranamer.FaweParanamer;
|
||||
import com.thoughtworks.paranamer.Paranamer;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
@ -45,40 +54,44 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Creates commands using annotations placed on methods and individual parameters of
|
||||
* such methods.
|
||||
*
|
||||
*
|
||||
* @see Command defines a command
|
||||
* @see Switch defines a flag
|
||||
*/
|
||||
public class ParametricBuilder {
|
||||
|
||||
private final Map<Type, Binding> bindings = new HashMap<>();
|
||||
private final Paranamer paranamer = new CachingParanamer();
|
||||
private final List<InvokeListener> invokeListeners = new ArrayList<>();
|
||||
private final Map<Type, Binding> bindings = new HashMap<Type, Binding>();
|
||||
private final Paranamer paranamer = new FaweParanamer();
|
||||
private final List<InvokeListener> invokeListeners = new ArrayList<InvokeListener>();
|
||||
private final List<ExceptionConverter> exceptionConverters = new ArrayList<ExceptionConverter>();
|
||||
private Authorizer authorizer = new NullAuthorizer();
|
||||
private CommandCompleter defaultCompleter = new NullCompleter();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new builder.
|
||||
*
|
||||
* <p>This method will install {@link PrimitiveBindings} and
|
||||
* <p>
|
||||
* <p>This method will install {@link PrimitiveBindings} and
|
||||
* {@link StandardBindings} and default bindings.</p>
|
||||
*/
|
||||
public ParametricBuilder() {
|
||||
addBinding(new PrimitiveBindings());
|
||||
addBinding(new FawePrimitiveBinding());
|
||||
addBinding(new StandardBindings());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a binding for a given type or classifier (annotation).
|
||||
*
|
||||
* <p>
|
||||
* <p>Whenever a method parameter is encountered, a binding must be found for it
|
||||
* so that it can be called later to consume the stack of arguments provided by
|
||||
* the user and return an object that is later passed to
|
||||
* the user and return an object that is later passed to
|
||||
* {@link Method#invoke(Object, Object...)}.</p>
|
||||
*
|
||||
* <p>
|
||||
* <p>Normally, a {@link Type} is used to discern between different bindings, but
|
||||
* if this is not specific enough, an annotation can be defined and used. This
|
||||
* makes it a "classifier" and it will take precedence over the base type. For
|
||||
@ -87,59 +100,95 @@ public class ParametricBuilder {
|
||||
* parameter, which will cause the {@link Builder} to consult the {@link Binding}
|
||||
* associated with {@code @MyArg} rather than with the binding for
|
||||
* the {@link String} type.</p>
|
||||
*
|
||||
*
|
||||
* @param binding the binding
|
||||
* @param type a list of types (if specified) to override the binding's types
|
||||
* @param type a list of types (if specified) to override the binding's types
|
||||
*/
|
||||
public void addBinding(Binding binding, Type... type) {
|
||||
if (type == null || type.length == 0) {
|
||||
type = binding.getTypes();
|
||||
}
|
||||
|
||||
|
||||
for (Type t : type) {
|
||||
bindings.put(t, binding);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attach an invocation listener.
|
||||
*
|
||||
* <p>
|
||||
* <p>Invocation handlers are called in order that their listeners are
|
||||
* registered with a {@link ParametricBuilder}. It is not guaranteed that
|
||||
* a listener may be called, in the case of a {@link CommandException} being
|
||||
* thrown at any time before the appropriate listener or handler is called.
|
||||
* It is possible for a
|
||||
* {@link InvokeHandler#preInvoke(Object, Method, ParameterData[], Object[], CommandContext)} to
|
||||
* It is possible for a
|
||||
* {@link com.sk89q.worldedit.util.command.parametric.InvokeHandler#preInvoke(Object, Method, com.sk89q.worldedit.util.command.parametric.ParameterData[], Object[], CommandContext)} to
|
||||
* be called for a invocation handler, but not the associated
|
||||
* {@link InvokeHandler#postInvoke(Object, Method, ParameterData[], Object[], CommandContext)}.</p>
|
||||
*
|
||||
* {@link com.sk89q.worldedit.util.command.parametric.InvokeHandler#postInvoke(Object, Method, com.sk89q.worldedit.util.command.parametric.ParameterData[], Object[], CommandContext)}.</p>
|
||||
* <p>
|
||||
* <p>An example of an invocation listener is one to handle
|
||||
* {@link CommandPermissions}, by first checking to see if permission is available
|
||||
* in a {@link InvokeHandler#preInvoke(Object, Method, ParameterData[], Object[], CommandContext)}
|
||||
* in a {@link com.sk89q.worldedit.util.command.parametric.InvokeHandler#preInvoke(Object, Method, com.sk89q.worldedit.util.command.parametric.ParameterData[], Object[], CommandContext)}
|
||||
* call. If permission is not found, then an appropriate {@link CommandException}
|
||||
* can be thrown to cease invocation.</p>
|
||||
*
|
||||
*
|
||||
* @param listener the listener
|
||||
* @see InvokeHandler the handler
|
||||
* @see com.sk89q.worldedit.util.command.parametric.InvokeHandler the handler
|
||||
*/
|
||||
public void addInvokeListener(InvokeListener listener) {
|
||||
invokeListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach an exception converter to this builder in order to wrap unknown
|
||||
* {@link Throwable}s into known {@link CommandException}s.
|
||||
* <p>
|
||||
* <p>Exception converters are called in order that they are registered.</p>
|
||||
*
|
||||
* @param converter the converter
|
||||
* @see ExceptionConverter for an explanation
|
||||
*/
|
||||
public void addExceptionConverter(ExceptionConverter converter) {
|
||||
exceptionConverters.add(converter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a list of commands from methods specially annotated with {@link Command}
|
||||
* (and other relevant annotations) and register them all with the given
|
||||
* {@link Dispatcher}.
|
||||
*
|
||||
*
|
||||
* @param dispatcher the dispatcher to register commands with
|
||||
* @param object the object contain the methods
|
||||
* @throws ParametricException thrown if the commands cannot be registered
|
||||
* @param object the object contain the methods
|
||||
* @throws com.sk89q.worldedit.util.command.parametric.ParametricException thrown if the commands cannot be registered
|
||||
*/
|
||||
public void registerMethodsAsCommands(Dispatcher dispatcher, Object object) throws ParametricException {
|
||||
registerMethodsAsCommands(dispatcher, object, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a list of commands from methods specially annotated with {@link Command}
|
||||
* (and other relevant annotations) and register them all with the given
|
||||
* {@link Dispatcher}.
|
||||
*
|
||||
* @param dispatcher the dispatcher to register commands with
|
||||
* @param object the object contain the methods
|
||||
* @throws com.sk89q.worldedit.util.command.parametric.ParametricException thrown if the commands cannot be registered
|
||||
*/
|
||||
public void registerMethodsAsCommands(Dispatcher dispatcher, Object object, CallableProcessor processor) throws ParametricException {
|
||||
for (Method method : object.getClass().getDeclaredMethods()) {
|
||||
Command definition = method.getAnnotation(Command.class);
|
||||
if (definition != null) {
|
||||
definition = Commands.translate(method.getDeclaringClass(), definition);
|
||||
CommandCallable callable = build(object, method, definition);
|
||||
if (processor != null) {
|
||||
callable = new ProcessedCallable(callable, processor);
|
||||
}
|
||||
else if (object instanceof CallableProcessor) {
|
||||
callable = new ProcessedCallable(callable, (CallableProcessor) object);
|
||||
}
|
||||
if (object instanceof MethodCommands) {
|
||||
((MethodCommands) object).register(method, callable, dispatcher);
|
||||
}
|
||||
dispatcher.registerCommand(callable, definition.aliases());
|
||||
}
|
||||
}
|
||||
@ -147,46 +196,63 @@ public class ParametricBuilder {
|
||||
|
||||
/**
|
||||
* Build a {@link CommandCallable} for the given method.
|
||||
*
|
||||
* @param object the object to be invoked on
|
||||
* @param method the method to invoke
|
||||
*
|
||||
* @param object the object to be invoked on
|
||||
* @param method the method to invoke
|
||||
* @param definition the command definition annotation
|
||||
* @return the command executor
|
||||
* @throws ParametricException thrown on an error
|
||||
*/
|
||||
private CommandCallable build(Object object, Method method, Command definition)
|
||||
private CommandCallable build(Object object, Method method, Command definition)
|
||||
throws ParametricException {
|
||||
return new ParametricCallable(this, object, method, definition);
|
||||
try {
|
||||
return new ParametricCallable(this, object, method, definition);
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof ParametricException) {
|
||||
throw (ParametricException) e;
|
||||
}
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object used to get method names on Java versions before 8 (assuming
|
||||
* that Java 8 is given the ability to reliably reflect method names at runtime).
|
||||
*
|
||||
*
|
||||
* @return the paranamer
|
||||
*/
|
||||
Paranamer getParanamer() {
|
||||
public Paranamer getParanamer() {
|
||||
return paranamer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the map of bindings.
|
||||
*
|
||||
*
|
||||
* @return the map of bindings
|
||||
*/
|
||||
Map<Type, Binding> getBindings() {
|
||||
public Map<Type, Binding> getBindings() {
|
||||
return bindings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of invocation listeners.
|
||||
*
|
||||
*
|
||||
* @return a list of invocation listeners
|
||||
*/
|
||||
List<InvokeListener> getInvokeListeners() {
|
||||
public List<InvokeListener> getInvokeListeners() {
|
||||
return invokeListeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of exception converters.
|
||||
*
|
||||
* @return a list of exception converters
|
||||
*/
|
||||
public List<ExceptionConverter> getExceptionConverters() {
|
||||
return exceptionConverters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the authorizer.
|
||||
*
|
||||
@ -227,4 +293,8 @@ public class ParametricBuilder {
|
||||
this.defaultCompleter = defaultCompleter;
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return ParametricBuilder.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
package com.sk89q.worldedit.util.command.parametric;
|
||||
|
||||
import com.boydti.fawe.command.SuggestInputParseException;
|
||||
import com.google.common.primitives.Chars;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
@ -26,6 +27,7 @@ import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
|
||||
import com.sk89q.minecraft.util.commands.SuggestionContext;
|
||||
import com.sk89q.minecraft.util.commands.WrappedCommandException;
|
||||
import com.sk89q.worldedit.util.command.CommandCallable;
|
||||
import com.sk89q.worldedit.util.command.InvalidUsageException;
|
||||
@ -34,7 +36,6 @@ import com.sk89q.worldedit.util.command.Parameter;
|
||||
import com.sk89q.worldedit.util.command.SimpleDescription;
|
||||
import com.sk89q.worldedit.util.command.UnconsumedParameterException;
|
||||
import com.sk89q.worldedit.util.command.binding.Switch;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
@ -48,42 +49,43 @@ import java.util.Set;
|
||||
/**
|
||||
* The implementation of a {@link CommandCallable} for the {@link ParametricBuilder}.
|
||||
*/
|
||||
class ParametricCallable implements CommandCallable {
|
||||
public class ParametricCallable extends AParametricCallable {
|
||||
|
||||
private final ParametricBuilder builder;
|
||||
private final Object object;
|
||||
private final Method method;
|
||||
private final ParameterData[] parameters;
|
||||
private final Set<Character> valueFlags = new HashSet<>();
|
||||
private final Set<Character> valueFlags = new HashSet<Character>();
|
||||
private final boolean anyFlags;
|
||||
private final Set<Character> legacyFlags = new HashSet<>();
|
||||
private final Set<Character> legacyFlags = new HashSet<Character>();
|
||||
private final SimpleDescription description = new SimpleDescription();
|
||||
private final CommandPermissions commandPermissions;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param builder the parametric builder
|
||||
* @param object the object to invoke on
|
||||
* @param method the method to invoke
|
||||
*
|
||||
* @param builder the parametric builder
|
||||
* @param object the object to invoke on
|
||||
* @param method the method to invoke
|
||||
* @param definition the command definition annotation
|
||||
* @throws ParametricException thrown on an error
|
||||
*/
|
||||
ParametricCallable(ParametricBuilder builder, Object object, Method method, Command definition) throws ParametricException {
|
||||
public ParametricCallable(ParametricBuilder builder, Object object, Method method, Command definition) throws ParametricException {
|
||||
this.builder = builder;
|
||||
this.object = object;
|
||||
this.method = method;
|
||||
|
||||
|
||||
Annotation[][] annotations = method.getParameterAnnotations();
|
||||
String[] names = builder.getParanamer().lookupParameterNames(method, false);
|
||||
Type[] types = method.getGenericParameterTypes();
|
||||
|
||||
parameters = new ParameterData[types.length];
|
||||
List<Parameter> userParameters = new ArrayList<>();
|
||||
|
||||
List<Parameter> userParameters = new ArrayList<Parameter>();
|
||||
|
||||
// This helps keep tracks of @Nullables that appear in the middle of a list
|
||||
// of parameters
|
||||
int numOptional = 0;
|
||||
|
||||
|
||||
// Set permission hint
|
||||
CommandPermissions permHint = method.getAnnotation(CommandPermissions.class);
|
||||
if (permHint != null) {
|
||||
@ -93,7 +95,7 @@ class ParametricCallable implements CommandCallable {
|
||||
// Go through each parameter
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
Type type = types[i];
|
||||
|
||||
|
||||
ParameterData parameter = new ParameterData();
|
||||
parameter.setType(type);
|
||||
parameter.setModifiers(annotations[i]);
|
||||
@ -108,7 +110,7 @@ class ParametricCallable implements CommandCallable {
|
||||
if (value.length > 0) {
|
||||
parameter.setDefaultValue(value);
|
||||
}
|
||||
// Special annotation bindings
|
||||
// Special annotation bindings
|
||||
} else if (parameter.getBinding() == null) {
|
||||
parameter.setBinding(builder.getBindings().get(annotation.annotationType()));
|
||||
parameter.setClassifier(annotation);
|
||||
@ -131,10 +133,10 @@ class ParametricCallable implements CommandCallable {
|
||||
throw new ParametricException("Don't know how to handle the parameter type '" + type + "' in\n" + method.toGenericString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Do some validation of this parameter
|
||||
parameter.validate(method, i + 1);
|
||||
|
||||
|
||||
// Keep track of optional parameters
|
||||
if (parameter.isOptional() && parameter.getFlag() == null) {
|
||||
numOptional++;
|
||||
@ -142,17 +144,17 @@ class ParametricCallable implements CommandCallable {
|
||||
if (numOptional > 0 && parameter.isNonFlagConsumer()) {
|
||||
if (parameter.getConsumedCount() < 0) {
|
||||
throw new ParametricException(
|
||||
"Found an parameter using the binding " +
|
||||
parameter.getBinding().getClass().getCanonicalName() +
|
||||
"\nthat does not know how many arguments it consumes, but " +
|
||||
"it follows an optional parameter\nMethod: " +
|
||||
method.toGenericString());
|
||||
"Found an parameter using the binding " +
|
||||
parameter.getBinding().getClass().getCanonicalName() +
|
||||
"\nthat does not know how many arguments it consumes, but " +
|
||||
"it follows an optional parameter\nMethod: " +
|
||||
method.toGenericString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
parameters[i] = parameter;
|
||||
|
||||
|
||||
// Make a list of "real" parameters
|
||||
if (parameter.isUserInput()) {
|
||||
userParameters.add(parameter);
|
||||
@ -171,7 +173,7 @@ class ParametricCallable implements CommandCallable {
|
||||
for (InvokeListener listener : builder.getInvokeListeners()) {
|
||||
listener.updateDescription(object, method, parameters, description);
|
||||
}
|
||||
|
||||
|
||||
// Set parameters
|
||||
description.setParameters(userParameters);
|
||||
|
||||
@ -179,6 +181,16 @@ class ParametricCallable implements CommandCallable {
|
||||
commandPermissions = method.getAnnotation(CommandPermissions.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Command getCommand() {
|
||||
return object.getClass().getAnnotation(Command.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return object.getClass().getSimpleName().replaceAll("Commands", "").replaceAll("Util$", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object call(String stringArguments, CommandLocals locals, String[] parentCommands) throws CommandException {
|
||||
// Test permission
|
||||
@ -187,7 +199,7 @@ class ParametricCallable implements CommandCallable {
|
||||
}
|
||||
|
||||
String calledCommand = parentCommands.length > 0 ? parentCommands[parentCommands.length - 1] : "_";
|
||||
String[] split = CommandContext.split(calledCommand + " " + stringArguments);
|
||||
String[] split = (calledCommand + " " + stringArguments).split(" ", -1);
|
||||
CommandContext context = new CommandContext(split, getValueFlags(), false, locals);
|
||||
|
||||
// Provide help if -? is specified
|
||||
@ -201,7 +213,7 @@ class ParametricCallable implements CommandCallable {
|
||||
|
||||
try {
|
||||
// preProcess handlers
|
||||
List<InvokeHandler> handlers = new ArrayList<>();
|
||||
List<InvokeHandler> handlers = new ArrayList<InvokeHandler>();
|
||||
for (InvokeListener listener : builder.getInvokeListeners()) {
|
||||
InvokeHandler handler = listener.createInvokeHandler();
|
||||
handlers.add(handler);
|
||||
@ -217,13 +229,15 @@ class ParametricCallable implements CommandCallable {
|
||||
ArgumentStack usedArguments = getScopedContext(parameter, arguments);
|
||||
|
||||
try {
|
||||
usedArguments.mark();
|
||||
args[i] = parameter.getBinding().bind(parameter, usedArguments, false);
|
||||
} catch (MissingParameterException e) {
|
||||
} catch (ParameterException e) {
|
||||
// Not optional? Then we can't execute this command
|
||||
if (!parameter.isOptional()) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
usedArguments.reset();
|
||||
args[i] = getDefaultValue(i, arguments);
|
||||
}
|
||||
} else {
|
||||
@ -240,21 +254,22 @@ class ParametricCallable implements CommandCallable {
|
||||
}
|
||||
|
||||
// Execute!
|
||||
method.invoke(object, args);
|
||||
Object result = method.invoke(object, args);
|
||||
|
||||
// postInvoke handlers
|
||||
for (InvokeHandler handler : handlers) {
|
||||
handler.postInvoke(handler, method, parameters, args, context);
|
||||
}
|
||||
return result;
|
||||
} catch (MissingParameterException e) {
|
||||
throw new InvalidUsageException("Too few parameters!", this);
|
||||
throw new InvalidUsageException("Too few parameters!", this, true);
|
||||
} catch (UnconsumedParameterException e) {
|
||||
throw new InvalidUsageException("Too many parameters! Unused parameters: " + e.getUnconsumed(), this);
|
||||
throw new InvalidUsageException("Too many parameters! Unused parameters: " + e.getUnconsumed(), this, true);
|
||||
} catch (ParameterException e) {
|
||||
assert parameter != null;
|
||||
String name = parameter.getName();
|
||||
|
||||
throw new InvalidUsageException("For parameter '" + name + "': " + e.getMessage(), this);
|
||||
throw new InvalidUsageException("For parameter '" + name + "': " + e.getMessage(), this, true);
|
||||
} catch (InvocationTargetException e) {
|
||||
if (e.getCause() instanceof CommandException) {
|
||||
throw (CommandException) e.getCause();
|
||||
@ -263,13 +278,19 @@ class ParametricCallable implements CommandCallable {
|
||||
} catch (Throwable t) {
|
||||
throw new WrappedCommandException(t);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
public Object getObject() {
|
||||
return object;
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException {
|
||||
return builder.getDefaultCompleter().getSuggestions(arguments, locals);
|
||||
public ParameterData[] getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -281,190 +302,45 @@ class ParametricCallable implements CommandCallable {
|
||||
return valueFlags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Character> getLegacyFlags() {
|
||||
return legacyFlags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SimpleDescription getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testPermission(CommandLocals locals) {
|
||||
if (commandPermissions != null) {
|
||||
for (String perm : commandPermissions.value()) {
|
||||
if (builder.getAuthorizer().testPermission(locals, perm)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
public String[] getPermissions() {
|
||||
return commandPermissions != null ? commandPermissions.value() : new String[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the right {@link ArgumentStack}.
|
||||
*
|
||||
* @param parameter the parameter
|
||||
* @param existing the existing scoped context
|
||||
* @return the context to use
|
||||
*/
|
||||
private static ArgumentStack getScopedContext(Parameter parameter, ArgumentStack existing) {
|
||||
if (parameter.getFlag() != null) {
|
||||
CommandContext context = existing.getContext();
|
||||
|
||||
if (parameter.isValueFlag()) {
|
||||
return new StringArgumentStack(context, context.getFlag(parameter.getFlag()), false);
|
||||
} else {
|
||||
String v = context.hasFlag(parameter.getFlag()) ? "true" : "false";
|
||||
return new StringArgumentStack(context, v, true);
|
||||
}
|
||||
}
|
||||
|
||||
return existing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether a parameter is allowed to consume arguments.
|
||||
*
|
||||
* @param i the index of the parameter
|
||||
* @param scoped the scoped context
|
||||
* @return true if arguments may be consumed
|
||||
*/
|
||||
private boolean mayConsumeArguments(int i, ContextArgumentStack scoped) {
|
||||
CommandContext context = scoped.getContext();
|
||||
ParameterData parameter = parameters[i];
|
||||
|
||||
// Flag parameters: Always consume
|
||||
// Required non-flag parameters: Always consume
|
||||
// Optional non-flag parameters:
|
||||
// - Before required parameters: Consume if there are 'left over' args
|
||||
// - At the end: Always consumes
|
||||
|
||||
if (parameter.isOptional()) {
|
||||
if (parameter.getFlag() != null) {
|
||||
return !parameter.isValueFlag() || context.hasFlag(parameter.getFlag());
|
||||
} else {
|
||||
int numberFree = context.argsLength() - scoped.position();
|
||||
for (int j = i; j < parameters.length; j++) {
|
||||
if (parameters[j].isNonFlagConsumer() && !parameters[j].isOptional()) {
|
||||
// We already checked if the consumed count was > -1
|
||||
// when we created this object
|
||||
numberFree -= parameters[j].getConsumedCount();
|
||||
}
|
||||
}
|
||||
|
||||
// Skip this optional parameter
|
||||
if (numberFree < 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default value for a parameter.
|
||||
*
|
||||
* @param i the index of the parameter
|
||||
* @param scoped the scoped context
|
||||
* @return a value
|
||||
* @throws ParameterException on an error
|
||||
* @throws CommandException on an error
|
||||
*/
|
||||
private Object getDefaultValue(int i, ContextArgumentStack scoped) throws ParameterException, CommandException, InvocationTargetException {
|
||||
CommandContext context = scoped.getContext();
|
||||
ParameterData parameter = parameters[i];
|
||||
|
||||
String[] defaultValue = parameter.getDefaultValue();
|
||||
if (defaultValue != null) {
|
||||
try {
|
||||
return parameter.getBinding().bind(parameter, new StringArgumentStack(context, defaultValue, false), false);
|
||||
} catch (MissingParameterException e) {
|
||||
throw new ParametricException(
|
||||
"The default value of the parameter using the binding " +
|
||||
parameter.getBinding().getClass() + " in the method\n" +
|
||||
method.toGenericString() + "\nis invalid");
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
@Override
|
||||
public ParametricBuilder getBuilder() {
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check to see if all arguments, including flag arguments, were consumed.
|
||||
*
|
||||
* @param scoped the argument scope
|
||||
* @throws UnconsumedParameterException thrown if parameters were not consumed
|
||||
*/
|
||||
private void checkUnconsumed(ContextArgumentStack scoped) throws UnconsumedParameterException {
|
||||
CommandContext context = scoped.getContext();
|
||||
String unconsumed;
|
||||
String unconsumedFlags = getUnusedFlags(context);
|
||||
|
||||
if ((unconsumed = scoped.getUnconsumed()) != null) {
|
||||
throw new UnconsumedParameterException(unconsumed + " " + unconsumedFlags);
|
||||
}
|
||||
|
||||
if (unconsumedFlags != null) {
|
||||
throw new UnconsumedParameterException(unconsumedFlags);
|
||||
}
|
||||
@Override
|
||||
public boolean anyFlags() {
|
||||
return anyFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any unused flag arguments.
|
||||
*
|
||||
* @param context the command context
|
||||
*/
|
||||
private String getUnusedFlags(CommandContext context) {
|
||||
if (!anyFlags) {
|
||||
Set<Character> unusedFlags = null;
|
||||
for (char flag : context.getFlags()) {
|
||||
boolean found = false;
|
||||
|
||||
if (legacyFlags.contains(flag)) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (ParameterData parameter : parameters) {
|
||||
Character paramFlag = parameter.getFlag();
|
||||
if (paramFlag != null && flag == paramFlag) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
if (unusedFlags == null) {
|
||||
unusedFlags = new HashSet<>();
|
||||
}
|
||||
unusedFlags.add(flag);
|
||||
}
|
||||
}
|
||||
|
||||
if (unusedFlags != null) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (Character flag : unusedFlags) {
|
||||
builder.append("-").append(flag).append(" ");
|
||||
}
|
||||
|
||||
return builder.toString().trim();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
@Override
|
||||
public String toString() {
|
||||
return method.toGenericString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate a name for a parameter.
|
||||
*
|
||||
* @param type the type
|
||||
*
|
||||
* @param type the type
|
||||
* @param classifier the classifier
|
||||
* @param index the index
|
||||
* @param index the index
|
||||
* @return a generated name
|
||||
*/
|
||||
private static String generateName(Type type, Annotation classifier, int index) {
|
||||
public static String generateName(Type type, Annotation classifier, int index) {
|
||||
if (classifier != null) {
|
||||
return classifier.annotationType().getSimpleName().toLowerCase();
|
||||
} else {
|
||||
@ -476,4 +352,7 @@ class ParametricCallable implements CommandCallable {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public static Class<?> inject() {
|
||||
return ParametricCallable.class;
|
||||
}
|
||||
}
|
@ -20,23 +20,24 @@
|
||||
package com.sk89q.worldedit.util.command.parametric;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.util.StringUtil;
|
||||
import com.sk89q.worldedit.util.command.MissingParameterException;
|
||||
import com.sk89q.util.StringUtil;
|
||||
|
||||
/**
|
||||
* A virtual scope that does not actually read from the underlying
|
||||
* A virtual scope that does not actually read from the underlying
|
||||
* {@link CommandContext}.
|
||||
*/
|
||||
public class StringArgumentStack implements ArgumentStack {
|
||||
|
||||
|
||||
private final boolean nonNullBoolean;
|
||||
private final CommandContext context;
|
||||
private final String[] arguments;
|
||||
private int markedIndex = 0;
|
||||
private int index = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance using the given context.
|
||||
*
|
||||
*
|
||||
* @param context the context
|
||||
* @param arguments a list of arguments
|
||||
* @param nonNullBoolean true to have {@link #nextBoolean()} return false instead of null
|
||||
@ -47,10 +48,10 @@ public class StringArgumentStack implements ArgumentStack {
|
||||
this.arguments = arguments;
|
||||
this.nonNullBoolean = nonNullBoolean;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance using the given context.
|
||||
*
|
||||
*
|
||||
* @param context the context
|
||||
* @param arguments an argument string to be parsed
|
||||
* @param nonNullBoolean true to have {@link #nextBoolean()} return false instead of null
|
||||
@ -99,7 +100,7 @@ public class StringArgumentStack implements ArgumentStack {
|
||||
if (nonNullBoolean) { // Special case
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
throw new MissingParameterException();
|
||||
}
|
||||
}
|
||||
@ -125,4 +126,32 @@ public class StringArgumentStack implements ArgumentStack {
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the current position of the stack.
|
||||
*
|
||||
* <p>The marked position initially starts at 0.</p>
|
||||
*/
|
||||
@Override
|
||||
public void mark() {
|
||||
markedIndex = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset to the previously {@link #mark()}ed position of the stack, and return
|
||||
* the arguments that were consumed between this point and that previous point.
|
||||
*
|
||||
* <p>The marked position initially starts at 0.</p>
|
||||
*
|
||||
* @return the consumed arguments
|
||||
*/
|
||||
@Override
|
||||
public String reset() {
|
||||
String value = context.getString(markedIndex, index - 1);
|
||||
index = markedIndex;
|
||||
return value;
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return StringArgumentStack.class;
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,10 @@
|
||||
|
||||
package com.sk89q.worldedit.util.eventbus;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Event handler object for {@link EventBus} that is able to dispatch
|
||||
* an event.
|
||||
|
@ -23,11 +23,7 @@ import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.sk89q.worldedit.internal.annotation.RequiresNewerGuava;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Holds a cache of class hierarchy.
|
||||
|
@ -19,10 +19,10 @@
|
||||
|
||||
package com.sk89q.worldedit.util.eventbus;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Invokes a {@link Method} to dispatch an event.
|
||||
*/
|
||||
|
@ -19,12 +19,12 @@
|
||||
|
||||
package com.sk89q.worldedit.util.eventbus;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
|
||||
/**
|
||||
* Used to mark methods as event handlers.
|
||||
*/
|
||||
|
@ -25,12 +25,12 @@ package com.sk89q.worldedit.util.formatting;
|
||||
public class Fragment {
|
||||
|
||||
private final StringBuilder builder = new StringBuilder();
|
||||
|
||||
Fragment() {
|
||||
|
||||
public Fragment() {
|
||||
}
|
||||
|
||||
public Fragment append(String str) {
|
||||
builder.append(Style.stripColor(str));
|
||||
builder.append(str);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -88,5 +88,8 @@ public class Fragment {
|
||||
public String toString() {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
|
||||
public static Class<?> inject() {
|
||||
return Fragment.class;
|
||||
}
|
||||
}
|
||||
|
@ -19,14 +19,14 @@
|
||||
|
||||
package com.sk89q.worldedit.util.formatting;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* All supported color values for chat.
|
||||
*
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
package com.sk89q.worldedit.util.formatting.component;
|
||||
|
||||
import com.sk89q.worldedit.util.formatting.Style;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
|
||||
public class CommandListBox extends MessageBox {
|
||||
|
||||
@ -35,13 +35,19 @@ public class CommandListBox extends MessageBox {
|
||||
}
|
||||
|
||||
public CommandListBox appendCommand(String alias, String description) {
|
||||
return appendCommand(alias, description, true);
|
||||
}
|
||||
|
||||
public CommandListBox appendCommand(String alias, String description, boolean allowed) {
|
||||
if (!first) {
|
||||
getContents().newLine();
|
||||
}
|
||||
getContents().createFragment(Style.YELLOW_DARK).append(alias).append(": ");
|
||||
getContents().append(description);
|
||||
getContents().append((allowed ? BBC.HELP_ITEM_ALLOWED : BBC.HELP_ITEM_DENIED).format(alias, description));
|
||||
first = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return CommandListBox.class;
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,7 @@
|
||||
|
||||
package com.sk89q.worldedit.util.formatting.component;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.extension.platform.CommandManager;
|
||||
import com.sk89q.worldedit.util.command.CommandCallable;
|
||||
@ -28,13 +27,16 @@ 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.util.command.PrimaryAliasComparator;
|
||||
import com.sk89q.worldedit.util.formatting.Style;
|
||||
import com.sk89q.worldedit.util.formatting.StyledFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* A box to describe usage of a command.
|
||||
*/
|
||||
@ -43,7 +45,7 @@ public class CommandUsageBox extends StyledFragment {
|
||||
/**
|
||||
* Create a new usage box.
|
||||
*
|
||||
* @param command the command to describe
|
||||
* @param command the command to describe
|
||||
* @param commandString the command that was used, such as "/we" or "/brush sphere"
|
||||
*/
|
||||
public CommandUsageBox(CommandCallable command, String commandString) {
|
||||
@ -53,9 +55,9 @@ public class CommandUsageBox extends StyledFragment {
|
||||
/**
|
||||
* Create a new usage box.
|
||||
*
|
||||
* @param command the command to describe
|
||||
* @param command the command to describe
|
||||
* @param commandString the command that was used, such as "/we" or "/brush sphere"
|
||||
* @param locals list of locals to use
|
||||
* @param locals list of locals to use
|
||||
*/
|
||||
public CommandUsageBox(CommandCallable command, String commandString, @Nullable CommandLocals locals) {
|
||||
checkNotNull(command);
|
||||
@ -68,34 +70,34 @@ public class CommandUsageBox extends StyledFragment {
|
||||
}
|
||||
|
||||
private void attachDispatcherUsage(Dispatcher dispatcher, String commandString, @Nullable CommandLocals locals) {
|
||||
CommandListBox box = new CommandListBox("Subcommands");
|
||||
CommandListBox box = new CommandListBox(BBC.HELP_HEADER_SUBCOMMANDS.f());
|
||||
String prefix = !commandString.isEmpty() ? commandString + " " : "";
|
||||
|
||||
List<CommandMapping> list = new ArrayList<>(dispatcher.getCommands());
|
||||
list.sort(new PrimaryAliasComparator(CommandManager.COMMAND_CLEAN_PATTERN));
|
||||
List<CommandMapping> list = new ArrayList<CommandMapping>(dispatcher.getCommands());
|
||||
Collections.sort(list, new PrimaryAliasComparator(CommandManager.COMMAND_CLEAN_PATTERN));
|
||||
|
||||
for (CommandMapping mapping : list) {
|
||||
if (locals == null || mapping.getCallable().testPermission(locals)) {
|
||||
box.appendCommand(prefix + mapping.getPrimaryAlias(), mapping.getDescription().getDescription());
|
||||
}
|
||||
boolean perm = locals == null || mapping.getCallable().testPermission(locals);
|
||||
box.appendCommand(prefix + mapping.getPrimaryAlias(), mapping.getDescription().getDescription(), perm);
|
||||
}
|
||||
|
||||
append(box);
|
||||
}
|
||||
|
||||
private void attachCommandUsage(Description description, String commandString) {
|
||||
MessageBox box = new MessageBox("Help for " + commandString);
|
||||
MessageBox box = new MessageBox(BBC.HELP_HEADER_COMMAND.f(commandString));
|
||||
StyledFragment contents = box.getContents();
|
||||
|
||||
if (description.getUsage() != null) {
|
||||
contents.append(new Label().append("Usage: "));
|
||||
contents.append(description.getUsage());
|
||||
contents.append(new Label().append(BBC.COMMAND_SYNTAX.f(description.getUsage())));
|
||||
} else {
|
||||
contents.createFragment(Style.GRAY);
|
||||
contents.append(new Subtle().append("Usage information is not available."));
|
||||
}
|
||||
|
||||
contents.newLine();
|
||||
|
||||
contents.createFragment(Style.GRAY);
|
||||
if (description.getHelp() != null) {
|
||||
contents.append(description.getHelp());
|
||||
} else if (description.getDescription() != null) {
|
||||
@ -107,4 +109,8 @@ public class CommandUsageBox extends StyledFragment {
|
||||
append(box);
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return CommandUsageBox.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,12 +19,11 @@
|
||||
|
||||
package com.sk89q.worldedit.util.formatting.component;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.worldedit.util.formatting.ColorCodeBuilder;
|
||||
import com.sk89q.worldedit.util.formatting.Style;
|
||||
import com.sk89q.worldedit.util.formatting.StyledFragment;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Makes for a box with a border above and below.
|
||||
*/
|
||||
@ -37,38 +36,21 @@ public class MessageBox extends StyledFragment {
|
||||
*/
|
||||
public MessageBox(String title) {
|
||||
checkNotNull(title);
|
||||
|
||||
int leftOver = ColorCodeBuilder.GUARANTEED_NO_WRAP_CHAT_PAGE_WIDTH - title.length() - 2;
|
||||
int leftSide = (int) Math.floor(leftOver * 1.0/3);
|
||||
int rightSide = (int) Math.floor(leftOver * 2.0/3);
|
||||
if (leftSide > 0) {
|
||||
createFragment(Style.YELLOW).append(createBorder(leftSide));
|
||||
}
|
||||
append(" ");
|
||||
append(title);
|
||||
append(" ");
|
||||
if (rightSide > 0) {
|
||||
createFragment(Style.YELLOW).append(createBorder(rightSide));
|
||||
}
|
||||
newLine();
|
||||
append(contents);
|
||||
}
|
||||
|
||||
private String createBorder(int count) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < count; i++) {
|
||||
builder.append("-");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the internal contents.
|
||||
*
|
||||
*
|
||||
* @return the contents
|
||||
*/
|
||||
public StyledFragment getContents() {
|
||||
return contents;
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return MessageBox.class;
|
||||
}
|
||||
}
|
||||
|
@ -19,13 +19,12 @@
|
||||
|
||||
package com.sk89q.worldedit.util.function;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Provides a Levenshtein distance between a given string and each string
|
||||
|
@ -19,8 +19,6 @@
|
||||
|
||||
package com.sk89q.worldedit.util.io;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Throwables;
|
||||
|
||||
@ -33,6 +31,8 @@ import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public final class Closer implements Closeable {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(Closer.class.getCanonicalName());
|
||||
|
@ -19,15 +19,9 @@
|
||||
|
||||
package com.sk89q.worldedit.util.logging;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.logging.Filter;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.SimpleFormatter;
|
||||
import java.util.logging.StreamHandler;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.logging.*;
|
||||
|
||||
/**
|
||||
* A {@link StreamHandler} delegate that allows for the swap and disable of
|
||||
|
@ -19,11 +19,11 @@
|
||||
|
||||
package com.sk89q.worldedit.util.logging;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Date;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* A standard logging format for WorldEdit.
|
||||
|
Reference in New Issue
Block a user