All commands translatable + Start on inspect brush

+ Disable AWE if present as otherwise both don't load
This commit is contained in:
Jesse Boyd 2016-08-03 19:23:31 +10:00
parent 1ca5798e9d
commit e5ebccd053
12 changed files with 488 additions and 4 deletions

View File

@ -1,10 +1,53 @@
package com.boydti.fawe.bukkit; package com.boydti.fawe.bukkit;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.FaweQueue;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
public abstract class ABukkitMain extends JavaPlugin { public abstract class ABukkitMain extends JavaPlugin {
static {
{ // Disable AWE as otherwise both fail to load
PluginManager manager = Bukkit.getPluginManager();
try {
Field pluginsField = manager.getClass().getDeclaredField("plugins");
Field lookupNamesField = manager.getClass().getDeclaredField("lookupNames");
pluginsField.setAccessible(true);
lookupNamesField.setAccessible(true);
List<Plugin> plugins = (List<Plugin>) pluginsField.get(manager);
Map<String, Plugin> lookupNames = (Map<String, Plugin>) lookupNamesField.get(manager);
pluginsField.set(manager, new ArrayList<Plugin>(plugins) {
@Override
public boolean add(Plugin plugin) {
if (!plugin.getName().startsWith("AsyncWorldEdit")) {
return super.add(plugin);
} else {
Fawe.debug("[FAWE] Disabling `" + plugin.getName() + "` as it is incompatible");
}
return false;
}
});
lookupNamesField.set(manager, new ConcurrentHashMap<String, Plugin>(lookupNames) {
@Override
public Plugin put(String key, Plugin plugin) {
if (!plugin.getName().startsWith("AsyncWorldEdit")) {
return super.put(key, plugin);
}
return null;
}
});
} catch (Throwable ignore) {}
}
}
@Override @Override
public void onEnable() { public void onEnable() {
FaweBukkit imp = new FaweBukkit(this); FaweBukkit imp = new FaweBukkit(this);

View File

@ -3,7 +3,7 @@ main: com.boydti.fawe.bukkit.v1_10.BukkitMain_110
version: ${version} version: ${version}
description: Fast Async WorldEdit plugin description: Fast Async WorldEdit plugin
authors: [Empire92] authors: [Empire92]
loadbefore: [WorldEdit,AsyncWorldEdit] loadbefore: [WorldEdit,AsyncWorldEdit,AsyncWorldEditInjector]
load: STARTUP load: STARTUP
database: false database: false
#softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones] #softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones]

View File

@ -3,7 +3,7 @@ main: com.boydti.fawe.bukkit.v1_7.BukkitMain_17
version: ${version} version: ${version}
description: Fast Async WorldEdit plugin description: Fast Async WorldEdit plugin
authors: [Empire92] authors: [Empire92]
loadbefore: [WorldEdit,AsyncWorldEdit] loadbefore: [WorldEdit,AsyncWorldEdit,AsyncWorldEditInjector]
load: STARTUP load: STARTUP
database: false database: false
#softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones] #softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones]

View File

@ -3,7 +3,7 @@ main: com.boydti.fawe.bukkit.v1_8.BukkitMain_18
version: ${version} version: ${version}
description: Fast Async WorldEdit plugin description: Fast Async WorldEdit plugin
authors: [Empire92] authors: [Empire92]
loadbefore: [WorldEdit,AsyncWorldEdit] loadbefore: [WorldEdit,AsyncWorldEdit,AsyncWorldEditInjector]
load: STARTUP load: STARTUP
database: false database: false
#softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones] #softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones]

View File

@ -3,7 +3,7 @@ main: com.boydti.fawe.bukkit.v1_9.BukkitMain_19
version: ${version} version: ${version}
description: Fast Async WorldEdit plugin description: Fast Async WorldEdit plugin
authors: [Empire92] authors: [Empire92]
loadbefore: [WorldEdit,AsyncWorldEdit] loadbefore: [WorldEdit,AsyncWorldEdit,AsyncWorldEditInjector]
load: STARTUP load: STARTUP
database: false database: false
#softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones] #softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones]

View File

@ -7,6 +7,7 @@ import com.boydti.fawe.command.Stream;
import com.boydti.fawe.command.Wea; import com.boydti.fawe.command.Wea;
import com.boydti.fawe.command.WorldEditRegion; import com.boydti.fawe.command.WorldEditRegion;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Commands;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.regions.general.plot.PlotSquaredFeature; import com.boydti.fawe.regions.general.plot.PlotSquaredFeature;
@ -55,6 +56,7 @@ import com.sk89q.worldedit.history.change.EntityCreate;
import com.sk89q.worldedit.history.change.EntityRemove; import com.sk89q.worldedit.history.change.EntityRemove;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import com.sk89q.worldedit.util.command.parametric.ParametricBuilder;
import com.sk89q.worldedit.world.registry.BundledBlockData; import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -240,6 +242,8 @@ public class Fawe {
Settings.save(file); Settings.save(file);
// Setting up message.yml // Setting up message.yml
BBC.load(new File(this.IMP.getDirectory(), "message.yml")); BBC.load(new File(this.IMP.getDirectory(), "message.yml"));
// Setting up commands.yml
Commands.load(new File(this.IMP.getDirectory(), "commands.yml"));
// Block rotation // Block rotation
try { try {
BundledBlockData.getInstance().loadFromResource(); BundledBlockData.getInstance().loadFromResource();
@ -280,6 +284,7 @@ public class Fawe {
RegionCommands.inject(); // Translations RegionCommands.inject(); // Translations
HistoryCommands.inject(); // Translations HistoryCommands.inject(); // Translations
NavigationCommands.inject(); // Translations + thru fix NavigationCommands.inject(); // Translations + thru fix
ParametricBuilder.inject(); // Translations
// Schematic // Schematic
SchematicReader.inject(); SchematicReader.inject();
SchematicWriter.inject(); SchematicWriter.inject();

View File

@ -90,6 +90,7 @@ public enum BBC {
BRUSH_HEIGHT_INVALID("Invalid height map file (%s0)", "WorldEdit.Brush"), BRUSH_HEIGHT_INVALID("Invalid height map file (%s0)", "WorldEdit.Brush"),
BRUSH_SMOOTH("Smooth brush equipped (%s0 x %s1 using %s2).", "WorldEdit.Brush"), BRUSH_SMOOTH("Smooth brush equipped (%s0 x %s1 using %s2).", "WorldEdit.Brush"),
BRUSH_SPHERE("Sphere brush shape equipped (%s0).", "WorldEdit.Brush"), BRUSH_SPHERE("Sphere brush shape equipped (%s0).", "WorldEdit.Brush"),
BRUSH_INSPECT("Inspect brush shape equipped (%s0).", "WorldEdit.Brush"),
SCHEMATIC_DELETE("%s0 has been deleted.", "Worldedit.Schematic"), SCHEMATIC_DELETE("%s0 has been deleted.", "Worldedit.Schematic"),
SCHEMATIC_FORMAT("Available clipboard formats (Name: Lookup names)", "Worldedit.Schematic"), SCHEMATIC_FORMAT("Available clipboard formats (Name: Lookup names)", "Worldedit.Schematic"),

View File

@ -0,0 +1,116 @@
package com.boydti.fawe.config;
import com.boydti.fawe.configuration.ConfigurationSection;
import com.boydti.fawe.configuration.file.YamlConfiguration;
import com.sk89q.minecraft.util.commands.Command;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class Commands {
private static YamlConfiguration cmdConfig;
private static File cmdFile;
public static void load(File file) {
cmdFile = file;
try {
if (!file.exists()) {
file.getParentFile().mkdirs();
file.createNewFile();
}
cmdConfig = YamlConfiguration.loadConfiguration(file);
} catch (IOException e) {
e.printStackTrace();
}
}
public static Command translate(final Command command) {
if (cmdConfig == null) {
return command;
}
String id = command.aliases()[0];
ConfigurationSection commands = cmdConfig.getConfigurationSection(id);
boolean set = false;
if (commands == null) {
set = (commands = cmdConfig.createSection(id)) != null;
}
HashMap<String, Object> options = new HashMap<>();
options.put("aliases", new ArrayList<String>(Arrays.asList(command.aliases())));
options.put("usage", command.usage());
options.put("desc", command.desc());
options.put("help", command.help());
for (Map.Entry<String, Object> entry : options.entrySet()) {
String key = entry.getKey();
if (!commands.contains(key)) {
commands.set(key, entry.getValue());
set = true;
}
}
if (set) {
try {
cmdConfig.save(cmdFile);
} catch (IOException e) {
e.printStackTrace();
}
}
final String[] aliases = commands.getStringList("aliases").toArray(new String[0]);
final String usage = commands.getString("usage");
final String desc = commands.getString("desc");
final String help = commands.getString("help");
return new Command() {
@Override
public Class<? extends Annotation> annotationType() {
return command.annotationType();
}
@Override
public String[] aliases() {
return aliases;
}
@Override
public String usage() {
return usage;
}
@Override
public String desc() {
return desc;
}
@Override
public int min() {
return command.min();
}
@Override
public int max() {
return command.max();
}
@Override
public String flags() {
return command.flags();
}
@Override
public String help() {
return help;
}
@Override
public boolean anyFlags() {
return command.anyFlags();
}
};
}
}

View File

@ -0,0 +1,24 @@
package com.boydti.fawe.object.brush;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.function.pattern.Pattern;
public class InspectBrush implements Brush {
private final Player player;
private final int radius;
public InspectBrush(Player player, double radius) {
this.player = player;
this.radius = (int) radius;
}
@Override
public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
// TODO
}
}

View File

@ -8,6 +8,7 @@ import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.biome.BaseBiome;
import java.io.File; import java.io.File;
import java.util.Collection;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ConcurrentLinkedDeque;
@ -123,6 +124,11 @@ public class DelegateFaweQueue extends FaweQueue {
return parent.getFaweChunk(x, z); return parent.getFaweChunk(x, z);
} }
@Override
public Collection<FaweChunk> getFaweChunks() {
return parent.getFaweChunks();
}
@Override @Override
public void setChunk(FaweChunk<?> chunk) { public void setChunk(FaweChunk<?> chunk) {
parent.setChunk(chunk); parent.setChunk(chunk);

View File

@ -27,6 +27,7 @@ import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.brush.CommandBrush; import com.boydti.fawe.object.brush.CommandBrush;
import com.boydti.fawe.object.brush.CopyBrush; import com.boydti.fawe.object.brush.CopyBrush;
import com.boydti.fawe.object.brush.HeightBrush; import com.boydti.fawe.object.brush.HeightBrush;
import com.boydti.fawe.object.brush.InspectBrush;
import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandPermissions;
@ -79,6 +80,24 @@ public class BrushCommands {
this.worldEdit = worldEdit; this.worldEdit = worldEdit;
} }
@Command(
aliases = { "inspect", "i" },
usage = "<radius>",
desc = "Inspect edits within a radius",
help =
"Chooses the inspect brush",
min = 0,
max = 1
)
@CommandPermissions("worldedit.brush.inspect")
public void inspectBrush(Player player, LocalSession session, EditSession editSession, @Optional("1") double radius) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setSize(radius);
tool.setBrush(new InspectBrush(player, radius), "worldedit.brush.inspect");
BBC.BRUSH_INSPECT.send(player, radius);
}
@Command( @Command(
aliases = { "sphere", "s" }, aliases = { "sphere", "s" },
usage = "<pattern> [radius]", usage = "<pattern> [radius]",

View File

@ -0,0 +1,270 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
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.util.auth.Authorizer;
import com.sk89q.worldedit.util.auth.NullAuthorizer;
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.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.Paranamer;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
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<Type, Binding>();
private final Paranamer paranamer = new CachingParanamer();
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
* {@link StandardBindings} and default bindings.</p>
*/
public ParametricBuilder() {
addBinding(new PrimitiveBindings());
addBinding(new StandardBindings());
}
/**
* Add a binding for a given type or classifier (annotation).
*
* <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
* {@link Method#invoke(Object, Object...)}.</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
* example, even if there is a binding that handles {@link String} parameters,
* a special {@code @MyArg} annotation can be assigned to a {@link String}
* 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
*/
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>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 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 com.sk89q.worldedit.util.command.parametric.InvokeHandler#postInvoke(Object, Method, com.sk89q.worldedit.util.command.parametric.ParameterData[], Object[], CommandContext)}.</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 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 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>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 com.sk89q.worldedit.util.command.parametric.ParametricException thrown if the commands cannot be registered
*/
public void registerMethodsAsCommands(Dispatcher dispatcher, Object object) throws ParametricException {
for (Method method : object.getClass().getDeclaredMethods()) {
Command definition = method.getAnnotation(Command.class);
if (definition != null) {
CommandCallable callable = build(object, method, definition);
dispatcher.registerCommand(callable, definition.aliases());
}
}
}
/**
* Build a {@link CommandCallable} for the given method.
*
* @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)
throws ParametricException {
try {
Class<?> clazz = Class.forName("com.sk89q.worldedit.util.command.parametric.ParametricCallable");
Constructor<?> constructor = clazz.getDeclaredConstructors()[0];
constructor.setAccessible(true);
return (CommandCallable) constructor.newInstance(this, object, method, Commands.translate(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
*/
public Paranamer getParanamer() {
return paranamer;
}
/**
* Get the map of bindings.
*
* @return the map of bindings
*/
public Map<Type, Binding> getBindings() {
return bindings;
}
/**
* Get a list of invocation listeners.
*
* @return a list of invocation listeners
*/
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.
*
* @return the authorizer
*/
public Authorizer getAuthorizer() {
return authorizer;
}
/**
* Set the authorizer.
*
* @param authorizer the authorizer
*/
public void setAuthorizer(Authorizer authorizer) {
checkNotNull(authorizer);
this.authorizer = authorizer;
}
/**
* Get the default command suggestions provider that will be used if
* no suggestions are available.
*
* @return the default command completer
*/
public CommandCompleter getDefaultCompleter() {
return defaultCompleter;
}
/**
* Set the default command suggestions provider that will be used if
* no suggestions are available.
*
* @param defaultCompleter the default command completer
*/
public void setDefaultCompleter(CommandCompleter defaultCompleter) {
checkNotNull(defaultCompleter);
this.defaultCompleter = defaultCompleter;
}
public static Class<?> inject() {
return ParametricBuilder.class;
}
}