diff --git a/build.gradle b/build.gradle index aa32d780a..853a547fe 100644 --- a/build.gradle +++ b/build.gradle @@ -8,6 +8,8 @@ buildscript { configurations.all { resolutionStrategy { + force 'com.google.guava:guava:21.0' + force 'org.ow2.asm:asm:6.0_BETA' force 'commons-io:commons-io:2.4' } } diff --git a/splash.txt b/splash.txt index c63b561f2..6513022a7 100644 --- a/splash.txt +++ b/splash.txt @@ -7,7 +7,7 @@ | | / _____ \ \ /\ / | |____ |__| /__/ \__\ \__/ \__/ |_______| -======= By Empire92 and WorldEdit team ======= +======== Authors https://git.io/fjIDU ======== If you encounter trouble: - Run `build` in a separate Gradle run diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/v1_13_1/Spigot_v1_13_R2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/v1_13_1/Spigot_v1_13_R2.java index a31b89f06..4cdc7a264 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/v1_13_1/Spigot_v1_13_R2.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/v1_13_1/Spigot_v1_13_R2.java @@ -50,20 +50,21 @@ import org.bukkit.craftbukkit.v1_13_R2.block.data.CraftBlockData; import org.bukkit.craftbukkit.v1_13_R2.entity.CraftEntity; import org.bukkit.entity.Player; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.annotation.Nullable; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; import java.util.logging.Level; -import java.util.logging.Logger; import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkNotNull; public final class Spigot_v1_13_R2 extends CachedBukkitAdapter implements BukkitImplAdapter{ - private final Logger logger = Logger.getLogger(getClass().getCanonicalName()); + private final Logger logger = LoggerFactory.getLogger(getClass()); private final Field nbtListTagListField; private final Method nbtCreateTagMethod; @@ -337,7 +338,7 @@ public final class Spigot_v1_13_R2 extends CachedBukkitAdapter implements Bukkit return Collections.emptyMap(); } if (block == null) { - logger.warning("Failed to find properties for " + blockType.getId()); + logger.warn("Failed to find properties for " + blockType.getId()); return Collections.emptyMap(); } Map> properties = Maps.newLinkedHashMap(); @@ -403,7 +404,7 @@ public final class Spigot_v1_13_R2 extends CachedBukkitAdapter implements Bukkit try { return toNativeList((NBTTagList) foreign); } catch (Throwable e) { - logger.log(Level.WARNING, "Failed to convert NBTTagList", e); + logger.warn("Failed to convert NBTTagList", e); return new ListTag(ByteTag.class, new ArrayList()); } } else if (foreign instanceof NBTTagLong) { diff --git a/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/CommandRegistration.java b/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/CommandRegistration.java index 0e47b5f9a..e7df6832c 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/CommandRegistration.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/CommandRegistration.java @@ -35,11 +35,7 @@ import java.util.Set; public class CommandRegistration { static { - try { - Bukkit.getServer().getHelpMap().registerHelpTopicFactory(DynamicPluginCommand.class, new DynamicPluginCommandHelpTopic.Factory()); - } catch (Throwable e) { - e.printStackTrace(); - } + Bukkit.getServer().getHelpMap().registerHelpTopicFactory(DynamicPluginCommand.class, new DynamicPluginCommandHelpTopic.Factory()); } protected final Plugin plugin; diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockRegistry.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockRegistry.java index 0264ba49e..fcf2fd25d 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockRegistry.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockRegistry.java @@ -54,18 +54,18 @@ public class BukkitBlockRegistry extends BundledBlockRegistry { BlockMaterial result = adapter.getMaterial(blockType); if (result != null) return result; } - Material type = BukkitAdapter.adapt(blockType); - if (type == null) { + Material mat = BukkitAdapter.adapt(blockType); + if (mat == null) { if (blockType == BlockTypes.__RESERVED__) return new PassthroughBlockMaterial(super.getMaterial(BlockTypes.AIR)); return new PassthroughBlockMaterial(null); } if (materialMap == null) { materialMap = new BukkitBlockMaterial[Material.values().length]; } - BukkitBlockMaterial result = materialMap[type.ordinal()]; + BukkitBlockMaterial result = materialMap[mat.ordinal()]; if (result == null) { - result = new BukkitBlockMaterial(BukkitBlockRegistry.super.getMaterial(blockType), type); - materialMap[type.ordinal()] = result; + result = new BukkitBlockMaterial(BukkitBlockRegistry.super.getMaterial(blockType), mat); + materialMap[mat.ordinal()] = result; } return result; } @@ -84,9 +84,8 @@ public class BukkitBlockRegistry extends BundledBlockRegistry { @Nullable @Override public Map> getProperties(BlockType blockType) { - BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); - if (adapter != null) { - return adapter.getProperties(blockType); + if (WorldEditPlugin.getInstance().getBukkitImplAdapter() != null) { + return WorldEditPlugin.getInstance().getBukkitImplAdapter().getProperties(blockType); } return super.getProperties(blockType); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java index 94b616f7b..22e424821 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java @@ -294,7 +294,7 @@ public class BukkitPlayer extends AbstractPlayerActor { } @Override - public > void sendFakeBlock(BlockVector3 pos, B block) { + public void sendFakeBlock(BlockVector3 pos, BlockStateHolder block) { Location loc = new Location(player.getWorld(), pos.getX(), pos.getY(), pos.getZ()); if (block == null) { player.sendBlockChange(loc, player.getWorld().getBlockAt(loc).getBlockData()); diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java index bf460997e..2d312c19f 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java @@ -149,7 +149,7 @@ public class BukkitServerInterface implements MultiUserPlatform { @Override public String getPlatformName() { - return "bukkit"; + return "Bukkit"; } @Override diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java index e2b5335fd..e8dc2ecef 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java @@ -33,31 +33,35 @@ import com.sk89q.worldedit.bukkit.adapter.AdapterLoadException; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplLoader; import com.sk89q.worldedit.event.platform.CommandEvent; +import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.event.platform.PlatformReadyEvent; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Capability; -import com.sk89q.worldedit.extension.platform.NoCapablePlatformException; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extent.inventory.BlockBag; +import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.block.BlockCategory; +import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.FuzzyBlockState; import com.sk89q.worldedit.world.entity.EntityType; import com.sk89q.worldedit.world.item.ItemCategory; import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.registry.LegacyMapper; +import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.Tag; import org.bukkit.block.Biome; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; import org.bukkit.entity.Player; -import org.bukkit.plugin.*; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPluginLoader; import org.slf4j.Logger; @@ -84,8 +88,7 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Plugin for Bukkit. */ -public class WorldEditPlugin extends JavaPlugin //implements TabCompleter -{ +public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter private static final Logger log = LoggerFactory.getLogger(WorldEditPlugin.class); public static final String CUI_PLUGIN_CHANNEL = "worldedit:cui"; @@ -300,7 +303,7 @@ public class WorldEditPlugin extends JavaPlugin //implements TabCompleter } } // { -// java.util.logging.Logger logger = getLogger(); +// Logger logger = getLogger(); // if (logger != null) { // try { // Field nameField = Logger.class.getDeclaredField("name"); @@ -324,7 +327,7 @@ public class WorldEditPlugin extends JavaPlugin //implements TabCompleter e.printStackTrace(); } } - log.info("Please restart the server if you have any plugins which depend on FAWE."); + getLogger().info("Please restart the server if you have any plugins which depend on FAWE."); } } @@ -332,7 +335,7 @@ public class WorldEditPlugin extends JavaPlugin //implements TabCompleter try { run.run(); } catch (Throwable e) { - log.error(message); + getLogger().severe(message); e.printStackTrace(); } } @@ -343,7 +346,7 @@ public class WorldEditPlugin extends JavaPlugin //implements TabCompleter config = new BukkitConfiguration(new YAMLProcessor(new File(getDataFolder(), "config-legacy.yml"), true), this); config.load(); } catch (Throwable e) { - log.error("Failed to load config.yml"); + getLogger().severe("Failed to load config.yml"); e.printStackTrace(); } // Create schematics folder @@ -359,8 +362,8 @@ public class WorldEditPlugin extends JavaPlugin //implements TabCompleter BukkitImplLoader adapterLoader = new BukkitImplLoader(); try { adapterLoader.addClass(Spigot_v1_13_R2.class); - } catch (Throwable ignore) { - ignore.printStackTrace(); + } catch (Throwable throwable) { + throwable.printStackTrace(); } try { @@ -378,18 +381,14 @@ public class WorldEditPlugin extends JavaPlugin //implements TabCompleter bukkitAdapter = adapterLoader.loadAdapter(); log.info("Using " + bukkitAdapter.getClass().getCanonicalName() + " as the Bukkit adapter"); } catch (AdapterLoadException e) { - try { - Platform platform = worldEdit.getPlatformManager().queryCapability(Capability.WORLD_EDITING); - if (platform instanceof BukkitServerInterface) { - log.warn(e.getMessage()); - return; - } else { - log.info("WorldEdit could not find a Bukkit adapter for this MC version, " + - "but it seems that you have another implementation of WorldEdit installed (" + platform.getPlatformName() + ") " + - "that handles the world editing."); - } - } catch (NoCapablePlatformException ignore) {} - log.info("WorldEdit could not find a Bukkit adapter for this MC version"); + Platform platform = worldEdit.getPlatformManager().queryCapability(Capability.WORLD_EDITING); + if (platform instanceof BukkitServerInterface) { + log.warn(e.getMessage()); + } else { + log.info("WorldEdit could not find a Bukkit adapter for this MC version, " + + "but it seems that you have another implementation of WorldEdit installed (" + platform.getPlatformName() + ") " + + "that handles the world editing."); + } } } diff --git a/worldedit-core/build.gradle b/worldedit-core/build.gradle index 6ac2c5455..eb0f957c3 100644 --- a/worldedit-core/build.gradle +++ b/worldedit-core/build.gradle @@ -1,89 +1,89 @@ -apply plugin: 'eclipse' -apply plugin: 'idea' -repositories { - maven {url "http://ci.athion.net/job/PlotSquared-Breaking/ws/mvn/"} -} -dependencies { - compile 'de.schlichtherle:truezip:6.8.3' - compile 'rhino:js:1.7R2' - compile 'com.google.guava:guava:21.0' - compile 'com.sk89q:jchronic:0.2.4a' - compile 'com.google.code.findbugs:jsr305:1.3.9' - compile 'com.thoughtworks.paranamer:paranamer:2.6' - compile 'com.google.code.gson:gson:2.8.0' - compile 'com.sk89q.lib:jlibnoise:1.0.0' - compile 'com.googlecode.json-simple:json-simple:1.1.1' - compile 'org.slf4j:slf4j-api:1.7.26' - //compile 'net.sf.trove4j:trove4j:3.0.3' - testCompile 'org.mockito:mockito-core:1.9.0-rc1' - - // Fawe depends - compile 'org.yaml:snakeyaml:1.19' - compile 'net.fabiozumbi12:redprotect:1.9.6' - compile ("com.github.intellectualsites.plotsquared:PlotSquared-API:latest") { - transitive = false - } - compile 'com.github.luben:zstd-jni:1.1.1' - compile 'co.aikar:fastutil-lite:1.0' -} - -sourceSets { - main { - java { - srcDir 'src/main/java' - srcDir 'src/legacy/java' - } - resources { - srcDir 'src/main/resources' - } - } -} - -processResources { - from('src/main/resources') { - include 'fawe.properties' - expand( - internalVersion: "${project.parent.version}", - name: project.parent.name, - ) - } -} - -jar.archiveName="fawe-api-${project.parent.version}.jar" -jar.destinationDir = file '../mvn/com/boydti/fawe-api/' + project.parent.version -task createPom << { - pom { - project { - groupId 'com.boydti' - artifactId 'fawe-api' - version project.parent.version - } - } - .getEffectivePom() - .setDependencies(new ArrayList<>()) - .writeTo("../mvn/com/boydti/fawe-api/${project.parent.version}/fawe-api-${project.parent.version}.pom") - pom { - project { - groupId 'com.boydti' - artifactId 'fawe-api' - version 'latest' - } - } - .getEffectivePom() - .setDependencies(new ArrayList<>()) - .writeTo("../mvn/com/boydti/fawe-api/latest/fawe-api-latest.pom") -} -task copyFiles { - doLast { - copy { - from "../mvn/com/boydti/fawe-api/${project.parent.version}/" - into '../mvn/com/boydti/fawe-api/latest/' - include('*.jar') - rename ("fawe-api-${project.parent.version}.jar", 'fawe-api-latest.jar') - } - } -} - -build.dependsOn(shadowJar) -build.finalizedBy(copyFiles) -copyFiles.dependsOn(createPom) +apply plugin: 'eclipse' +apply plugin: 'idea' +repositories { + maven {url "http://ci.athion.net/job/PlotSquared-Breaking/ws/mvn/"} +} +dependencies { + compile 'de.schlichtherle:truezip:6.8.3' + compile 'rhino:js:1.7R2' + compile 'com.google.guava:guava:21.0' + compile 'com.sk89q:jchronic:0.2.4a' + compile 'com.google.code.findbugs:jsr305:1.3.9' + compile 'com.thoughtworks.paranamer:paranamer:2.6' + compile 'com.google.code.gson:gson:2.8.0' + compile 'com.sk89q.lib:jlibnoise:1.0.0' + compile 'com.googlecode.json-simple:json-simple:1.1.1' + compile 'org.slf4j:slf4j-api:1.7.26' + //compile 'net.sf.trove4j:trove4j:3.0.3' + testCompile 'org.mockito:mockito-core:1.9.0-rc1' + + // Fawe depends + compile 'org.yaml:snakeyaml:1.19' + compile 'net.fabiozumbi12:redprotect:1.9.6' + compile ("com.github.intellectualsites.plotsquared:PlotSquared-API:latest") { + transitive = false + } + compile 'com.github.luben:zstd-jni:1.1.1' + compile 'co.aikar:fastutil-lite:1.0' +} + +sourceSets { + main { + java { + srcDir 'src/main/java' + srcDir 'src/legacy/java' + } + resources { + srcDir 'src/main/resources' + } + } +} + +processResources { + from('src/main/resources') { + include 'fawe.properties' + expand( + internalVersion: "${project.parent.version}", + name: project.parent.name, + ) + } +} + +jar.archiveName="fawe-api-${project.parent.version}.jar" +jar.destinationDir = file '../mvn/com/boydti/fawe-api/' + project.parent.version +task createPom << { + pom { + project { + groupId 'com.boydti' + artifactId 'fawe-api' + version project.parent.version + } + } + .getEffectivePom() + .setDependencies(new ArrayList<>()) + .writeTo("../mvn/com/boydti/fawe-api/${project.parent.version}/fawe-api-${project.parent.version}.pom") + pom { + project { + groupId 'com.boydti' + artifactId 'fawe-api' + version 'latest' + } + } + .getEffectivePom() + .setDependencies(new ArrayList<>()) + .writeTo("../mvn/com/boydti/fawe-api/latest/fawe-api-latest.pom") +} +task copyFiles { + doLast { + copy { + from "../mvn/com/boydti/fawe-api/${project.parent.version}/" + into '../mvn/com/boydti/fawe-api/latest/' + include('*.jar') + rename ("fawe-api-${project.parent.version}.jar", 'fawe-api-latest.jar') + } + } +} + +build.dependsOn(shadowJar) +build.finalizedBy(copyFiles) +copyFiles.dependsOn(createPom) diff --git a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SignBlock.java b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SignBlock.java index 60dabd6c7..4cc0e5bcb 100644 --- a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SignBlock.java +++ b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/SignBlock.java @@ -25,6 +25,7 @@ import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.util.gson.GsonUtil; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; + import java.util.HashMap; import java.util.Map; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/configuration/serialization/ConfigurationSerialization.java b/worldedit-core/src/main/java/com/boydti/fawe/configuration/serialization/ConfigurationSerialization.java index 445702c6f..f3249bbbf 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/configuration/serialization/ConfigurationSerialization.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/configuration/serialization/ConfigurationSerialization.java @@ -1,16 +1,16 @@ package com.boydti.fawe.configuration.serialization; +import com.boydti.fawe.configuration.Configuration; +import org.slf4j.LoggerFactory; + import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - /** - * Utility class for storing and retrieving classes for {@link com.boydti.fawe.configuration.Configuration}. + * Utility class for storing and retrieving classes for {@link Configuration}. */ public class ConfigurationSerialization { @@ -27,7 +27,7 @@ public class ConfigurationSerialization { * Attempts to deserialize the given arguments into a new instance of the * given class. *

- *

The class must implement {@link com.boydti.fawe.configuration.serialization.ConfigurationSerializable}, including + *

The class must implement {@link ConfigurationSerializable}, including * the extra methods as specified in the javadoc of * ConfigurationSerializable.

*

@@ -39,7 +39,7 @@ public class ConfigurationSerialization { * @return New instance of the specified class */ public static ConfigurationSerializable deserializeObject(Map args, Class clazz) { - return new com.boydti.fawe.configuration.serialization.ConfigurationSerialization(clazz).deserialize(args); + return new ConfigurationSerialization(clazz).deserialize(args); } /** @@ -47,7 +47,7 @@ public class ConfigurationSerialization { *

* given class. *

- * The class must implement {@link com.boydti.fawe.configuration.serialization.ConfigurationSerializable}, including + * The class must implement {@link ConfigurationSerializable}, including * the extra methods as specified in the javadoc of * ConfigurationSerializable.

*

@@ -80,17 +80,17 @@ public class ConfigurationSerialization { throw new IllegalArgumentException("Args doesn't contain type key ('" + SERIALIZED_TYPE_KEY + "')"); } - return new com.boydti.fawe.configuration.serialization.ConfigurationSerialization(clazz).deserialize(args); + return new ConfigurationSerialization(clazz).deserialize(args); } /** - * Registers the given {@link com.boydti.fawe.configuration.serialization.ConfigurationSerializable} class by its + * Registers the given {@link ConfigurationSerializable} class by its * alias. * * @param clazz Class to register */ public static void registerClass(Class clazz) { - com.boydti.fawe.configuration.serialization.DelegateDeserialization delegate = clazz.getAnnotation(com.boydti.fawe.configuration.serialization.DelegateDeserialization.class); + DelegateDeserialization delegate = clazz.getAnnotation(DelegateDeserialization.class); if (delegate == null) { registerClass(clazz, getAlias(clazz)); @@ -99,19 +99,18 @@ public class ConfigurationSerialization { } /** - * Registers the given alias to the specified {@link - * com.boydti.fawe.configuration.serialization.ConfigurationSerializable} class. + * Registers the given alias to the specified {@link ConfigurationSerializable} class. * * @param clazz Class to register * @param alias Alias to register as - * @see com.boydti.fawe.configuration.serialization.SerializableAs + * @see SerializableAs */ public static void registerClass(Class clazz, String alias) { aliases.put(alias, clazz); } /** - * Unregisters the specified alias to a {@link com.boydti.fawe.configuration.serialization.ConfigurationSerializable} + * Unregisters the specified alias to a {@link ConfigurationSerializable} * * @param alias Alias to unregister */ @@ -120,8 +119,7 @@ public class ConfigurationSerialization { } /** - * Unregisters any aliases for the specified {@link - * com.boydti.fawe.configuration.serialization.ConfigurationSerializable} class. + * Unregisters any aliases for the specified {@link ConfigurationSerializable} class. * * @param clazz Class to unregister */ @@ -131,7 +129,7 @@ public class ConfigurationSerialization { } /** - * Attempts to get a registered {@link com.boydti.fawe.configuration.serialization.ConfigurationSerializable} class by + * Attempts to get a registered {@link ConfigurationSerializable} class by * its alias. * * @param alias Alias of the serializable @@ -142,14 +140,14 @@ public class ConfigurationSerialization { } /** - * Gets the correct alias for the given {@link com.boydti.fawe.configuration.serialization.ConfigurationSerializable} + * Gets the correct alias for the given {@link ConfigurationSerializable} * class. * * @param clazz Class to get alias for * @return Alias to use for the class */ public static String getAlias(Class clazz) { - com.boydti.fawe.configuration.serialization.DelegateDeserialization delegate = clazz.getAnnotation(DelegateDeserialization.class); + DelegateDeserialization delegate = clazz.getAnnotation(DelegateDeserialization.class); if (delegate != null) { if ((delegate.value() == null) || (delegate.value() == clazz)) { @@ -180,9 +178,7 @@ public class ConfigurationSerialization { } return method; - } catch (NoSuchMethodException ex) { - return null; - } catch (SecurityException ex) { + } catch (NoSuchMethodException | SecurityException ex) { return null; } } @@ -190,9 +186,7 @@ public class ConfigurationSerialization { protected Constructor getConstructor() { try { return this.clazz.getConstructor(Map.class); - } catch (NoSuchMethodException ex) { - return null; - } catch (SecurityException ex) { + } catch (NoSuchMethodException | SecurityException ex) { return null; } } @@ -202,14 +196,13 @@ public class ConfigurationSerialization { ConfigurationSerializable result = (ConfigurationSerializable) method.invoke(null, args); if (result == null) { - Logger.getLogger(com.boydti.fawe.configuration.serialization.ConfigurationSerialization.class.getName()).log(Level.SEVERE, + LoggerFactory.getLogger(ConfigurationSerialization.class).error( "Could not call method '" + method.toString() + "' of " + this.clazz + " for deserialization: method returned null"); } else { return result; } } catch (Throwable ex) { - Logger.getLogger(com.boydti.fawe.configuration.serialization.ConfigurationSerialization.class.getName()) - .log(Level.SEVERE, "Could not call method '" + method.toString() + "' of " + this.clazz + LoggerFactory.getLogger(ConfigurationSerialization.class).error("Could not call method '" + method.toString() + "' of " + this.clazz + " for deserialization", ex instanceof InvocationTargetException ? ex.getCause() : ex); } @@ -221,8 +214,7 @@ public class ConfigurationSerialization { try { return ctor.newInstance(args); } catch (Throwable ex) { - Logger.getLogger(com.boydti.fawe.configuration.serialization.ConfigurationSerialization.class.getName()) - .log(Level.SEVERE, "Could not call constructor '" + ctor.toString() + "' of " + this.clazz + LoggerFactory.getLogger(ConfigurationSerialization.class).error("Could not call constructor '" + ctor.toString() + "' of " + this.clazz + " for deserialization", ex instanceof InvocationTargetException ? ex.getCause() : ex); } diff --git a/worldedit-core/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java b/worldedit-core/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java index df3b0806b..f8af6a8c2 100644 --- a/worldedit-core/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java +++ b/worldedit-core/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java @@ -1,585 +1,585 @@ -/* - * 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.minecraft.util.commands; - -import com.sk89q.util.StringUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Manager for handling commands. This allows you to easily process commands, - * including nested commands, by correctly annotating methods of a class. - * - *

To use this, it is merely a matter of registering classes containing - * the commands (as methods with the proper annotations) with the - * manager. When you want to process a command, use one of the - * {@code execute} methods. If something is wrong, such as incorrect - * usage, insufficient permissions, or a missing command altogether, an - * exception will be raised for upstream handling.

- * - *

Methods of a class to be registered can be static, but if an injector - * is registered with the class, the instances of the command classes - * will be created automatically and methods will be called non-statically.

- * - *

To mark a method as a command, use {@link Command}. For nested commands, - * see {@link NestedCommand}. To handle permissions, use - * {@link CommandPermissions}.

- * - *

This uses Java reflection extensively, but to reduce the overhead of - * reflection, command lookups are completely cached on registration. This - * allows for fast command handling. Method invocation still has to be done - * with reflection, but this is quite fast in that of itself.

- * - * @param command sender class - */ -@SuppressWarnings("ProtectedField") -public abstract class CommandsManager { - - protected static final Logger logger = - LoggerFactory.getLogger(CommandsManager.class); - - /** - * Mapping of commands (including aliases) with a description. Root - * commands are stored under a key of null, whereas child commands are - * cached under their respective {@link Method}. The child map has - * the key of the command name (one for each alias) with the - * method. - */ - protected Map> commands = new HashMap<>(); - - /** - * Used to store the instances associated with a method. - */ - protected Map instances = new HashMap<>(); - - /** - * Mapping of commands (not including aliases) with a description. This - * is only for top level commands. - */ - protected Map descs = new HashMap<>(); - - /** - * Stores the injector used to getInstance. - */ - protected Injector injector; - - /** - * Mapping of commands (not including aliases) with a description. This - * is only for top level commands. - */ - protected Map helpMessages = new HashMap<>(); - - /** - * Register an class that contains commands (denoted by {@link Command}. - * If no dependency injector is specified, then the methods of the - * class will be registered to be called statically. Otherwise, new - * instances will be created of the command classes and methods will - * not be called statically. - * - * @param cls the class to register - */ - public void register(Class cls) { - registerMethods(cls, null); - } - - /** - * Register an class that contains commands (denoted by {@link Command}. - * If no dependency injector is specified, then the methods of the - * class will be registered to be called statically. Otherwise, new - * instances will be created of the command classes and methods will - * not be called statically. A List of {@link Command} annotations from - * registered commands is returned. - * - * @param cls the class to register - * @return A List of {@link Command} annotations from registered commands, - * for use in eg. a dynamic command registration system. - */ - public List registerAndReturn(Class cls) { - return registerMethods(cls, null); - } - - /** - * Register the methods of a class. This will automatically construct - * instances as necessary. - * - * @param cls the class to register - * @param parent the parent method - * @return Commands Registered - */ - public List registerMethods(Class cls, Method parent) { - try { - if (getInjector() == null) { - return registerMethods(cls, parent, null); - } else { - Object obj = getInjector().getInstance(cls); - return registerMethods(cls, parent, obj); - } - } catch (InvocationTargetException | InstantiationException | IllegalAccessException e) { - logger.error("Failed to register commands", e); - } - return null; - } - - /** - * Register the methods of a class. - * - * @param cls the class to register - * @param parent the parent method - * @param obj the object whose methods will become commands if they are annotated - * @return a list of commands - */ - private List registerMethods(Class cls, Method parent, Object obj) { - Map map; - List registered = new ArrayList<>(); - - // Make a new hash map to cache the commands for this class - // as looking up methods via reflection is fairly slow - if (commands.containsKey(parent)) { - map = commands.get(parent); - } else { - map = new HashMap<>(); - commands.put(parent, map); - } - - for (Method method : cls.getMethods()) { - if (!method.isAnnotationPresent(Command.class)) { - continue; - } - - boolean isStatic = Modifier.isStatic(method.getModifiers()); - - Command cmd = method.getAnnotation(Command.class); - - // Cache the aliases too - for (String alias : cmd.aliases()) { - map.put(alias, method); - } - - // We want to be able invoke with an instance - if (!isStatic) { - // Can't register this command if we don't have an instance - if (obj == null) { - continue; - } - - instances.put(method, obj); - } - - // Build a list of commands and their usage details, at least for - // root level commands - if (parent == null) { - final String commandName = cmd.aliases()[0]; - final String desc = cmd.desc(); - - final String usage = cmd.usage(); - if (usage.isEmpty()) { - descs.put(commandName, desc); - } else { - descs.put(commandName, usage + " - " + desc); - } - - String help = cmd.help(); - if (help.isEmpty()) { - help = desc; - } - - final CharSequence arguments = getArguments(cmd); - for (String alias : cmd.aliases()) { - final String helpMessage = "/" + alias + " " + arguments + "\n\n" + help; - final String key = alias.replaceAll("/", ""); - String previous = helpMessages.put(key, helpMessage); - - if (previous != null && !previous.replaceAll("^/[^ ]+ ", "").equals(helpMessage.replaceAll("^/[^ ]+ ", ""))) { - helpMessages.put(key, previous + "\n\n" + helpMessage); - } - } - - } - - // Add the command to the registered command list for return - registered.add(cmd); - - // Look for nested commands -- if there are any, those have - // to be cached too so that they can be quickly looked - // up when processing commands - if (method.isAnnotationPresent(NestedCommand.class)) { - NestedCommand nestedCmd = method.getAnnotation(NestedCommand.class); - - for (Class nestedCls : nestedCmd.value()) { - registerMethods(nestedCls, method); - } - } - } - - if (cls.getSuperclass() != null) { - registerMethods(cls.getSuperclass(), parent, obj); - } - - return registered; - } - - /** - * Checks to see whether there is a command named such at the root level. - * This will check aliases as well. - * - * @param command the command - * @return true if the command exists - */ - public boolean hasCommand(String command) { - return commands.get(null).containsKey(command.toLowerCase()); - } - - /** - * Get a list of command descriptions. This is only for root commands. - * - * @return a map of commands - */ - public Map getCommands() { - return descs; - } - - /** - * Get the mapping of methods under a parent command. - * - * @return the mapping - */ - public Map> getMethods() { - return commands; - } - - /** - * Get a map from command name to help message. This is only for root commands. - * - * @return a map of help messages for each command - */ - public Map getHelpMessages() { - return helpMessages; - } - - /** - * Get the usage string for a command. - * - * @param args the arguments - * @param level the depth of the command - * @param cmd the command annotation - * @return the usage string - */ - protected String getUsage(String[] args, int level, Command cmd) { - final StringBuilder command = new StringBuilder(); - - command.append('/'); - - for (int i = 0; i <= level; ++i) { - command.append(args[i]); - command.append(' '); - } - command.append(getArguments(cmd)); - - final String help = cmd.help(); - if (!help.isEmpty()) { - command.append("\n\n"); - command.append(help); - } - - return command.toString(); - } - - protected CharSequence getArguments(Command cmd) { - final String flags = cmd.flags(); - - final StringBuilder command2 = new StringBuilder(); - if (!flags.isEmpty()) { - String flagString = flags.replaceAll(".:", ""); - if (!flagString.isEmpty()) { - command2.append("[-"); - for (int i = 0; i < flagString.length(); ++i) { - command2.append(flagString.charAt(i)); - } - command2.append("] "); - } - } - - command2.append(cmd.usage()); - - return command2; - } - - /** - * Get the usage string for a nested command. - * - * @param args the arguments - * @param level the depth of the command - * @param method the parent method - * @param player the player - * @return the usage string - * @throws CommandException on some error - */ - protected String getNestedUsage(String[] args, int level, Method method, T player) throws CommandException { - StringBuilder command = new StringBuilder(); - - command.append("/"); - - for (int i = 0; i <= level; ++i) { - command.append(args[i]).append(" "); - } - - Map map = commands.get(method); - boolean found = false; - - command.append("<"); - - Set allowedCommands = new HashSet<>(); - - for (Map.Entry entry : map.entrySet()) { - Method childMethod = entry.getValue(); - found = true; - - if (hasPermission(childMethod, player)) { - Command childCmd = childMethod.getAnnotation(Command.class); - - allowedCommands.add(childCmd.aliases()[0]); - } - } - - if (!allowedCommands.isEmpty()) { - command.append(StringUtil.joinString(allowedCommands, "|", 0)); - } else { - if (!found) { - command.append("?"); - } else { - //command.append("action"); - throw new CommandPermissionsException(); - } - } - - command.append(">"); - - return command.toString(); - } - - /** - * Attempt to execute a command. This version takes a separate command - * name (for the root command) and then a list of following arguments. - * - * @param cmd command to run - * @param args arguments - * @param player command source - * @param methodArgs method arguments - * @throws CommandException thrown when the command throws an error - */ - public void execute(String cmd, String[] args, T player, Object... methodArgs) throws CommandException { - - String[] newArgs = new String[args.length + 1]; - System.arraycopy(args, 0, newArgs, 1, args.length); - newArgs[0] = cmd; - Object[] newMethodArgs = new Object[methodArgs.length + 1]; - System.arraycopy(methodArgs, 0, newMethodArgs, 1, methodArgs.length); - - executeMethod(null, newArgs, player, newMethodArgs, 0); - } - - /** - * Attempt to execute a command. - * - * @param args the arguments - * @param player the player - * @param methodArgs the arguments for the method - * @throws CommandException thrown on command error - */ - public void execute(String[] args, T player, Object... methodArgs) throws CommandException { - Object[] newMethodArgs = new Object[methodArgs.length + 1]; - System.arraycopy(methodArgs, 0, newMethodArgs, 1, methodArgs.length); - executeMethod(null, args, player, newMethodArgs, 0); - } - - /** - * Attempt to execute a command. - * - * @param parent the parent method - * @param args an array of arguments - * @param player the player - * @param methodArgs the array of method arguments - * @param level the depth of the command - * @throws CommandException thrown on a command error - */ - public void executeMethod(Method parent, String[] args, T player, Object[] methodArgs, int level) throws CommandException { - String cmdName = args[level]; - - Map map = commands.get(parent); - Method method = map.get(cmdName.toLowerCase()); - - if (method == null) { - if (parent == null) { // Root - throw new UnhandledCommandException(); - } else { - throw new MissingNestedCommandException("Unknown command: " + cmdName, - getNestedUsage(args, level - 1, parent, player)); - } - } - - checkPermission(player, method); - - int argsCount = args.length - 1 - level; - - // checks if we need to execute the body of the nested command method (false) - // or display the help what commands are available (true) - // this is all for an args count of 0 if it is > 0 and a NestedCommand Annotation is present - // it will always handle the methods that NestedCommand points to - // e.g.: - // - /cmd - @NestedCommand(executeBody = true) will go into the else loop and execute code in that method - // - /cmd - @NestedCommand(executeBody = true) will always go to the nested command class - // - /cmd - @NestedCommand(executeBody = false) will always go to the nested command class not matter the args - boolean executeNested = method.isAnnotationPresent(NestedCommand.class) - && (argsCount > 0 || !method.getAnnotation(NestedCommand.class).executeBody()); - - if (executeNested) { - if (argsCount == 0) { - throw new MissingNestedCommandException("Sub-command required.", - getNestedUsage(args, level, method, player)); - } else { - executeMethod(method, args, player, methodArgs, level + 1); - } - } else if (method.isAnnotationPresent(CommandAlias.class)) { - CommandAlias aCmd = method.getAnnotation(CommandAlias.class); - executeMethod(parent, aCmd.value(), player, methodArgs, level); - } else { - Command cmd = method.getAnnotation(Command.class); - - String[] newArgs = new String[args.length - level]; - System.arraycopy(args, level, newArgs, 0, args.length - level); - - final Set valueFlags = new HashSet<>(); - - char[] flags = cmd.flags().toCharArray(); - Set newFlags = new HashSet<>(); - for (int i = 0; i < flags.length; ++i) { - if (flags.length > i + 1 && flags[i + 1] == ':') { - valueFlags.add(flags[i]); - ++i; - } - newFlags.add(flags[i]); - } - - CommandContext context = new CommandContext(newArgs, valueFlags); - - if (context.argsLength() < cmd.min()) { - throw new CommandUsageException("Too few arguments.", getUsage(args, level, cmd)); - } - - if (cmd.max() != -1 && context.argsLength() > cmd.max()) { - throw new CommandUsageException("Too many arguments.", getUsage(args, level, cmd)); - } - - if (!cmd.anyFlags()) { - for (char flag : context.getFlags()) { - if (!newFlags.contains(flag)) { - throw new CommandUsageException("Unknown flag: " + flag, getUsage(args, level, cmd)); - } - } - } - - methodArgs[0] = context; - - Object instance = instances.get(method); - - invokeMethod(parent, args, player, method, instance, methodArgs, argsCount); - } - } - - protected void checkPermission(T player, Method method) throws CommandException { - if (!hasPermission(method, player)) { - throw new CommandPermissionsException(); - } - } - - public void invokeMethod(Method parent, String[] args, T player, Method method, Object instance, Object[] methodArgs, int level) throws CommandException { - try { - method.invoke(instance, methodArgs); - } catch (IllegalArgumentException | IllegalAccessException e) { - logger.error("Failed to execute command", e); - } catch (InvocationTargetException e) { - if (e.getCause() instanceof CommandException) { - throw (CommandException) e.getCause(); - } - - throw new WrappedCommandException(e.getCause()); - } - } - - /** - * Returns whether a player has access to a command. - * - * @param method the method - * @param player the player - * @return true if permission is granted - */ - protected boolean hasPermission(Method method, T player) { - CommandPermissions perms = method.getAnnotation(CommandPermissions.class); - if (perms == null) { - return true; - } - - for (String perm : perms.value()) { - if (hasPermission(player, perm)) { - return true; - } - } - - return false; - } - - /** - * Returns whether a player permission.. - * - * @param player the player - * @param permission the permission - * @return true if permission is granted - */ - public abstract boolean hasPermission(T player, String permission); - - /** - * Get the injector used to create new instances. This can be - * null, in which case only classes will be registered statically. - * - * @return an injector instance - */ - public Injector getInjector() { - return injector; - } - - /** - * Set the injector for creating new instances. - * - * @param injector injector or null - */ - public void setInjector(Injector injector) { - this.injector = injector; - } -} +/* + * 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.minecraft.util.commands; + +import com.sk89q.util.StringUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Manager for handling commands. This allows you to easily process commands, + * including nested commands, by correctly annotating methods of a class. + * + *

To use this, it is merely a matter of registering classes containing + * the commands (as methods with the proper annotations) with the + * manager. When you want to process a command, use one of the + * {@code execute} methods. If something is wrong, such as incorrect + * usage, insufficient permissions, or a missing command altogether, an + * exception will be raised for upstream handling.

+ * + *

Methods of a class to be registered can be static, but if an injector + * is registered with the class, the instances of the command classes + * will be created automatically and methods will be called non-statically.

+ * + *

To mark a method as a command, use {@link Command}. For nested commands, + * see {@link NestedCommand}. To handle permissions, use + * {@link CommandPermissions}.

+ * + *

This uses Java reflection extensively, but to reduce the overhead of + * reflection, command lookups are completely cached on registration. This + * allows for fast command handling. Method invocation still has to be done + * with reflection, but this is quite fast in that of itself.

+ * + * @param command sender class + */ +@SuppressWarnings("ProtectedField") +public abstract class CommandsManager { + + protected static final Logger logger = + LoggerFactory.getLogger(CommandsManager.class); + + /** + * Mapping of commands (including aliases) with a description. Root + * commands are stored under a key of null, whereas child commands are + * cached under their respective {@link Method}. The child map has + * the key of the command name (one for each alias) with the + * method. + */ + protected Map> commands = new HashMap<>(); + + /** + * Used to store the instances associated with a method. + */ + protected Map instances = new HashMap<>(); + + /** + * Mapping of commands (not including aliases) with a description. This + * is only for top level commands. + */ + protected Map descs = new HashMap<>(); + + /** + * Stores the injector used to getInstance. + */ + protected Injector injector; + + /** + * Mapping of commands (not including aliases) with a description. This + * is only for top level commands. + */ + protected Map helpMessages = new HashMap<>(); + + /** + * Register an class that contains commands (denoted by {@link Command}. + * If no dependency injector is specified, then the methods of the + * class will be registered to be called statically. Otherwise, new + * instances will be created of the command classes and methods will + * not be called statically. + * + * @param cls the class to register + */ + public void register(Class cls) { + registerMethods(cls, null); + } + + /** + * Register an class that contains commands (denoted by {@link Command}. + * If no dependency injector is specified, then the methods of the + * class will be registered to be called statically. Otherwise, new + * instances will be created of the command classes and methods will + * not be called statically. A List of {@link Command} annotations from + * registered commands is returned. + * + * @param cls the class to register + * @return A List of {@link Command} annotations from registered commands, + * for use in eg. a dynamic command registration system. + */ + public List registerAndReturn(Class cls) { + return registerMethods(cls, null); + } + + /** + * Register the methods of a class. This will automatically construct + * instances as necessary. + * + * @param cls the class to register + * @param parent the parent method + * @return Commands Registered + */ + public List registerMethods(Class cls, Method parent) { + try { + if (getInjector() == null) { + return registerMethods(cls, parent, null); + } else { + Object obj = getInjector().getInstance(cls); + return registerMethods(cls, parent, obj); + } + } catch (InvocationTargetException | InstantiationException | IllegalAccessException e) { + logger.error("Failed to register commands", e); + } + return null; + } + + /** + * Register the methods of a class. + * + * @param cls the class to register + * @param parent the parent method + * @param obj the object whose methods will become commands if they are annotated + * @return a list of commands + */ + private List registerMethods(Class cls, Method parent, Object obj) { + Map map; + List registered = new ArrayList<>(); + + // Make a new hash map to cache the commands for this class + // as looking up methods via reflection is fairly slow + if (commands.containsKey(parent)) { + map = commands.get(parent); + } else { + map = new HashMap<>(); + commands.put(parent, map); + } + + for (Method method : cls.getMethods()) { + if (!method.isAnnotationPresent(Command.class)) { + continue; + } + + boolean isStatic = Modifier.isStatic(method.getModifiers()); + + Command cmd = method.getAnnotation(Command.class); + + // Cache the aliases too + for (String alias : cmd.aliases()) { + map.put(alias, method); + } + + // We want to be able invoke with an instance + if (!isStatic) { + // Can't register this command if we don't have an instance + if (obj == null) { + continue; + } + + instances.put(method, obj); + } + + // Build a list of commands and their usage details, at least for + // root level commands + if (parent == null) { + final String commandName = cmd.aliases()[0]; + final String desc = cmd.desc(); + + final String usage = cmd.usage(); + if (usage.isEmpty()) { + descs.put(commandName, desc); + } else { + descs.put(commandName, usage + " - " + desc); + } + + String help = cmd.help(); + if (help.isEmpty()) { + help = desc; + } + + final CharSequence arguments = getArguments(cmd); + for (String alias : cmd.aliases()) { + final String helpMessage = "/" + alias + " " + arguments + "\n\n" + help; + final String key = alias.replaceAll("/", ""); + String previous = helpMessages.put(key, helpMessage); + + if (previous != null && !previous.replaceAll("^/[^ ]+ ", "").equals(helpMessage.replaceAll("^/[^ ]+ ", ""))) { + helpMessages.put(key, previous + "\n\n" + helpMessage); + } + } + + } + + // Add the command to the registered command list for return + registered.add(cmd); + + // Look for nested commands -- if there are any, those have + // to be cached too so that they can be quickly looked + // up when processing commands + if (method.isAnnotationPresent(NestedCommand.class)) { + NestedCommand nestedCmd = method.getAnnotation(NestedCommand.class); + + for (Class nestedCls : nestedCmd.value()) { + registerMethods(nestedCls, method); + } + } + } + + if (cls.getSuperclass() != null) { + registerMethods(cls.getSuperclass(), parent, obj); + } + + return registered; + } + + /** + * Checks to see whether there is a command named such at the root level. + * This will check aliases as well. + * + * @param command the command + * @return true if the command exists + */ + public boolean hasCommand(String command) { + return commands.get(null).containsKey(command.toLowerCase()); + } + + /** + * Get a list of command descriptions. This is only for root commands. + * + * @return a map of commands + */ + public Map getCommands() { + return descs; + } + + /** + * Get the mapping of methods under a parent command. + * + * @return the mapping + */ + public Map> getMethods() { + return commands; + } + + /** + * Get a map from command name to help message. This is only for root commands. + * + * @return a map of help messages for each command + */ + public Map getHelpMessages() { + return helpMessages; + } + + /** + * Get the usage string for a command. + * + * @param args the arguments + * @param level the depth of the command + * @param cmd the command annotation + * @return the usage string + */ + protected String getUsage(String[] args, int level, Command cmd) { + final StringBuilder command = new StringBuilder(); + + command.append('/'); + + for (int i = 0; i <= level; ++i) { + command.append(args[i]); + command.append(' '); + } + command.append(getArguments(cmd)); + + final String help = cmd.help(); + if (!help.isEmpty()) { + command.append("\n\n"); + command.append(help); + } + + return command.toString(); + } + + protected CharSequence getArguments(Command cmd) { + final String flags = cmd.flags(); + + final StringBuilder command2 = new StringBuilder(); + if (!flags.isEmpty()) { + String flagString = flags.replaceAll(".:", ""); + if (!flagString.isEmpty()) { + command2.append("[-"); + for (int i = 0; i < flagString.length(); ++i) { + command2.append(flagString.charAt(i)); + } + command2.append("] "); + } + } + + command2.append(cmd.usage()); + + return command2; + } + + /** + * Get the usage string for a nested command. + * + * @param args the arguments + * @param level the depth of the command + * @param method the parent method + * @param player the player + * @return the usage string + * @throws CommandException on some error + */ + protected String getNestedUsage(String[] args, int level, Method method, T player) throws CommandException { + StringBuilder command = new StringBuilder(); + + command.append("/"); + + for (int i = 0; i <= level; ++i) { + command.append(args[i]).append(" "); + } + + Map map = commands.get(method); + boolean found = false; + + command.append("<"); + + Set allowedCommands = new HashSet<>(); + + for (Map.Entry entry : map.entrySet()) { + Method childMethod = entry.getValue(); + found = true; + + if (hasPermission(childMethod, player)) { + Command childCmd = childMethod.getAnnotation(Command.class); + + allowedCommands.add(childCmd.aliases()[0]); + } + } + + if (!allowedCommands.isEmpty()) { + command.append(StringUtil.joinString(allowedCommands, "|", 0)); + } else { + if (!found) { + command.append("?"); + } else { + //command.append("action"); + throw new CommandPermissionsException(); + } + } + + command.append(">"); + + return command.toString(); + } + + /** + * Attempt to execute a command. This version takes a separate command + * name (for the root command) and then a list of following arguments. + * + * @param cmd command to run + * @param args arguments + * @param player command source + * @param methodArgs method arguments + * @throws CommandException thrown when the command throws an error + */ + public void execute(String cmd, String[] args, T player, Object... methodArgs) throws CommandException { + + String[] newArgs = new String[args.length + 1]; + System.arraycopy(args, 0, newArgs, 1, args.length); + newArgs[0] = cmd; + Object[] newMethodArgs = new Object[methodArgs.length + 1]; + System.arraycopy(methodArgs, 0, newMethodArgs, 1, methodArgs.length); + + executeMethod(null, newArgs, player, newMethodArgs, 0); + } + + /** + * Attempt to execute a command. + * + * @param args the arguments + * @param player the player + * @param methodArgs the arguments for the method + * @throws CommandException thrown on command error + */ + public void execute(String[] args, T player, Object... methodArgs) throws CommandException { + Object[] newMethodArgs = new Object[methodArgs.length + 1]; + System.arraycopy(methodArgs, 0, newMethodArgs, 1, methodArgs.length); + executeMethod(null, args, player, newMethodArgs, 0); + } + + /** + * Attempt to execute a command. + * + * @param parent the parent method + * @param args an array of arguments + * @param player the player + * @param methodArgs the array of method arguments + * @param level the depth of the command + * @throws CommandException thrown on a command error + */ + public void executeMethod(Method parent, String[] args, T player, Object[] methodArgs, int level) throws CommandException { + String cmdName = args[level]; + + Map map = commands.get(parent); + Method method = map.get(cmdName.toLowerCase()); + + if (method == null) { + if (parent == null) { // Root + throw new UnhandledCommandException(); + } else { + throw new MissingNestedCommandException("Unknown command: " + cmdName, + getNestedUsage(args, level - 1, parent, player)); + } + } + + checkPermission(player, method); + + int argsCount = args.length - 1 - level; + + // checks if we need to execute the body of the nested command method (false) + // or display the help what commands are available (true) + // this is all for an args count of 0 if it is > 0 and a NestedCommand Annotation is present + // it will always handle the methods that NestedCommand points to + // e.g.: + // - /cmd - @NestedCommand(executeBody = true) will go into the else loop and execute code in that method + // - /cmd - @NestedCommand(executeBody = true) will always go to the nested command class + // - /cmd - @NestedCommand(executeBody = false) will always go to the nested command class not matter the args + boolean executeNested = method.isAnnotationPresent(NestedCommand.class) + && (argsCount > 0 || !method.getAnnotation(NestedCommand.class).executeBody()); + + if (executeNested) { + if (argsCount == 0) { + throw new MissingNestedCommandException("Sub-command required.", + getNestedUsage(args, level, method, player)); + } else { + executeMethod(method, args, player, methodArgs, level + 1); + } + } else if (method.isAnnotationPresent(CommandAlias.class)) { + CommandAlias aCmd = method.getAnnotation(CommandAlias.class); + executeMethod(parent, aCmd.value(), player, methodArgs, level); + } else { + Command cmd = method.getAnnotation(Command.class); + + String[] newArgs = new String[args.length - level]; + System.arraycopy(args, level, newArgs, 0, args.length - level); + + final Set valueFlags = new HashSet<>(); + + char[] flags = cmd.flags().toCharArray(); + Set newFlags = new HashSet<>(); + for (int i = 0; i < flags.length; ++i) { + if (flags.length > i + 1 && flags[i + 1] == ':') { + valueFlags.add(flags[i]); + ++i; + } + newFlags.add(flags[i]); + } + + CommandContext context = new CommandContext(newArgs, valueFlags); + + if (context.argsLength() < cmd.min()) { + throw new CommandUsageException("Too few arguments.", getUsage(args, level, cmd)); + } + + if (cmd.max() != -1 && context.argsLength() > cmd.max()) { + throw new CommandUsageException("Too many arguments.", getUsage(args, level, cmd)); + } + + if (!cmd.anyFlags()) { + for (char flag : context.getFlags()) { + if (!newFlags.contains(flag)) { + throw new CommandUsageException("Unknown flag: " + flag, getUsage(args, level, cmd)); + } + } + } + + methodArgs[0] = context; + + Object instance = instances.get(method); + + invokeMethod(parent, args, player, method, instance, methodArgs, argsCount); + } + } + + protected void checkPermission(T player, Method method) throws CommandException { + if (!hasPermission(method, player)) { + throw new CommandPermissionsException(); + } + } + + public void invokeMethod(Method parent, String[] args, T player, Method method, Object instance, Object[] methodArgs, int level) throws CommandException { + try { + method.invoke(instance, methodArgs); + } catch (IllegalArgumentException | IllegalAccessException e) { + logger.error("Failed to execute command", e); + } catch (InvocationTargetException e) { + if (e.getCause() instanceof CommandException) { + throw (CommandException) e.getCause(); + } + + throw new WrappedCommandException(e.getCause()); + } + } + + /** + * Returns whether a player has access to a command. + * + * @param method the method + * @param player the player + * @return true if permission is granted + */ + protected boolean hasPermission(Method method, T player) { + CommandPermissions perms = method.getAnnotation(CommandPermissions.class); + if (perms == null) { + return true; + } + + for (String perm : perms.value()) { + if (hasPermission(player, perm)) { + return true; + } + } + + return false; + } + + /** + * Returns whether a player permission.. + * + * @param player the player + * @param permission the permission + * @return true if permission is granted + */ + public abstract boolean hasPermission(T player, String permission); + + /** + * Get the injector used to create new instances. This can be + * null, in which case only classes will be registered statically. + * + * @return an injector instance + */ + public Injector getInjector() { + return injector; + } + + /** + * Set the injector for creating new instances. + * + * @param injector injector or null + */ + public void setInjector(Injector injector) { + this.injector = injector; + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index 69642107a..501b602ca 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -168,7 +168,6 @@ import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.*; import com.sk89q.worldedit.world.registry.LegacyMapper; import com.sk89q.worldedit.world.weather.WeatherType; -import javafx.stage.Stage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -186,7 +185,7 @@ import static com.sk89q.worldedit.regions.Regions.minimumBlockY; /** * An {@link Extent} that handles history, {@link BlockBag}s, change limits, * block re-ordering, and much more. Most operations in WorldEdit use this class. - *

+ * *

Most of the actual functionality is implemented with a number of other * {@link Extent}s that are chained together. For example, history is logged * using the {@link ChangeSetExtent}.

@@ -195,6 +194,10 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, private static final Logger log = LoggerFactory.getLogger(EditSession.class); + /** + * Used by {@link EditSession#setBlock(BlockVector3, BlockStateHolder, Stage)} to + * determine which {@link Extent}s should be bypassed. + */ public enum Stage { BEFORE_HISTORY, BEFORE_REORDER, @@ -1490,7 +1493,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, * @return the number of blocks that matched the pattern */ public int countBlocks(final Region region, final Set searchBlocks) { - final Mask mask = new BlockMaskBuilder().addBlocks(searchBlocks).build(extent); + Mask mask = new BlockMaskBuilder().addBlocks(searchBlocks).build(extent); RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() { @Override public boolean apply(BlockVector3 position) throws WorldEditException { @@ -1582,7 +1585,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, * @throws MaxChangedBlocksException thrown if too many blocks are changed */ public > int fillXZ(BlockVector3 origin, B block, double radius, int depth, boolean recursive) throws MaxChangedBlocksException { - return fillXZ(origin, new BlockPattern(block), radius, depth, recursive); + return fillXZ(origin, block, radius, depth, recursive); } /** * Fills an area recursively in the X/Z directions. @@ -1636,10 +1639,11 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, checkArgument(apothem >= 1, "apothem >= 1"); checkArgument(height >= 1, "height >= 1"); - final Region region = new CuboidRegion(this.getWorld(), // Causes clamping of Y range + Region region = new CuboidRegion( + getWorld(), // Causes clamping of Y range position.add(-apothem + 1, 0, -apothem + 1), position.add(apothem - 1, height - 1, apothem - 1)); - final Pattern pattern = BlockTypes.AIR.getDefaultState(); - return this.setBlocks(region, pattern); + Pattern pattern = BlockTypes.AIR.getDefaultState(); + return setBlocks(region, pattern); } /** @@ -1656,10 +1660,10 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, checkArgument(apothem >= 1, "apothem >= 1"); checkArgument(height >= 1, "height >= 1"); - final Region region = new CuboidRegion(this.getWorld(), // Causes clamping of Y range + Region region = new CuboidRegion(getWorld(), // Causes clamping of Y range position.add(-apothem + 1, 0, -apothem + 1), position.add(apothem - 1, -height + 1, apothem - 1)); - final Pattern pattern = BlockTypes.AIR.getDefaultState(); - return this.setBlocks(region, pattern); + Pattern pattern = (BlockTypes.AIR.getDefaultState()); + return setBlocks(region, pattern); } /** @@ -1724,7 +1728,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, getWorld(), // Causes clamping of Y range position.add(adjustment.multiply(-1)), position.add(adjustment)); - Pattern pattern = new BlockPattern(BlockTypes.AIR.getDefaultState()); + Pattern pattern = (BlockTypes.AIR.getDefaultState()); return replaceBlocks(region, mask, pattern); } @@ -1750,9 +1754,8 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, Operations.completeBlindly(visitor); this.changes += visitor.getAffected(); } else { - Iterator iter = region.iterator(); - while (iter.hasNext()) { - if (this.extent.setBlock(iter.next(), block)) { + for (BlockVector3 blockVector3 : region) { + if (this.extent.setBlock(blockVector3, block)) { changes++; } } @@ -1797,7 +1800,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, * @throws MaxChangedBlocksException thrown if too many blocks are changed */ public > int replaceBlocks(Region region, Set filter, B replacement) throws MaxChangedBlocksException { - return replaceBlocks(region, filter, new BlockPattern(replacement)); + return replaceBlocks(region, filter, (replacement)); } /** @@ -1825,8 +1828,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, * @return number of blocks affected * @throws MaxChangedBlocksException thrown if too many blocks are changed */ - @SuppressWarnings("deprecation") - public int replaceBlocks(final Region region, final Mask mask, final Pattern pattern) { + public int replaceBlocks(Region region, Mask mask, Pattern pattern) throws MaxChangedBlocksException { checkNotNull(region); checkNotNull(mask); checkNotNull(pattern); @@ -1989,7 +1991,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, */ public > int overlayCuboidBlocks(Region region, B block) throws MaxChangedBlocksException { checkNotNull(block); - return overlayCuboidBlocks(region, new BlockPattern(block)); + return overlayCuboidBlocks(region, (block)); } /** @@ -2992,8 +2994,8 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, } return BlockTypes.get((int) typeVariable.getValue()).withPropertyId((int) dataVariable.getValue()).toBaseBlock(); - } catch (final Exception e) { - Fawe.debug("Failed to create shape: " + e); + } catch (Exception e) { + log.warn("Failed to create shape", e); return null; } } @@ -3369,8 +3371,8 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, } return defaultBiomeType; - } catch (final Exception e) { - Fawe.debug("Failed to create shape: " + e); + } catch (Exception e) { + log.warn("Failed to create shape", e); return null; } } @@ -3428,9 +3430,9 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, } private void setExistingBlocks(BlockVector3 pos1, BlockVector3 pos2) { - for (int x = (int) pos1.getX(); x <= (int) pos2.getX(); x++) { + for (int x = pos1.getX(); x <= pos2.getX(); x++) { for (int z = pos1.getBlockZ(); z <= pos2.getBlockZ(); z++) { - for (int y = (int) pos1.getY(); y <= (int) pos2.getY(); y++) { + for (int y = pos1.getY(); y <= pos2.getY(); y++) { int from = queue.getCombinedId4Data(x, y, z); queue.setBlock(x, y, z, from); if (BlockTypes.getFromStateId(from).getMaterial().hasContainer()) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index ad9eae94e..c4a98e797 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -96,7 +96,6 @@ import static com.google.common.base.Preconditions.checkNotNull; */ public class LocalSession implements TextureHolder { - @Deprecated public transient static int MAX_HISTORY_SIZE = 15; // Non-session related fields @@ -1494,4 +1493,4 @@ public class LocalSession implements TextureHolder { } -} \ No newline at end of file +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/Blocks.java b/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/Blocks.java index 1f65c6a19..c0776f995 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/Blocks.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/blocks/Blocks.java @@ -21,11 +21,14 @@ package com.sk89q.worldedit.blocks; import com.google.common.collect.Maps; import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.world.block.BlockCategories; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import java.util.Collection; +import java.util.HashSet; import java.util.Map; +import java.util.Set; /** * Block-related utility methods. diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java index 48aaa4d39..c36fa5b53 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java @@ -35,6 +35,7 @@ import com.sk89q.worldedit.math.MathUtils; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.storage.LegacyChunkStore; import com.sk89q.worldedit.world.storage.McRegionChunkStore; + import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; @@ -184,4 +185,5 @@ public class ChunkCommands { player.printError(BBC.getPrefix() + "Shell script type must be configured: 'bat' or 'bash' expected."); } } + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java index e9832489e..d791810c5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java @@ -19,6 +19,9 @@ package com.sk89q.worldedit.command; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION; + import com.boydti.fawe.FaweAPI; import com.boydti.fawe.config.BBC; import com.boydti.fawe.util.MathMan; @@ -35,10 +38,6 @@ import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.world.World; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION; - /** * Commands for moving the player around. */ @@ -58,11 +57,11 @@ public class NavigationCommands { } @Command( - aliases = {"unstuck", "!"}, - usage = "", - desc = "Escape from being stuck inside a block", - min = 0, - max = 0 + aliases = { "unstuck", "!" }, + usage = "", + desc = "Escape from being stuck inside a block", + min = 0, + max = 0 ) @CommandPermissions("worldedit.navigation.unstuck") public void unstuck(Player player) throws WorldEditException { @@ -234,4 +233,4 @@ public class NavigationCommands { } -} \ No newline at end of file +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index 281fb66ac..a01b9a8a0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -299,8 +299,8 @@ public class RegionCommands extends MethodCommands { } @Command( - aliases = {"/replace", "/re", "/rep", "/r"}, - usage = "[from-mask] ", + aliases = { "/replace", "/re", "/rep" }, + usage = "[from-block] ", desc = "Replace all blocks in the selection with another", flags = "f", min = 1, @@ -528,7 +528,7 @@ public class RegionCommands extends MethodCommands { desc = "Move the contents of the selection", help = "Moves the contents of the selection.\n" + - " -s flag shifts the selection to the target location.\n" + + "The -s flag shifts the selection to the target location.\n" + " -b also copies biomes\n" + " -e ignores entities\n" + " -a ignores air\n" + @@ -622,7 +622,7 @@ public class RegionCommands extends MethodCommands { if (moveSelection) { try { final BlockVector3 size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1); - BlockVector3 shiftVector = BlockVector3.at(direction.getX() * size.getX() * count, direction.getY() * size.getY() * count, direction.getZ() * size.getZ() * count); + final BlockVector3 shiftVector = BlockVector3.at(direction.getX() * size.getX() * count, direction.getY() * size.getY() * count, direction.getZ() * size.getZ() * count); region.shift(shiftVector); session.getRegionSelector(player.getWorld()).learnChanges(); @@ -795,4 +795,4 @@ public class RegionCommands extends MethodCommands { } -} \ No newline at end of file +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java index 6b27ccf1a..5dacbb5a5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java @@ -49,12 +49,14 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader; import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.util.command.binding.Switch; import com.sk89q.worldedit.util.command.parametric.Optional; +import com.sk89q.worldedit.util.io.Closer; import com.sk89q.worldedit.util.io.file.FilenameException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java index ad87b11ec..9efed048f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java @@ -33,6 +33,7 @@ import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.world.snapshot.InvalidSnapshotException; import com.sk89q.worldedit.world.snapshot.Snapshot; import com.sk89q.worldedit.world.storage.MissingWorldException; + import java.io.File; import java.io.IOException; import java.text.DateFormat; @@ -105,7 +106,7 @@ public class SnapshotCommands { } @Command( - aliases = {"use"}, + aliases = { "use" }, usage = "", desc = "Choose a snapshot to use", min = 1, @@ -148,7 +149,7 @@ public class SnapshotCommands { } @Command( - aliases = {"sel"}, + aliases = { "sel" }, usage = "", desc = "Choose the snapshot based on the list id", min = 1, @@ -195,7 +196,7 @@ public class SnapshotCommands { } @Command( - aliases = {"before"}, + aliases = { "before" }, usage = "", desc = "Choose the nearest snapshot before a date", min = 1, @@ -234,7 +235,7 @@ public class SnapshotCommands { } @Command( - aliases = {"after"}, + aliases = { "after" }, usage = "", desc = "Choose the nearest snapshot after a date", min = 1, @@ -259,7 +260,8 @@ public class SnapshotCommands { Snapshot snapshot = config.snapshotRepo.getSnapshotAfter(date, player.getWorld().getName()); if (snapshot == null) { dateFormat.setTimeZone(session.getTimeZone()); - player.printError("Couldn't find a snapshot after " + dateFormat.format(date.getTime()) + "."); + player.printError("Couldn't find a snapshot after " + + dateFormat.format(date.getTime()) + "."); } else { session.setSnapshot(snapshot); BBC.SNAPSHOT_SET.send(player, snapshot.getName()); @@ -269,4 +271,5 @@ public class SnapshotCommands { } } } + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java index 1224926fd..5b860d579 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java @@ -37,10 +37,10 @@ import com.sk89q.worldedit.world.snapshot.Snapshot; import com.sk89q.worldedit.world.snapshot.SnapshotRestore; import com.sk89q.worldedit.world.storage.ChunkStore; import com.sk89q.worldedit.world.storage.MissingWorldException; + import java.io.File; import java.io.IOException; - import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION; @Command(aliases = {}, desc = "[More Info](http://wiki.sk89q.com/wiki/WorldEdit/Snapshots)") @@ -53,7 +53,7 @@ public class SnapshotUtilCommands { } @Command( - aliases = {"restore", "/restore"}, + aliases = { "restore", "/restore" }, usage = "[snapshot]", desc = "Restore the selection from a snapshot", min = 0, diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java index e1425c3e1..3cb322eea 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java @@ -81,17 +81,21 @@ public class SelectionCommand extends SimpleCommand { if (!testPermission(locals)) { throw new CommandPermissionsException(); } + Contextual operationFactory = delegate.call(args, locals); + Actor actor = locals.get(Actor.class); if (actor instanceof Player) { try { Player player = (Player) actor; LocalSession session = WorldEdit.getInstance().getSessionManager().get(player); Region selection = session.getSelection(player.getWorld()); + EditSession editSession = session.createEditSession(player); editSession.enableStandardMode(); locals.put(EditSession.class, editSession); session.tellVersion(player); + EditContext editContext = new EditContext(); editContext.setDestination(locals.get(EditSession.class)); editContext.setRegion(selection); @@ -193,4 +197,4 @@ public class SelectionCommand extends SimpleCommand { -} \ No newline at end of file +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java index 004dc5bb2..bf6994c11 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java @@ -19,11 +19,6 @@ package com.sk89q.worldedit.command.tool; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - import com.google.common.collect.Lists; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalConfiguration; @@ -38,6 +33,11 @@ import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockState; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + /** * A mode that cycles the data values of supported blocks. */ @@ -47,7 +47,7 @@ public class BlockDataCyler implements DoubleActionBlockTool { public boolean canUse(Actor player) { return player.hasPermission("worldedit.tool.data-cycler"); } - + private Map> selectedProperties = new HashMap<>(); private boolean handleCycle(Platform server, LocalConfiguration config, @@ -104,7 +104,8 @@ public class BlockDataCyler implements DoubleActionBlockTool { player.print("Now cycling " + currentProperty.getName()); } } - return true; + + return true; } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java index ba2ef06f8..973e10731 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java @@ -19,9 +19,6 @@ package com.sk89q.worldedit.command.tool; -import com.sk89q.worldedit.function.pattern.Pattern; -import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; @@ -31,7 +28,11 @@ import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.function.pattern.BlockPattern; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockType; /** */ diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/HollowCylinderBrush.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/HollowCylinderBrush.java index ed7b23d55..dbf959e1b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/HollowCylinderBrush.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/HollowCylinderBrush.java @@ -21,7 +21,6 @@ package com.sk89q.worldedit.command.tool.brush; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; -import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/HollowSphereBrush.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/HollowSphereBrush.java index e76173174..0e89b3c16 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/HollowSphereBrush.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/HollowSphereBrush.java @@ -21,7 +21,6 @@ package com.sk89q.worldedit.command.tool.brush; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; -import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java index f89b628e2..32f1b533a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java @@ -60,6 +60,8 @@ import com.sk89q.worldedit.util.command.fluent.CommandGraph; import com.sk89q.worldedit.util.command.fluent.DispatcherNode; import com.sk89q.worldedit.util.command.parametric.*; 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 com.sk89q.worldedit.world.World; @@ -74,7 +76,6 @@ import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Supplier; import java.util.logging.FileHandler; import java.util.logging.Level; import java.util.regex.Pattern; @@ -84,7 +85,7 @@ import static com.sk89q.worldedit.util.command.composition.LegacyCommandAdapter. /** * Handles the registration and invocation of commands. - *

+ * *

This class is primarily for internal usage.

*/ public final class CommandManager { @@ -129,6 +130,7 @@ public final class CommandManager { commandLog.addHandler(dynamicHandler); dynamicHandler.setFormatter(new LogFormat()); + // Set up the commands manager builder = new ParametricBuilder(); builder.setAuthorizer(new ActorAuthorizer()); builder.setDefaultCompleter(new UserCommandCompleter(platformManager)); @@ -430,7 +432,8 @@ public final class CommandManager { return handleCommandTask(task, locals, null, null, null, null); } - private Object handleCommandTask(ThrowableSupplier task, CommandLocals locals, @Nullable Actor actor, @Nullable LocalSession session, @Nullable Set failedPermissions, @Nullable FawePlayer fp) { + private Object handleCommandTask(ThrowableSupplier task, CommandLocals locals, @Nullable + Actor actor, @Nullable LocalSession session, @Nullable Set failedPermissions, @Nullable FawePlayer fp) { Request.reset(); if (actor == null) actor = locals.get(Actor.class); if (session == null) session = locals.get(LocalSession.class); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java index a00eae891..6cd413f16 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java @@ -64,6 +64,7 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Manages registered {@link Platform}s for WorldEdit. Platforms are * implementations of WorldEdit. + * *

This class is thread-safe.

*/ public class PlatformManager { @@ -111,7 +112,7 @@ public class PlatformManager { if (!firstSeenVersion.equals(platform.getVersion())) { logger.warn("Multiple ports of WorldEdit are installed but they report different versions ({0} and {1}). " + "If these two versions are truly different, then you may run into unexpected crashes and errors.", - new Object[]{firstSeenVersion, platform.getVersion()}); + new Object[]{ firstSeenVersion, platform.getVersion() }); } } else { firstSeenVersion = platform.getVersion(); @@ -120,7 +121,7 @@ public class PlatformManager { /** * Unregister a platform from WorldEdit. - *

+ * *

If the platform has been chosen for any capabilities, then a new * platform will be found.

* @@ -223,7 +224,7 @@ public class PlatformManager { /** * Get a list of loaded platforms. - *

+ * *

The returned list is a copy of the original and is mutable.

* * @return a list of platforms @@ -277,7 +278,7 @@ public class PlatformManager { /** * Get the current configuration. - *

+ * *

If no platform has been registered yet, then a default configuration * will be returned.

* @@ -305,67 +306,66 @@ public class PlatformManager { public void handleBlockInteract(BlockInteractEvent event) { // Create a proxy actor with a potentially different world for // making changes to the world - Request.reset(); - final Actor actor = createProxyActor(event.getCause()); + Actor actor = createProxyActor(event.getCause()); + + Location location = event.getLocation(); + try { - final Location location = event.getLocation(); - final BlockVector3 vector = location.toBlockPoint(); + Vector3 vector = location.toVector(); // At this time, only handle interaction from players if (actor instanceof Player) { - final LocalSession session = worldEdit.getSessionManager().get(actor); - Player playerActor = (Player) actor; + Player player = (Player) actor; + LocalSession session = worldEdit.getSessionManager().get(actor); + Request.reset(); VirtualWorld virtual = session.getVirtualWorld(); if (virtual != null) { - virtual.handleBlockInteract(playerActor, vector, event); + virtual.handleBlockInteract(player, vector.toBlockPoint(), event); if (event.isCancelled()) return; } if (event.getType() == Interaction.HIT) { - if (session.isToolControlEnabled() && playerActor.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().wandItem)) { - FawePlayer fp = FawePlayer.wrap(playerActor); + if (session.isToolControlEnabled() && player.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().wandItem)) { if (!actor.hasPermission("worldedit.selection.pos")) { return; } - final RegionSelector selector = session.getRegionSelector(playerActor.getWorld()); - final Player player = new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), ((Player) actor).getLocation()); - fp.runAction(new Runnable() { - @Override - public void run() { - if (selector.selectPrimary(vector, ActorSelectorLimits.forActor(player))) { - selector.explainPrimarySelection(actor, session, vector); - } + FawePlayer fp = FawePlayer.wrap(player); + RegionSelector selector = session.getRegionSelector(player.getWorld()); + final Player maskedPlayerWrapper = + new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), + ((Player) actor).getLocation()); + BlockVector3 blockPoint = vector.toBlockPoint(); + fp.runAction(() -> { + if (selector.selectPrimary(blockPoint, + ActorSelectorLimits.forActor(maskedPlayerWrapper))) { + selector + .explainPrimarySelection(actor, session, blockPoint); } }, false, true); event.setCancelled(true); return; } - if (session.hasSuperPickAxe() && playerActor.isHoldingPickAxe()) { + if (session.hasSuperPickAxe() && player.isHoldingPickAxe()) { final BlockTool superPickaxe = session.getSuperPickaxe(); - if (superPickaxe != null && superPickaxe.canUse(playerActor)) { - FawePlayer fp = FawePlayer.wrap(playerActor); - final Player player = new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), ((Player) actor).getLocation()); - fp.runAction(new Runnable() { - @Override - public void run() { - reset(superPickaxe).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session, location); - } - }, false, true); + if (superPickaxe != null && superPickaxe.canUse(player)) { + FawePlayer fp = FawePlayer.wrap(player); + final Player maskedPlayerWrapper = new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), ((Player) actor).getLocation()); + fp.runAction(() -> reset(superPickaxe).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), maskedPlayerWrapper, session, location), false, true); event.setCancelled(true); return; } } - final Tool tool = session.getTool(playerActor); + final Tool tool = session.getTool(player); if (tool != null && tool instanceof DoubleActionBlockTool) { - if (tool.canUse(playerActor)) { - FawePlayer fp = FawePlayer.wrap(playerActor); - final Player player = new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), ((Player) actor).getLocation()); + if (tool.canUse(player)) { + FawePlayer fp = FawePlayer.wrap(player); + final Player maskedPlayerWrapper = new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), ((Player) actor).getLocation()); fp.runAction(new Runnable() { @Override public void run() { - reset(((DoubleActionBlockTool) tool)).actSecondary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session, location); + reset(((DoubleActionBlockTool) tool)).actSecondary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), maskedPlayerWrapper, session, location); } }, false, true); event.setCancelled(true); @@ -373,20 +373,22 @@ public class PlatformManager { } } } else if (event.getType() == Interaction.OPEN) { - if (session.isToolControlEnabled() && playerActor.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().wandItem)) { - FawePlayer fp = FawePlayer.wrap(playerActor); + if (session.isToolControlEnabled() && player.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().wandItem)) { if (!actor.hasPermission("worldedit.selection.pos")) { return; } + FawePlayer fp = FawePlayer.wrap(player); if (fp.checkAction()) { - final RegionSelector selector = session.getRegionSelector(playerActor.getWorld()); - final Player player = new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), ((Player) actor).getLocation()); - fp.runAction(new Runnable() { - @Override - public void run() { - if (selector.selectSecondary(vector, ActorSelectorLimits.forActor(player))) { - selector.explainSecondarySelection(actor, session, vector); - } + RegionSelector selector = session.getRegionSelector(player.getWorld()); + Player maskedPlayerWrapper = new LocationMaskedPlayerWrapper( + PlayerWrapper.wrap((Player) actor), + ((Player) actor).getLocation()); + BlockVector3 blockPoint = vector.toBlockPoint(); + fp.runAction(() -> { + if (selector.selectSecondary(blockPoint, + ActorSelectorLimits.forActor(maskedPlayerWrapper))) { + selector.explainSecondarySelection(actor, session, + blockPoint); } }, false, true); } @@ -394,20 +396,17 @@ public class PlatformManager { return; } - final Tool tool = session.getTool(playerActor); + final Tool tool = session.getTool(player); if (tool != null && tool instanceof BlockTool) { - if (tool.canUse(playerActor)) { - FawePlayer fp = FawePlayer.wrap(playerActor); + if (tool.canUse(player)) { + FawePlayer fp = FawePlayer.wrap(player); if (fp.checkAction()) { - final Player player = new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), ((Player) actor).getLocation()); - fp.runAction(new Runnable() { - @Override - public void run() { - if (tool instanceof BrushTool) { - ((BlockTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session, location); - } else { - reset((BlockTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session, location); - } + final Player maskedPlayerWrapper = new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), ((Player) actor).getLocation()); + fp.runAction(() -> { + if (tool instanceof BrushTool) { + ((BlockTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), maskedPlayerWrapper, session, location); + } else { + reset((BlockTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), maskedPlayerWrapper, session, location); } }, false, true); event.setCancelled(true); @@ -435,7 +434,6 @@ public class PlatformManager { } } - @SuppressWarnings("deprecation") @Subscribe public void handlePlayerInput(PlayerInputEvent event) { // Create a proxy actor with a potentially different world for @@ -453,11 +451,7 @@ public class PlatformManager { try { switch (event.getInputType()) { case PRIMARY: { - if (player.getItemInHand(HandSide.MAIN_HAND).getType().equals(getConfiguration().navigationWand)) { - if (getConfiguration().navigationWandMaxDistance <= 0) { - return; - } - + if (getConfiguration().navigationWandMaxDistance > 0 && player.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().navigationWand)) { if (!player.hasPermission("worldedit.navigation.jumpto.tool")) { return; } @@ -473,16 +467,11 @@ public class PlatformManager { return; } - final Tool tool = session.getTool(player); - if (tool != null && tool instanceof DoubleActionTraceTool) { + Tool tool = session.getTool(player); + if (tool instanceof DoubleActionTraceTool) { if (tool.canUse(player)) { FawePlayer fp = FawePlayer.wrap(player); - fp.runAsyncIfFree(new Runnable() { - @Override - public void run() { - reset((DoubleActionTraceTool) tool).actSecondary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session); - } - }); + fp.runAsyncIfFree(() -> reset((DoubleActionTraceTool) tool).actSecondary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session)); event.setCancelled(true); return; } @@ -491,11 +480,7 @@ public class PlatformManager { } case SECONDARY: { - if (player.getItemInHand(HandSide.MAIN_HAND).getType().equals(getConfiguration().navigationWand)) { - if (getConfiguration().navigationWandMaxDistance <= 0) { - return; - } - + if (getConfiguration().navigationWandMaxDistance > 0 && player.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().navigationWand)) { if (!player.hasPermission("worldedit.navigation.thru.tool")) { return; } @@ -508,16 +493,11 @@ public class PlatformManager { return; } - final Tool tool = session.getTool(player); - if (tool != null && tool instanceof TraceTool) { + Tool tool = session.getTool(player); + if (tool instanceof TraceTool) { if (tool.canUse(player)) { FawePlayer fp = FawePlayer.wrap(player); - fp.runAction(new Runnable() { - @Override - public void run() { - reset((TraceTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session); - } - }, false, true); + fp.runAction(() -> reset((TraceTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session), false, true); event.setCancelled(true); return; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormats.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormats.java index ad98f88ad..d3b23efda 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormats.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/ClipboardFormats.java @@ -313,4 +313,4 @@ public class ClipboardFormats { throw new RuntimeException(e); } } -} \ No newline at end of file +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SchematicReader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SchematicReader.java index 489ce802f..e4ac175f9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SchematicReader.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SchematicReader.java @@ -26,11 +26,13 @@ import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.extent.clipboard.Clipboard; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.IOException; import java.io.InputStream; import java.util.Map; import java.util.UUID; -import java.util.logging.Logger; import javax.annotation.Nullable; @@ -41,7 +43,6 @@ import static com.google.common.base.Preconditions.checkNotNull; */ public class SchematicReader implements ClipboardReader { - private static final Logger log = Logger.getLogger(SchematicReader.class.getCanonicalName()); private NBTInputStream inputStream; private InputStream rootStream; @@ -109,4 +110,4 @@ public class SchematicReader implements ClipboardReader { public void close() throws IOException { inputStream.close(); } -} \ No newline at end of file +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicReader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicReader.java index c25b8fde8..e759af00a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicReader.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicReader.java @@ -254,4 +254,4 @@ public class SpongeSchematicReader extends NBTSchematicReader { public void close() throws IOException { inputStream.close(); } -} \ No newline at end of file +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/BlockPattern.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/BlockPattern.java index 7a41cc062..8f0560364 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/BlockPattern.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/BlockPattern.java @@ -27,8 +27,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder; /** * A pattern that returns the same {@link BaseBlock} each time. */ -@Deprecated -public class BlockPattern implements Pattern { +public class BlockPattern extends AbstractPattern { private BaseBlock block; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java index 367efdb69..0d6447ceb 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java @@ -641,4 +641,4 @@ public class BlockVector3 { return "(" + x + ", " + y + ", " + z + ")"; } -} \ No newline at end of file +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/Vector3.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/Vector3.java index 275dff135..e5157e939 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/Vector3.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/Vector3.java @@ -40,6 +40,21 @@ public class Vector3 { public static final Vector3 ONE = new Vector3(1, 1, 1); public static Vector3 at(double x, double y, double z) { + // switch for efficiency on typical cases + // in MC y is rarely 0/1 on selections + int yTrunc = (int) y; + switch (yTrunc) { + case 0: + if (x == 0 && y == 0 && z == 0) { + return ZERO; + } + break; + case 1: + if (x == 1 && y == 1 && z == 1) { + return ONE; + } + break; + } return new Vector3(x, y, z); } @@ -632,15 +647,16 @@ public class Vector3 { @Override public int hashCode() { - return ((int) getX() ^ ((int) getZ() << 16)) ^ ((int) getY() << 30); + int hash = 17; + hash = 31 * hash + Double.hashCode(x); + hash = 31 * hash + Double.hashCode(y); + hash = 31 * hash + Double.hashCode(z); + return hash; } @Override public String toString() { - String x = (getX() == getBlockX() ? "" + getBlockX() : "" + getX()); - String y = (getY() == getBlockY() ? "" + getBlockY() : "" + getY()); - String z = (getZ() == getBlockZ() ? "" + getBlockZ() : "" + getZ()); return "(" + x + ", " + y + ", " + z + ")"; } -} \ No newline at end of file +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/session/SessionManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/session/SessionManager.java index 4e5edd5f2..229ba0375 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/session/SessionManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/session/SessionManager.java @@ -47,7 +47,8 @@ import java.util.Map; import java.util.Timer; import java.util.TimerTask; import java.util.UUID; -import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; + import static com.google.common.base.Preconditions.checkNotNull; @@ -340,4 +341,4 @@ public class SessionManager { } } -} \ No newline at end of file +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/PropertiesConfiguration.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/PropertiesConfiguration.java index 12513b97d..b4620b293 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/PropertiesConfiguration.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/PropertiesConfiguration.java @@ -25,6 +25,8 @@ import com.sk89q.util.StringUtil; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.util.report.Unreported; +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; import org.slf4j.Logger; @@ -78,6 +80,8 @@ public class PropertiesConfiguration extends LocalConfiguration { profile = getBool("profile", profile); traceUnflushedSessions = getBool("trace-unflushed-sessions", traceUnflushedSessions); disallowedBlocks = getStringSet("disallowed-blocks", getDefaultDisallowedBlocks()); + allowedDataCycleBlocks = + new HashSet<>(getStringSet("limits.allowed-data-cycle-blocks", null)); defaultChangeLimit = getInt("default-max-changed-blocks", defaultChangeLimit); maxChangeLimit = getInt("max-changed-blocks", maxChangeLimit); defaultMaxPolygonalPoints = getInt("default-max-polygon-points", defaultMaxPolygonalPoints); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/logging/WorldEditPrefixHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/logging/WorldEditPrefixHandler.java new file mode 100644 index 000000000..6922987c4 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/logging/WorldEditPrefixHandler.java @@ -0,0 +1,60 @@ +/* + * 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.util.logging; + +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +/** + * Adds a WorldEdit prefix to WorldEdit's logger messages using a handler. + */ +public final class WorldEditPrefixHandler extends Handler { + + private WorldEditPrefixHandler() { + } + + @Override + public void publish(LogRecord record) { + String message = record.getMessage(); + if (!message.startsWith("WorldEdit: ") && !message.startsWith("[WorldEdit] ")) { + record.setMessage("[WorldEdit] " + message); + } + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + + /** + * Add the handler to the following logger name. + * + * @param name the logger name + */ + public static void register(String name) { + //todo fix this + //Logger.getLogger(name).addHandler(new WorldEditPrefixHandler()); + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java index 47042f6a6..856fdf98e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java @@ -904,8 +904,8 @@ public final class BlockTypes { try { BlockStateHolder block = LegacyMapper.getInstance().getBlockFromLegacy(input); if (block != null) return block.getBlockType(); - } catch (NumberFormatException e) { - } catch (IndexOutOfBoundsException e) {} + } catch (NumberFormatException | IndexOutOfBoundsException e) { + } throw new SuggestInputParseException("Does not match a valid block type: " + inputLower, inputLower, () -> Stream.of(BlockTypes.values) .filter(b -> b.getId().contains(inputLower)) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockData.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockData.java index e7c83ca7c..f7b2d5837 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockData.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockData.java @@ -147,4 +147,4 @@ public class BundledBlockData { public SimpleBlockMaterial material = new SimpleBlockMaterial(); } -} \ No newline at end of file +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/LegacyMapper.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/LegacyMapper.java index 80b3a846a..76b141465 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/LegacyMapper.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/LegacyMapper.java @@ -40,8 +40,6 @@ import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemTypes; -import com.sk89q.worldedit.extension.input.ParserContext; -import com.sk89q.worldedit.util.gson.VectorAdapter; import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,6 +48,7 @@ import javax.annotation.Nullable; import java.io.IOException; import java.net.URL; import java.nio.charset.Charset; +import java.util.Arrays; import java.util.Map; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/weather/WeatherTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/weather/WeatherTypes.java index d7450610d..7d8cfc4b3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/weather/WeatherTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/weather/WeatherTypes.java @@ -37,6 +37,7 @@ public class WeatherTypes { private WeatherTypes() { } + public static @Nullable WeatherType get(final String id) { return WeatherType.REGISTRY.get(id); } diff --git a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/legacy.json b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/legacy.json index 06c20e4e4..10907d78e 100644 --- a/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/legacy.json +++ b/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/legacy.json @@ -2393,4 +2393,4 @@ "2266:0": "minecraft:music_disc_11", "2267:0": "minecraft:music_disc_wait" } -} \ No newline at end of file +} diff --git a/worldedit-core/src/test/java/com/sk89q/minecraft/util/commands/CommandContextTest.java b/worldedit-core/src/test/java/com/sk89q/minecraft/util/commands/CommandContextTest.java index a542ebe30..555c83889 100644 --- a/worldedit-core/src/test/java/com/sk89q/minecraft/util/commands/CommandContextTest.java +++ b/worldedit-core/src/test/java/com/sk89q/minecraft/util/commands/CommandContextTest.java @@ -33,8 +33,6 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.junit.Assert.*; - public class CommandContextTest { private static final Logger log = LoggerFactory.getLogger(CommandContextTest.class);