diff --git a/build.gradle b/build.gradle
index 3aef1232..e4ae9cc4 100644
--- a/build.gradle
+++ b/build.gradle
@@ -78,6 +78,10 @@ subprojects {
sourceCompatibility = 1.8
targetCompatibility = 1.8
+ compileJava {
+ options.compilerArgs += ["-parameters"]
+ }
+
repositories {
mavenCentral()
maven {url "http://repo.dmulloy2.net/content/groups/public/"}
diff --git a/core/src/main/java/com/boydti/fawe/Fawe.java b/core/src/main/java/com/boydti/fawe/Fawe.java
index 1e053545..a972a1fe 100644
--- a/core/src/main/java/com/boydti/fawe/Fawe.java
+++ b/core/src/main/java/com/boydti/fawe/Fawe.java
@@ -133,6 +133,7 @@ import com.sk89q.worldedit.util.formatting.Fragment;
import com.sk89q.worldedit.util.formatting.component.CommandListBox;
import com.sk89q.worldedit.util.formatting.component.CommandUsageBox;
import com.sk89q.worldedit.util.formatting.component.MessageBox;
+import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.io.File;
import java.io.FileNotFoundException;
@@ -560,6 +561,8 @@ public class Fawe {
Vector2D.inject(); // Optimizations
// Block
BaseBlock.inject(); // Optimizations
+ // Biome
+ BaseBiome.inject(); // Features
// Pattern
ArbitraryShape.inject(); // Optimizations + update from legacy code
Pattern.inject(); // Simplify API
diff --git a/core/src/main/java/com/boydti/fawe/config/Settings.java b/core/src/main/java/com/boydti/fawe/config/Settings.java
index fef4fe93..97553bef 100644
--- a/core/src/main/java/com/boydti/fawe/config/Settings.java
+++ b/core/src/main/java/com/boydti/fawe/config/Settings.java
@@ -74,6 +74,7 @@ public class Settings extends Config {
public String TEXTURES = "textures";
public String HEIGHTMAP = "heightmap";
public String HISTORY = "history";
+ @Comment("Multiple servers can use the same clipboards")
public String CLIPBOARD = "clipboard";
@Comment("Each player has their own sub directory for schematics")
public boolean PER_PLAYER_SCHEMATICS = true;
@@ -145,18 +146,19 @@ public class Settings extends Config {
" - Frees up a lot of memory",
" - Persists restarts",
" - Unlimited undo",
- " - Enables the rollback command"
+ " - Does not affect edit performance if `combine-stages`",
})
public boolean USE_DISK = true;
@Comment({
"Use a database to store disk storage summaries:",
- " - Faster lookups and rollback from disk",
+ " - Enables inspection and rollback",
+ " - Does not impact performance",
})
public boolean USE_DATABASE = true;
@Comment({
"Record history with dispatching:",
- " - Faster as it avoids duplicate block checks",
- " - Worse compression since dispatch order is different"
+ " - Much faster as it avoids duplicate block checks",
+ " - Slightly worse compression since dispatch order is different",
})
public boolean COMBINE_STAGES = true;
@Comment({
diff --git a/core/src/main/java/com/boydti/fawe/util/DocumentationPrinter.java b/core/src/main/java/com/boydti/fawe/util/DocumentationPrinter.java
index 8883bf14..a55b4e4a 100644
--- a/core/src/main/java/com/boydti/fawe/util/DocumentationPrinter.java
+++ b/core/src/main/java/com/boydti/fawe/util/DocumentationPrinter.java
@@ -101,7 +101,7 @@ public final class DocumentationPrinter {
writePermissionsWikiTable(stream, builder, "/", RegionCommands.class);
writePermissionsWikiTable(stream, builder, "/", SelectionCommands.class);
writePermissionsWikiTable(stream, builder, "/", HistoryCommands.class);
- writePermissionsWikiTable(stream, builder, "/", SchematicCommands.class);
+ writePermissionsWikiTable(stream, builder, "/schematic ", SchematicCommands.class);
writePermissionsWikiTable(stream, builder, "/", ClipboardCommands.class);
writePermissionsWikiTable(stream, builder, "/", GenerationCommands.class);
writePermissionsWikiTable(stream, builder, "/", BiomeCommands.class);
@@ -116,9 +116,9 @@ public final class DocumentationPrinter {
writePermissionsWikiTable(stream, builder, "/", BrushOptionsCommands.class);
writePermissionsWikiTable(stream, builder, "/tool ", ToolCommands.class);
writePermissionsWikiTable(stream, builder, "/brush ", BrushCommands.class);
- writePermissionsWikiTable(stream, builder, "", MaskCommands.class);
- writePermissionsWikiTable(stream, builder, "", PatternCommands.class);
- writePermissionsWikiTable(stream, builder, "", TransformCommands.class);
+ writePermissionsWikiTable(stream, builder, "", MaskCommands.class, "/Masks");
+ writePermissionsWikiTable(stream, builder, "", PatternCommands.class, "/Patterns");
+ writePermissionsWikiTable(stream, builder, "", TransformCommands.class, "/Transforms");
stream.println();
stream.print("#### Uncategorized\n");
stream.append("| Aliases | Permission | flags | Usage |\n");
@@ -133,21 +133,28 @@ public final class DocumentationPrinter {
}
private static void writePermissionsWikiTable(PrintStream stream, StringBuilder content, String prefix, Class> cls) {
- String title = cls.getSimpleName().replaceAll("(\\p{Ll})(\\p{Lu})", "$1 $2");
- stream.print(" - [`" + title + "`](#" + title.replaceAll(" ", "-").toLowerCase() + "-) ");
+ writePermissionsWikiTable(stream, content, prefix, cls, getName(cls));
+ }
+
+ public static String getName(Class cls) {
+ return cls.getSimpleName().replaceAll("(\\p{Ll})(\\p{Lu})", "$1 $2");
+ }
+
+ private static void writePermissionsWikiTable(PrintStream stream, StringBuilder content, String prefix, Class> cls, String name) {
+ stream.print(" - [`" + name + "`](#" + name.replaceAll(" ", "-").toLowerCase() + "-edittop) ");
Command cmd = cls.getAnnotation(Command.class);
if (cmd != null) {
stream.print(" (" + cmd.desc() + ")");
}
stream.println();
- writePermissionsWikiTable(content, prefix, cls, true);
+ writePermissionsWikiTable(content, prefix, cls, name, true);
}
- private static void writePermissionsWikiTable(StringBuilder stream, String prefix, Class> cls, boolean title) {
+ private static void writePermissionsWikiTable(StringBuilder stream, String prefix, Class> cls, String name, boolean title) {
// //setbiome || worldedit.biome.set || //setbiome || p || Sets the biome of the player's current block or region.
if (title) {
String path = "https://github.com/boy0001/FastAsyncWorldedit/edit/master/core/src/main/java/" + cls.getName().replaceAll("\\.", "/") + ".java";
- stream.append("### **" + cls.getSimpleName().replaceAll("(\\p{Ll})(\\p{Lu})", "$1 $2") + "** [`✎`](" + path + ")[`▲`](#overview)");
+ stream.append("### **" + name + "** `[`[`edit`](" + path + ")`|`[`top`](#overview)`]`");
stream.append("\n");
Command cmd = cls.getAnnotation(Command.class);
if (cmd != null) {
@@ -191,7 +198,7 @@ public final class DocumentationPrinter {
Class>[] nestedClasses = nested.value();
for (Class clazz : nestedClasses) {
- writePermissionsWikiTable(stream, prefix + cmd.aliases()[0] + " ", clazz, false);
+ writePermissionsWikiTable(stream, prefix + cmd.aliases()[0] + " ", clazz, getName(clazz), false);
}
}
}
diff --git a/core/src/main/java/com/boydti/fawe/util/MainUtil.java b/core/src/main/java/com/boydti/fawe/util/MainUtil.java
index 8c01c16e..8151216e 100644
--- a/core/src/main/java/com/boydti/fawe/util/MainUtil.java
+++ b/core/src/main/java/com/boydti/fawe/util/MainUtil.java
@@ -39,6 +39,7 @@ import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
@@ -144,6 +145,31 @@ public class MainUtil {
return result;
}
+ public static T getOf(Object[] arr, Class ofType) {
+ for (Object a : arr) {
+ if (a != null && a.getClass() == ofType) {
+ return (T) a;
+ }
+ }
+ return null;
+ }
+
+ public static String[] getParameterNames(Method method) {
+ Parameter[] parameters = method.getParameters();
+ List parameterNames = new ArrayList<>();
+
+ for (Parameter parameter : parameters) {
+ if(!parameter.isNamePresent()) {
+ throw new IllegalArgumentException("Parameter names are not present!");
+ }
+
+ String parameterName = parameter.getName();
+ parameterNames.add(parameterName);
+ }
+
+ return parameterNames.toArray(new String[parameterNames.size()]);
+ }
+
public static long getTotalSize(Path path) {
final AtomicLong size = new AtomicLong(0);
traverse(path, new RunnableVal2() {
diff --git a/core/src/main/java/com/boydti/fawe/util/StringMan.java b/core/src/main/java/com/boydti/fawe/util/StringMan.java
index bf7b52cb..9f318c26 100644
--- a/core/src/main/java/com/boydti/fawe/util/StringMan.java
+++ b/core/src/main/java/com/boydti/fawe/util/StringMan.java
@@ -296,14 +296,21 @@ public class StringMan {
}
public static String join(final Object[] array, final String delimiter) {
- final StringBuilder result = new StringBuilder();
- for (int i = 0, j = array.length; i < j; i++) {
- if (i > 0) {
- result.append(delimiter);
- }
- result.append(array[i]);
+ switch (array.length) {
+ case 0:
+ return "";
+ case 1:
+ return array[0].toString();
+ default:
+ final StringBuilder result = new StringBuilder();
+ for (int i = 0, j = array.length; i < j; i++) {
+ if (i > 0) {
+ result.append(delimiter);
+ }
+ result.append(array[i]);
+ }
+ return result.toString();
}
- return result.toString();
}
public static String join(final int[] array, final String delimiter) {
diff --git a/core/src/main/java/com/boydti/fawe/util/chat/UsageMessage.java b/core/src/main/java/com/boydti/fawe/util/chat/UsageMessage.java
new file mode 100644
index 00000000..d2fb96e5
--- /dev/null
+++ b/core/src/main/java/com/boydti/fawe/util/chat/UsageMessage.java
@@ -0,0 +1,158 @@
+package com.boydti.fawe.util.chat;
+
+import com.boydti.fawe.config.BBC;
+import com.boydti.fawe.config.Commands;
+import com.boydti.fawe.util.MainUtil;
+import com.boydti.fawe.util.StringMan;
+import com.sk89q.minecraft.util.commands.CommandLocals;
+import com.sk89q.minecraft.util.commands.Link;
+import com.sk89q.worldedit.WorldEdit;
+import com.sk89q.worldedit.extension.platform.CommandManager;
+import com.sk89q.worldedit.util.command.CommandCallable;
+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.Parameter;
+import com.sk89q.worldedit.util.command.PrimaryAliasComparator;
+import com.sk89q.worldedit.util.command.binding.Range;
+import com.sk89q.worldedit.util.command.parametric.ParameterData;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.annotation.Nullable;
+
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class UsageMessage extends Message {
+ /**
+ * Create a new usage box.
+ *
+ * @param command the command to describe
+ * @param commandString the command that was used, such as "/we" or "/brush sphere"
+ */
+ public UsageMessage(CommandCallable command, String commandString) {
+ this(command, commandString, null);
+ }
+
+ /**
+ * Create a new usage box.
+ *
+ * @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
+ */
+ public UsageMessage(CommandCallable command, String commandString, @Nullable CommandLocals locals) {
+ checkNotNull(command);
+ checkNotNull(commandString);
+ if (command instanceof Dispatcher) {
+ attachDispatcherUsage((Dispatcher) command, commandString, locals);
+ } else {
+ attachCommandUsage(command.getDescription(), commandString);
+ }
+ }
+
+ private void attachDispatcherUsage(Dispatcher dispatcher, String commandString, @Nullable CommandLocals locals) {
+ prefix();
+ text(BBC.HELP_HEADER_SUBCOMMANDS.f());
+ String prefix = !commandString.isEmpty() ? commandString + " " : "";
+
+ List list = new ArrayList(dispatcher.getCommands());
+ Collections.sort(list, new PrimaryAliasComparator(CommandManager.COMMAND_CLEAN_PATTERN));
+
+ for (CommandMapping mapping : list) {
+ boolean perm = locals == null || mapping.getCallable().testPermission(locals);
+ newline();
+ String cmd = prefix + mapping.getPrimaryAlias();
+ text((perm ? BBC.HELP_ITEM_ALLOWED : BBC.HELP_ITEM_DENIED).format(cmd, mapping.getDescription().getDescription()));
+ cmdTip(cmd);
+ }
+ }
+
+ private void attachCommandUsage(Description description, String commandString) {
+ List params = description.getParameters();
+ String[] usage;
+ if (description.getUsage() != null) {
+ usage = description.getUsage().split(" ", params.size());
+ } else {
+ usage = new String[params.size()];
+ for (int i = 0; i < usage.length; i++) {
+ Parameter param = params.get(i);
+ boolean optional = param.isValueFlag() || param.isOptional();
+ String arg;
+ if (param.getFlag() != null) {
+ arg = "-" + param.getFlag();
+ if (param.isValueFlag())
+ arg += param.getName();
+ } else {
+ arg = param.getName();
+ if (param.getDefaultValue() != null && param.getDefaultValue().length > 0)
+ arg += "=" + StringMan.join(param.getDefaultValue(), ",");
+ }
+ usage[i] = optional ? ("[" + arg + "]") : ("<" + arg + ">");
+ }
+ }
+
+ prefix();
+ text("&cUsage: ");
+ commandString = (WorldEdit.getInstance().getConfiguration().noDoubleSlash ? "" : "/") + commandString;
+ text("&7" + commandString);
+ suggestTip(commandString + " ");
+ for (int i = 0; i < usage.length; i++) {
+ String argStr = usage[i];
+ text(" " + argStr.replaceAll("[\\[|\\]|<|>]", "&8$0&7"));
+
+ if (params.isEmpty()) continue;
+ Parameter param = params.get(i);
+
+ StringBuilder tooltip = new StringBuilder();
+ String command = null;
+ String webpage = null;
+
+ tooltip.append("Name: " + param.getName());
+ if (param instanceof ParameterData) {
+ ParameterData pd = (ParameterData) param;
+ Type type = pd.getType();
+ if (type instanceof Class) {
+ tooltip.append("\nType: " + ((Class) type).getSimpleName());
+ }
+
+ Range range = MainUtil.getOf(pd.getModifiers(), Range.class);
+ if (range != null) {
+ String min = range.min() == Double.MIN_VALUE ? "(-∞" : ("[" + range.min());
+ String max = range.max() == Double.MAX_VALUE ? "∞)" : (range.max() + "]");
+ tooltip.append("\nRange: " + min + "," + max);
+ }
+ if (type instanceof Class) {
+ Link link = (Link) ((Class) type).getAnnotation(Link.class);
+ if (link != null) {
+ if (link.value().startsWith("http")) webpage = link.value();
+ else command = Commands.getAlias(link.clazz(), link.value());
+ }
+ }
+ }
+ tooltip.append("\nOptional: " + (param.isOptional() || param.isValueFlag()));
+ if (param.getDefaultValue() != null && param.getDefaultValue().length >= 0) {
+ tooltip.append("\nDefault: " + param.getDefaultValue()[0]);
+ } else if (argStr.contains("=")) {
+ tooltip.append("\nDefault: " + argStr.split("[=|\\]|>]")[1]);
+ }
+ if (command != null || webpage != null) {
+ tooltip.append("\nClick for more info");
+ }
+ tooltip(tooltip.toString());
+ if (command != null) command(command);
+ if (webpage != null) link(webpage);
+ }
+
+ newline();
+ if (description.getHelp() != null) {
+ text("&cHelp: &7" + description.getHelp());
+ } else if (description.getDescription() != null) {
+ text("&cDescription: &7" + description.getDescription());
+ } else {
+ text("No further help is available.");
+ }
+ }
+}
diff --git a/core/src/main/java/com/sk89q/minecraft/util/commands/Link.java b/core/src/main/java/com/sk89q/minecraft/util/commands/Link.java
new file mode 100644
index 00000000..297af2be
--- /dev/null
+++ b/core/src/main/java/com/sk89q/minecraft/util/commands/Link.java
@@ -0,0 +1,11 @@
+package com.sk89q.minecraft.util.commands;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Link {
+
+ Class clazz() default Link.class;
+ String value();
+}
diff --git a/core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java b/core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java
index 9fe94f31..7f89fbed 100644
--- a/core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java
+++ b/core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java
@@ -25,6 +25,7 @@ import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
+import com.sk89q.minecraft.util.commands.Link;
import com.sk89q.worldedit.CuboidClipboard.FlipDirection;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
@@ -63,6 +64,7 @@ import javax.annotation.Nullable;
* more appropriate.
*/
@SuppressWarnings("deprecation")
+@Link(value = "http://minecraft-ids.grahamedgecombe.com")
public class BaseBlock implements TileEntityBlock, Pattern, Serializable {
/**
diff --git a/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java b/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java
index f08f8eaa..aac7940c 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java
@@ -506,7 +506,7 @@ public class BrushCommands extends MethodCommands {
@Command(
aliases = {"cylinder", "cyl", "c"},
- usage = " [radius=2] [height=1]",
+ usage = " [radius=2] [height=1]",
flags = "h",
desc = "Creates a cylinder",
help =
@@ -633,7 +633,7 @@ public class BrushCommands extends MethodCommands {
" - The `-r` flag enables random off-axis rotation\n" +
" - The `-l` flag will work on snow layers\n" +
" - The `-s` flag disables smoothing\n" +
- "Note: Note: Use a negative yscale to reduce height\n" +
+ "Note: Use a negative yscale to reduce height\n" +
"Snow Pic: https://i.imgur.com/Hrzn0I4.png",
min = 1,
max = 4
diff --git a/core/src/main/java/com/sk89q/worldedit/command/BrushOptionsCommands.java b/core/src/main/java/com/sk89q/worldedit/command/BrushOptionsCommands.java
index 98b61446..d2e99766 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/BrushOptionsCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/BrushOptionsCommands.java
@@ -1,7 +1,6 @@
package com.sk89q.worldedit.command;
import com.boydti.fawe.Fawe;
-import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.brush.BrushSettings;
import com.boydti.fawe.object.brush.TargetMode;
@@ -22,14 +21,12 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.platform.CommandEvent;
-import com.sk89q.worldedit.extension.factory.DefaultMaskParser;
-import com.sk89q.worldedit.extension.factory.DefaultTransformParser;
-import com.sk89q.worldedit.extension.factory.HashTagPatternParser;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.CommandManager;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.Pattern;
+import com.sk89q.worldedit.util.command.binding.Range;
import com.sk89q.worldedit.util.command.binding.Switch;
import com.sk89q.worldedit.util.command.parametric.Optional;
import java.io.DataInputStream;
@@ -185,64 +182,9 @@ public class BrushOptionsCommands extends MethodCommands {
}
}
- @Command(
- aliases = {"patterns"},
- usage = "[page=1|search|pattern]",
- desc = "View help about patterns",
- help = "Patterns determine what blocks are placed\n" +
- " - Use [brackets] for arguments\n" +
- " - Use , to OR multiple\n" +
- "e.g. #surfacespread[10][#existing],andesite\n" +
- "More Info: https://git.io/vSPmA",
- min = 1
- )
- public void patterns(Player player, LocalSession session, CommandContext args) throws WorldEditException {
- HashTagPatternParser parser = FaweAPI.getParser(HashTagPatternParser.class);
- if (parser != null) {
- UtilityCommands.help(args, worldEdit, player, "/" + getCommand().aliases()[0] + " ", parser.getDispatcher());
- }
- }
-
- @Command(
- aliases = {"masks"},
- usage = "[page=1|search|mask]",
- desc = "View help about masks",
- help = "Masks determine if a block can be placed\n" +
- " - Use [brackets] for arguments\n" +
- " - Use , to OR multiple\n" +
- " - Use & to AND multiple\n" +
- "e.g. >[stone,dirt],#light[0][5],$jungle\n" +
- "More Info: https://git.io/v9r4K",
- min = 1
- )
- public void masks(Player player, LocalSession session, CommandContext args) throws WorldEditException {
- DefaultMaskParser parser = FaweAPI.getParser(DefaultMaskParser.class);
- if (parser != null) {
- UtilityCommands.help(args, worldEdit, player, "/" + getCommand().aliases()[0] + " ", parser.getDispatcher());
- }
- }
-
- @Command(
- aliases = {"transforms"},
- usage = "[page=1|search|transform]",
- desc = "View help about transforms",
- help = "Transforms modify how a block is placed\n" +
- " - Use [brackets] for arguments\n" +
- " - Use , to OR multiple\n" +
- " - Use & to AND multiple\n" +
- "More Info: https://git.io/v9KHO",
- min = 1
- )
- public void transforms(Player player, LocalSession session, CommandContext args) throws WorldEditException {
- DefaultTransformParser parser = Fawe.get().getTransformParser();
- if (parser != null) {
- UtilityCommands.help(args, worldEdit, player, "/" + getCommand().aliases()[0] + " ", parser.getDispatcher());
- }
- }
-
@Command(
aliases = {"primary"},
- usage = "[brush arguments]",
+ usage = "[brush-arguments]",
desc = "Set the right click brush",
help = "Set the right click brush",
min = 1
@@ -262,7 +204,7 @@ public class BrushOptionsCommands extends MethodCommands {
@Command(
aliases = {"secondary"},
- usage = "[brush arguments]",
+ usage = "[brush-arguments]",
desc = "Set the left click brush",
help = "Set the left click brush",
min = 1
@@ -291,7 +233,7 @@ public class BrushOptionsCommands extends MethodCommands {
min = 0,
max = 1
)
- public void visual(Player player, LocalSession session, int mode) throws WorldEditException {
+ public void visual(Player player, LocalSession session, @Range(min = 0, max = 2)int mode) throws WorldEditException {
BrushTool tool = session.getBrushTool(player, false);
if (tool == null) {
BBC.BRUSH_NONE.send(player);
diff --git a/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java b/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java
index 27bc44e2..32dce91e 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java
@@ -164,7 +164,7 @@ public class GenerationCommands extends MethodCommands {
)
@CommandPermissions("worldedit.generation.ore")
@Logging(PLACEMENT)
- public void ore(FawePlayer player, LocalSession session, EditSession editSession, @Selection Region region, Mask mask, Pattern material, int size, int freq, int rarity, int minY, int maxY, CommandContext context) throws WorldEditException, ParameterException {
+ public void ore(FawePlayer player, LocalSession session, EditSession editSession, @Selection Region region, Mask mask, Pattern material, @Range(min = 0) int size, int freq, @Range(min = 0, max = 100) int rarity, @Range(min = 0, max = 255) int minY, @Range(min = 0, max = 255) int maxY, CommandContext context) throws WorldEditException, ParameterException {
player.checkConfirmationRegion(getArguments(context), region);
editSession.addOre(region, mask, material, size, freq, rarity, minY, maxY);
BBC.VISITOR_BLOCK.send(player, editSession.getBlockChangeCount());
@@ -190,7 +190,7 @@ public class GenerationCommands extends MethodCommands {
@Command(
aliases = {"/cyl"},
- usage = " [,] [height]",
+ usage = " [,] [height]",
flags = "h",
desc = "Generates a cylinder.",
help =
@@ -235,7 +235,7 @@ public class GenerationCommands extends MethodCommands {
@Command(
aliases = {"/hsphere"},
- usage = " [,,] [raised?]",
+ usage = " [,,] [raised?]",
desc = "Generates a hollow sphere.",
help =
"Generates a hollow sphere.\n" +
@@ -253,7 +253,7 @@ public class GenerationCommands extends MethodCommands {
@Command(
aliases = {"/sphere"},
- usage = " [,,] [raised?]",
+ usage = " [,,] [raised?]",
flags = "h",
desc = "Generates a filled sphere.",
help =
@@ -303,7 +303,7 @@ public class GenerationCommands extends MethodCommands {
@Command(
aliases = {"forestgen"},
- usage = "[size] [type] [density]",
+ usage = "[size] [tree-type] [density]",
desc = "Generate a forest",
min = 0,
max = 3
@@ -333,7 +333,7 @@ public class GenerationCommands extends MethodCommands {
@Command(
aliases = {"/hpyramid"},
- usage = " ",
+ usage = " ",
desc = "Generate a hollow pyramid",
min = 2,
max = 2
@@ -346,7 +346,7 @@ public class GenerationCommands extends MethodCommands {
@Command(
aliases = {"/pyramid"},
- usage = " ",
+ usage = " ",
flags = "h",
desc = "Generate a filled pyramid",
min = 2,
@@ -365,7 +365,7 @@ public class GenerationCommands extends MethodCommands {
@Command(
aliases = {"/generate", "/gen", "/g"},
- usage = " ",
+ usage = " ",
desc = "Generates a shape according to a formula.",
help =
"Generates a shape according to a formula that is expected to\n" +
diff --git a/core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java b/core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java
index f75275ae..400b7648 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java
@@ -44,6 +44,7 @@ import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.WorldVector;
import com.sk89q.worldedit.entity.Player;
+import com.sk89q.worldedit.util.command.binding.Range;
import com.sk89q.worldedit.util.command.parametric.Optional;
import com.sk89q.worldedit.world.World;
import java.io.File;
@@ -81,7 +82,7 @@ public class HistoryCommands {
max = 3
)
@CommandPermissions("worldedit.history.rollback")
- public void faweRollback(final Player player, LocalSession session, final String user, @Optional("0") int radius, @Optional("0") String time) throws WorldEditException {
+ public void faweRollback(final Player player, LocalSession session, final String user, @Optional("0") @Range(min = 0) int radius, @Optional("0") String time) throws WorldEditException {
if (!Settings.IMP.HISTORY.USE_DATABASE) {
BBC.SETTING_DISABLE.send(player, "history.use-database (Import with /frb #import )");
return;
diff --git a/core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java b/core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java
index 16693e82..ca73d067 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java
@@ -192,7 +192,7 @@ public class NavigationCommands {
@Command(
aliases = {"up"},
- usage = "",
+ usage = "",
desc = "Go upwards some distance",
flags = "fg",
min = 1,
diff --git a/core/src/main/java/com/sk89q/worldedit/command/PatternCommands.java b/core/src/main/java/com/sk89q/worldedit/command/PatternCommands.java
index 1497d9ad..827c9948 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/PatternCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/PatternCommands.java
@@ -53,6 +53,7 @@ import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
import com.sk89q.worldedit.session.ClipboardHolder;
+import com.sk89q.worldedit.util.command.binding.Range;
import com.sk89q.worldedit.util.command.parametric.Optional;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.awt.Color;
@@ -263,7 +264,7 @@ public class PatternCommands extends MethodCommands {
min = 2,
max = 2
)
- public Pattern iddatamask(Actor actor, LocalSession session, Extent extent, int bitmask, Pattern pattern) {
+ public Pattern iddatamask(Actor actor, LocalSession session, Extent extent, @Range(min = 0, max = 15) int bitmask, Pattern pattern) {
return new IdDataMaskPattern(extent, pattern, bitmask);
}
diff --git a/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
index 44e2906f..587cad65 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
@@ -188,7 +188,7 @@ public class RegionCommands extends MethodCommands {
max = 1
)
@CommandPermissions("worldedit.light.set")
- public void setlighting(Player player, @Selection Region region, int value) {
+ public void setlighting(Player player, @Selection Region region, @Range(min = 0, max = 15) int value) {
FawePlayer fp = FawePlayer.wrap(player);
final FaweLocation loc = fp.getLocation();
final int cx = loc.x >> 4;
@@ -212,7 +212,7 @@ public class RegionCommands extends MethodCommands {
max = 1
)
@CommandPermissions("worldedit.light.set")
- public void setskylighting(Player player, @Selection Region region, int value) {
+ public void setskylighting(Player player, @Selection Region region, @Range(min = 0, max = 15) int value) {
FawePlayer fp = FawePlayer.wrap(player);
final FaweLocation loc = fp.getLocation();
final int cx = loc.x >> 4;
@@ -231,7 +231,7 @@ public class RegionCommands extends MethodCommands {
@Command(
aliases = {"/line"},
- usage = " [thickness]",
+ usage = " [thickness]",
desc = "Draws a line segment between cuboid selection corners",
help =
"Draws a line segment between cuboid selection corners.\n" +
@@ -265,7 +265,7 @@ public class RegionCommands extends MethodCommands {
@Command(
aliases = {"/curve", "/spline"},
- usage = " [thickness]",
+ usage = " [thickness]",
desc = "Draws a spline through selected points",
help =
"Draws a spline through selected points.\n" +
@@ -344,7 +344,7 @@ public class RegionCommands extends MethodCommands {
@Command(
aliases = {"/overlay"},
- usage = "",
+ usage = "",
desc = "Set a block on top of blocks in the region",
min = 1,
max = 1
@@ -359,7 +359,7 @@ public class RegionCommands extends MethodCommands {
@Command(
aliases = {"/lay"},
- usage = "",
+ usage = "",
desc = "Set the top block in the region",
min = 1,
max = 1
@@ -393,7 +393,7 @@ public class RegionCommands extends MethodCommands {
@Command(
aliases = {"/center", "/middle"},
- usage = "",
+ usage = "",
desc = "Set the center block(s)",
min = 1,
max = 1
@@ -422,7 +422,7 @@ public class RegionCommands extends MethodCommands {
@Command(
aliases = {"/walls"},
- usage = "",
+ usage = "",
desc = "Build the four sides of the selection",
min = 1,
max = 1
@@ -437,7 +437,7 @@ public class RegionCommands extends MethodCommands {
@Command(
aliases = {"/faces", "/outline"},
- usage = "",
+ usage = "",
desc = "Build the walls, ceiling, and floor of a selection",
min = 1,
max = 1
@@ -727,7 +727,7 @@ public class RegionCommands extends MethodCommands {
@Command(
aliases = {"/hollow"},
- usage = "[[ ]]",
+ usage = "[[ ]]",
desc = "Hollows out the object contained in this selection",
help =
"Hollows out the object contained in this selection.\n" +
diff --git a/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java
index b00ad7d7..81d66734 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java
@@ -136,7 +136,7 @@ public class SchematicCommands {
@Command(aliases = {"load"}, usage = "[] ", desc = "Load a schematic into your clipboard")
@Deprecated
- @CommandPermissions({"worldedit.clipboard.load", "worldedit.schematic.load", "worldedit.schematic.upload"})
+ @CommandPermissions({"worldedit.clipboard.load", "worldedit.schematic.load", "worldedit.schematic.upload", "worldedit.schematic.load.other"})
public void load(final Player player, final LocalSession session, @Optional("schematic") final String formatName, final String filename) throws FilenameException {
final LocalConfiguration config = this.worldEdit.getConfiguration();
final ClipboardFormat format = ClipboardFormat.findByAlias(formatName);
@@ -224,7 +224,7 @@ public class SchematicCommands {
@Command(aliases = {"save"}, usage = "[] ", desc = "Save a schematic into your clipboard")
@Deprecated
- @CommandPermissions({"worldedit.clipboard.save", "worldedit.schematic.save"})
+ @CommandPermissions({"worldedit.clipboard.save", "worldedit.schematic.save", "worldedit.schematic.save.other"})
public void save(final Player player, final LocalSession session, @Optional("schematic") final String formatName, String filename) throws CommandException, WorldEditException {
final LocalConfiguration config = this.worldEdit.getConfiguration();
final ClipboardFormat format = ClipboardFormat.findByAlias(formatName);
diff --git a/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java
index c28e3ef1..a5edb7d7 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java
@@ -19,6 +19,8 @@
package com.sk89q.worldedit.command;
+import com.boydti.fawe.Fawe;
+import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Commands;
import com.boydti.fawe.object.FaweLimit;
@@ -26,6 +28,7 @@ import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.StringMan;
import com.boydti.fawe.util.chat.Message;
+import com.boydti.fawe.util.chat.UsageMessage;
import com.google.common.base.Joiner;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
@@ -44,6 +47,9 @@ import com.sk89q.worldedit.command.util.CreatureButcher;
import com.sk89q.worldedit.command.util.EntityRemover;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.Player;
+import com.sk89q.worldedit.extension.factory.DefaultMaskParser;
+import com.sk89q.worldedit.extension.factory.DefaultTransformParser;
+import com.sk89q.worldedit.extension.factory.HashTagPatternParser;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.CommandManager;
@@ -65,11 +71,10 @@ import com.sk89q.worldedit.util.command.CommandMapping;
import com.sk89q.worldedit.util.command.DelegateCallable;
import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.util.command.PrimaryAliasComparator;
+import com.sk89q.worldedit.util.command.binding.Range;
import com.sk89q.worldedit.util.command.binding.Text;
import com.sk89q.worldedit.util.command.parametric.Optional;
import com.sk89q.worldedit.util.command.parametric.ParametricCallable;
-import com.sk89q.worldedit.util.formatting.ColorCodeBuilder;
-import com.sk89q.worldedit.util.formatting.component.CommandUsageBox;
import com.sk89q.worldedit.world.World;
import java.io.File;
import java.net.URI;
@@ -102,10 +107,79 @@ public class UtilityCommands extends MethodCommands {
super(we);
}
+ @Command(
+ aliases = {"patterns"},
+ usage = "[page=1|search|pattern]",
+ desc = "View help about patterns",
+ help = "Patterns determine what blocks are placed\n" +
+ " - Use [brackets] for arguments\n" +
+ " - Use , to OR multiple\n" +
+ "e.g. #surfacespread[10][#existing],andesite\n" +
+ "More Info: https://git.io/vSPmA"
+ )
+ public void patterns(Player player, LocalSession session, CommandContext args) throws WorldEditException {
+ if (args.argsLength() == 0) {
+ String base = getCommand().aliases()[0];
+ UsageMessage msg = new UsageMessage(getCallable(), base, args.getLocals());
+ msg.newline().paginate(base, 0, 1).send(player);
+ return;
+ }
+ HashTagPatternParser parser = FaweAPI.getParser(HashTagPatternParser.class);
+ if (parser != null) {
+ UtilityCommands.help(args, worldEdit, player, getCommand().aliases()[0] + " ", parser.getDispatcher());
+ }
+ }
+
+ @Command(
+ aliases = {"masks"},
+ usage = "[page=1|search|mask]",
+ desc = "View help about masks",
+ help = "Masks determine if a block can be placed\n" +
+ " - Use [brackets] for arguments\n" +
+ " - Use , to OR multiple\n" +
+ " - Use & to AND multiple\n" +
+ "e.g. >[stone,dirt],#light[0][5],$jungle\n" +
+ "More Info: https://git.io/v9r4K"
+ )
+ public void masks(Player player, LocalSession session, CommandContext args) throws WorldEditException {
+ if (args.argsLength() == 0) {
+ String base = getCommand().aliases()[0];
+ UsageMessage msg = new UsageMessage(getCallable(), base, args.getLocals());
+ msg.newline().paginate(base, 0, 1).send(player);
+ return;
+ }
+ DefaultMaskParser parser = FaweAPI.getParser(DefaultMaskParser.class);
+ if (parser != null) {
+ UtilityCommands.help(args, worldEdit, player, getCommand().aliases()[0] + " ", parser.getDispatcher());
+ }
+ }
+
+ @Command(
+ aliases = {"transforms"},
+ usage = "[page=1|search|transform]",
+ desc = "View help about transforms",
+ help = "Transforms modify how a block is placed\n" +
+ " - Use [brackets] for arguments\n" +
+ " - Use , to OR multiple\n" +
+ " - Use & to AND multiple\n" +
+ "More Info: https://git.io/v9KHO"
+ )
+ public void transforms(Player player, LocalSession session, CommandContext args) throws WorldEditException {
+ if (args.argsLength() == 0) {
+ String base = getCommand().aliases()[0];
+ UsageMessage msg = new UsageMessage(getCallable(), base, args.getLocals());
+ msg.newline().paginate(base, 0, 1).send(player);
+ return;
+ }
+ DefaultTransformParser parser = Fawe.get().getTransformParser();
+ if (parser != null) {
+ UtilityCommands.help(args, worldEdit, player, getCommand().aliases()[0] + " ", parser.getDispatcher());
+ }
+ }
@Command(
aliases = {"/fill"},
- usage = " [depth]",
+ usage = " [depth]",
desc = "Fill a hole",
min = 2,
max = 3
@@ -126,7 +200,7 @@ public class UtilityCommands extends MethodCommands {
@Command(
aliases = {"/fillr"},
- usage = " [depth]",
+ usage = " [depth]",
desc = "Fill a hole recursively",
min = 2,
max = 3
@@ -565,7 +639,7 @@ public class UtilityCommands extends MethodCommands {
return null;
}
- public static void list(File dir, Actor actor, CommandContext args, int page, String formatName, boolean playerFolder) {
+ public static void list(File dir, Actor actor, CommandContext args, @Range(min = 0) int page, String formatName, boolean playerFolder) {
List fileList = new ArrayList<>();
int len = args.argsLength();
List filters = new ArrayList<>();
@@ -861,7 +935,7 @@ public class UtilityCommands extends MethodCommands {
}
if (!(callable instanceof Dispatcher)) {
// TODO interactive box
- actor.printRaw(BBC.getPrefix() + ColorCodeBuilder.asColorCodes(new CommandUsageBox(callable, Joiner.on(" ").join(visited))));
+ new UsageMessage(callable, Joiner.on(" ").join(visited)).send(actor);
return;
}
dispatcher = (Dispatcher) callable;
@@ -928,10 +1002,9 @@ public class UtilityCommands extends MethodCommands {
s1.append(mapping.getPrimaryAlias());
String s2 = mapping.getDescription().getDescription();
if (c.testPermission(locals)) {
- // TODO interactive
- // Hover -> command help
- // Click -> Suggest command
msg.text(BBC.HELP_ITEM_ALLOWED, s1, s2);
+ String helpCmd = baseCommand + " " + mapping.getPrimaryAlias();
+ msg.cmdTip(helpCmd);
msg.newline();
} else {
msg.text(BBC.HELP_ITEM_DENIED, s1, s2).newline();
@@ -945,7 +1018,7 @@ public class UtilityCommands extends MethodCommands {
msg.send(actor);
}
} else {
- actor.printRaw(BBC.getPrefix() + ColorCodeBuilder.asColorCodes(new CommandUsageBox(callable, Joiner.on(" ").join(visited))));
+ new UsageMessage(callable, Joiner.on(" ").join(visited)).send(actor);
}
} catch (Throwable e) {
e.printStackTrace();
diff --git a/core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java b/core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java
index 70bee291..c02a8576 100644
--- a/core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java
+++ b/core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java
@@ -28,6 +28,7 @@ import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.util.StringMan;
import com.boydti.fawe.util.TaskManager;
+import com.boydti.fawe.util.chat.UsageMessage;
import com.boydti.fawe.wrappers.FakePlayer;
import com.boydti.fawe.wrappers.LocationMaskedPlayerWrapper;
import com.google.common.base.Joiner;
@@ -85,8 +86,6 @@ import com.sk89q.worldedit.util.command.parametric.ExceptionConverter;
import com.sk89q.worldedit.util.command.parametric.LegacyCommandsHandler;
import com.sk89q.worldedit.util.command.parametric.ParametricBuilder;
import com.sk89q.worldedit.util.eventbus.Subscribe;
-import com.sk89q.worldedit.util.formatting.ColorCodeBuilder;
-import com.sk89q.worldedit.util.formatting.component.CommandUsageBox;
import com.sk89q.worldedit.util.logging.DynamicStreamHandler;
import com.sk89q.worldedit.util.logging.LogFormat;
import java.io.File;
@@ -394,7 +393,8 @@ public final class CommandManager {
BBC.NO_PERM.send(finalActor, StringMan.join(failedPermissions, " "));
} catch (InvalidUsageException e) {
if (e.isFullHelpSuggested()) {
- finalActor.printRaw(BBC.getPrefix() + ColorCodeBuilder.asColorCodes(new CommandUsageBox(e.getCommand(), e.getCommandUsed("", ""), locals)));
+ UsageMessage usage = new UsageMessage(e.getCommand(), e.getCommandUsed("", ""), locals);
+ usage.send(fp);
String message = e.getMessage();
if (message != null) {
finalActor.printError(message);
diff --git a/core/src/main/java/com/sk89q/worldedit/extent/Extent.java b/core/src/main/java/com/sk89q/worldedit/extent/Extent.java
index 71e85689..e9329a2a 100644
--- a/core/src/main/java/com/sk89q/worldedit/extent/Extent.java
+++ b/core/src/main/java/com/sk89q/worldedit/extent/Extent.java
@@ -160,7 +160,7 @@ public interface Extent extends InputExtent, OutputExtent {
PseudoRandom random = new PseudoRandom();
for (Vector2D chunkPos : region.getChunks()) {
for (int i = 0; i < frequency; i++) {
- if (random.nextInt(101) > rarity) {
+ if (random.nextInt(100) > rarity) {
continue;
}
int x = (chunkPos.getBlockX() << 4) + PseudoRandom.random.nextInt(16);
diff --git a/core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java b/core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java
index f3be8007..ac5cfdc7 100644
--- a/core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java
+++ b/core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java
@@ -19,16 +19,19 @@
package com.sk89q.worldedit.function.mask;
+import com.sk89q.minecraft.util.commands.Link;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
+import com.sk89q.worldedit.command.UtilityCommands;
import java.io.Serializable;
import javax.annotation.Nullable;
/**
* Tests whether a given vector meets a criteria.
*/
+@Link(clazz = UtilityCommands.class, value = "masks")
public interface Mask extends com.sk89q.worldedit.masks.Mask, Serializable {
/**
diff --git a/core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java b/core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java
index 79bc6023..2d1c5817 100644
--- a/core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java
+++ b/core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java
@@ -19,13 +19,16 @@
package com.sk89q.worldedit.function.pattern;
+import com.sk89q.minecraft.util.commands.Link;
import com.sk89q.worldedit.MutableBlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
+import com.sk89q.worldedit.command.UtilityCommands;
/**
* Returns a {@link BaseBlock} for a given position.
*/
+@Link(clazz = UtilityCommands.class, value = "patterns")
public interface Pattern extends com.sk89q.worldedit.patterns.Pattern {
/**
diff --git a/core/src/main/java/com/sk89q/worldedit/patterns/Pattern.java b/core/src/main/java/com/sk89q/worldedit/patterns/Pattern.java
index 4f76e9b2..97c727d6 100644
--- a/core/src/main/java/com/sk89q/worldedit/patterns/Pattern.java
+++ b/core/src/main/java/com/sk89q/worldedit/patterns/Pattern.java
@@ -19,9 +19,11 @@
package com.sk89q.worldedit.patterns;
+import com.sk89q.minecraft.util.commands.Link;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
+import com.sk89q.worldedit.command.UtilityCommands;
import com.sk89q.worldedit.extent.Extent;
import java.io.Serializable;
@@ -29,6 +31,7 @@ import java.io.Serializable;
* @deprecated See {@link com.sk89q.worldedit.function.pattern.Pattern}
*/
@Deprecated
+@Link(clazz = UtilityCommands.class, value = "patterns")
public interface Pattern extends Serializable {
/**
diff --git a/core/src/main/java/com/sk89q/worldedit/util/command/parametric/FaweParanamer.java b/core/src/main/java/com/sk89q/worldedit/util/command/parametric/FaweParanamer.java
new file mode 100644
index 00000000..8e2c0fbf
--- /dev/null
+++ b/core/src/main/java/com/sk89q/worldedit/util/command/parametric/FaweParanamer.java
@@ -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;
+ }
+}
diff --git a/core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java b/core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java
index 9447c78d..79035358 100644
--- a/core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java
+++ b/core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java
@@ -38,7 +38,7 @@ 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;
@@ -60,7 +60,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class ParametricBuilder {
private final Map bindings = new HashMap();
- private final Paranamer paranamer = new CachingParanamer();
+ private final Paranamer paranamer = new FaweParanamer();
private final List invokeListeners = new ArrayList();
private final List exceptionConverters = new ArrayList();
private Authorizer authorizer = new NullAuthorizer();
diff --git a/core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java b/core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java
index 35b06167..b6eda09f 100644
--- a/core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java
+++ b/core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java
@@ -78,6 +78,7 @@ public class ParametricCallable implements CommandCallable {
Annotation[][] annotations = method.getParameterAnnotations();
String[] names = builder.getParanamer().lookupParameterNames(method, false);
Type[] types = method.getGenericParameterTypes();
+
parameters = new ParameterData[types.length];
List userParameters = new ArrayList();
diff --git a/core/src/main/java/com/sk89q/worldedit/world/biome/BaseBiome.java b/core/src/main/java/com/sk89q/worldedit/world/biome/BaseBiome.java
new file mode 100644
index 00000000..72d39c71
--- /dev/null
+++ b/core/src/main/java/com/sk89q/worldedit/world/biome/BaseBiome.java
@@ -0,0 +1,92 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.world.biome;
+
+import com.sk89q.minecraft.util.commands.Link;
+import com.sk89q.worldedit.command.BiomeCommands;
+
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Basic storage object to represent a given biome.
+ */
+@Link(clazz = BiomeCommands.class, value = "biomelist")
+public class BaseBiome {
+
+ private int id;
+
+ /**
+ * Create a new biome with the given biome ID.
+ *
+ * @param id the biome ID
+ */
+ public BaseBiome(int id) {
+ this.id = id;
+ }
+
+ /**
+ * Create a clone of the given biome.
+ *
+ * @param biome the biome to clone
+ */
+ public BaseBiome(BaseBiome biome) {
+ checkNotNull(biome);
+ this.id = biome.getId();
+ }
+
+ /**
+ * Get the biome ID.
+ *
+ * @return the biome ID
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Set the biome id.
+ *
+ * @param id the biome ID
+ */
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ BaseBiome baseBiome = (BaseBiome) o;
+
+ return id == baseBiome.id;
+ }
+
+ @Override
+ public int hashCode() {
+ return id;
+ }
+
+
+ public static Class> inject() {
+ return BaseBiome.class;
+ }
+}