diff --git a/bukkit/build.gradle b/bukkit/build.gradle index 9e65c028..2c38d2ee 100644 --- a/bukkit/build.gradle +++ b/bukkit/build.gradle @@ -2,7 +2,7 @@ repositories { flatDir {dirs 'lib'} } dependencies { - compile 'com.destroystokyo.paper:paper-api:1.11.2-R0.1-SNAPSHOT' + compile 'com.destroystokyo.paper:paper-api:1.12-R0.1-SNAPSHOT' compile project(':core') compile 'org.bukkit.craftbukkitv1_10:craftbukkitv1_10:1.10' compile 'org.bukkit.craftbukkitv1_11:Craftbukkit:1.11' diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitMain.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitMain.java index 5f99c2e7..9cd95d3a 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitMain.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitMain.java @@ -82,7 +82,11 @@ public class BukkitMain extends JavaPlugin { } } - private enum Version { + public Version getVersion() { + return version; + } + + public enum Version { v1_7_R4, v1_8_R3, v1_9_R2, diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java index 245e894c..8e3f4353 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java @@ -22,6 +22,7 @@ import com.boydti.fawe.regions.FaweMaskManager; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.ReflectionUtils; import com.boydti.fawe.util.TaskManager; +import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.bukkit.EditSessionBlockChangeDelegate; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.world.World; @@ -68,7 +69,8 @@ public class FaweBukkit implements IFawe, Listener { try { Fawe.set(this); setupInjector(); - com.sk89q.worldedit.bukkit.BukkitPlayer.inject(); + com.sk89q.worldedit.bukkit.BukkitPlayer.inject(); // Fixes + BukkitWorld.inject(); // Fixes try { new BrushListener(plugin); } catch (Throwable e) { diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java index 1105772c..3d3c01c3 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java @@ -59,6 +59,11 @@ public abstract class BukkitQueue_0 extends NMSMa } } + public static BukkitImplAdapter getAdapter() { + if (adapter == null) setupAdapter(null); + return adapter; + } + @Override public File getSaveFolder() { return new File(Bukkit.getWorldContainer(), getWorldName() + File.separator + "region"); diff --git a/bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java new file mode 100644 index 00000000..3c62b670 --- /dev/null +++ b/bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -0,0 +1,552 @@ +/* + * 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.bukkit; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.bukkit.FaweBukkit; +import com.boydti.fawe.bukkit.v0.BukkitQueue_0; +import com.sk89q.worldedit.BlockVector2D; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.LocalWorld; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.Vector2D; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.blocks.BaseItemStack; +import com.sk89q.worldedit.blocks.LazyBlock; +import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; +import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.TreeGenerator; +import com.sk89q.worldedit.world.biome.BaseBiome; +import com.sk89q.worldedit.world.registry.WorldData; +import java.lang.ref.WeakReference; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; +import org.bukkit.Bukkit; +import org.bukkit.Effect; +import org.bukkit.Material; +import org.bukkit.TreeType; +import org.bukkit.World; +import org.bukkit.block.Biome; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.block.Chest; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.DoubleChestInventory; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + + +import static com.google.common.base.Preconditions.checkNotNull; + +public class BukkitWorld extends LocalWorld { + + private static final Logger logger = WorldEdit.logger; + + private static final Map effects = new HashMap(); + static { + for (Effect effect : Effect.values()) { + effects.put(effect.getId(), effect); + } + } + + private WeakReference worldRef; + private final String worldNameRef; + + /** + * Construct the object. + * + * @param world the world + */ + @SuppressWarnings("unchecked") + public BukkitWorld(World world) { + this.worldRef = new WeakReference(world); + this.worldNameRef = world.getName(); + } + + @Override + public List getEntities(Region region) { + World world = getWorld(); + + List ents = world.getEntities(); + List entities = new ArrayList(); + for (Entity ent : ents) { + if (region.contains(BukkitUtil.toVector(ent.getLocation()))) { + addEntities(ent, entities); + } + } + return entities; + } + + @Override + public List getEntities() { + List list = new ArrayList(); + for (Entity entity : getWorld().getEntities()) { + addEntities(entity, list); + } + return list; + } + + private void addEntities(Entity ent, Collection ents) { + ents.add(adapt(ent)); + switch (Fawe.imp().getPlugin().getVersion()) { + case v1_7_R4: + case v1_8_R3: + case v1_9_R2: + case v1_10_R1: + case v1_11_R1: + return; + default: + if (ent instanceof Player) { + final Player plr = (Player) ent; + com.sk89q.worldedit.entity.Entity left = adapt(((Player) ent).getShoulderEntityLeft()); + com.sk89q.worldedit.entity.Entity right = adapt(((Player) ent).getShoulderEntityRight()); + if (left != null) { + ents.add(new DelegateEntity(left) { + @Override + public boolean remove() { + plr.setShoulderEntityLeft(null); + return true; + } + }); + } + if (right != null) { + ents.add(new DelegateEntity(right) { + @Override + public boolean remove() { + plr.setShoulderEntityRight(null); + return true; + } + }); + } + } + } + }; + + @Nullable + @Override + public com.sk89q.worldedit.entity.Entity createEntity(com.sk89q.worldedit.util.Location location, BaseEntity entity) { + BukkitImplAdapter adapter = BukkitQueue_0.getAdapter(); + if (adapter != null) { + Entity createdEntity = adapter.createEntity(adapt(getWorld(), location), entity); + if (createdEntity != null) { + return new BukkitEntity(createdEntity); + } else { + return null; + } + } else { + return null; + } + } + + private static BukkitImplAdapter getAdapter() { + return BukkitQueue_0.getAdapter(); + } + + private static com.sk89q.worldedit.entity.Entity adapt(Entity ent) { + try { + if (ent == null) return null; + return (com.sk89q.worldedit.entity.Entity) ADAPT_ENTITY.invoke(null, ent); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + private static org.bukkit.Location adapt(org.bukkit.World world, Vector position) { + checkNotNull(world); + checkNotNull(position); + return new org.bukkit.Location( + world, + position.getX(), position.getY(), position.getZ()); + } + + private static org.bukkit.Location adapt(org.bukkit.World world, Location location) { + checkNotNull(world); + checkNotNull(location); + return new org.bukkit.Location( + world, + location.getX(), location.getY(), location.getZ(), + location.getYaw(), + location.getPitch()); + } + + private static Method ADAPT_ENTITY; + static { + try { + Class clazz = Class.forName("com.sk89q.worldedit.bukkit.BukkitAdapter"); + ADAPT_ENTITY = clazz.getDeclaredMethod("adapt", Entity.class); + ADAPT_ENTITY.setAccessible(true); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + /** + * Get the world handle. + * + * @return the world + */ + public World getWorld() { + World tmp = worldRef.get(); + if (tmp == null) { + tmp = Bukkit.getWorld(worldNameRef); + if (tmp != null) worldRef = new WeakReference(tmp); + } + return checkNotNull(tmp, "The world was unloaded and the reference is unavailable"); + } + + @Override + public String getName() { + return getWorld().getName(); + } + + @Override + public int getBlockLightLevel(Vector pt) { + return getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).getLightLevel(); + } + + @Override + public boolean regenerate(Region region, EditSession editSession) { + BaseBlock[] history = new BaseBlock[16 * 16 * (getMaxY() + 1)]; + + for (Vector2D chunk : region.getChunks()) { + Vector min = new Vector(chunk.getBlockX() * 16, 0, chunk.getBlockZ() * 16); + + // First save all the blocks inside + for (int x = 0; x < 16; ++x) { + for (int y = 0; y < (getMaxY() + 1); ++y) { + for (int z = 0; z < 16; ++z) { + Vector pt = min.add(x, y, z); + int index = y * 16 * 16 + z * 16 + x; + history[index] = editSession.getBlock(pt); + } + } + } + + try { + getWorld().regenerateChunk(chunk.getBlockX(), chunk.getBlockZ()); + } catch (Throwable t) { + logger.log(Level.WARNING, "Chunk generation via Bukkit raised an error", t); + } + + // Then restore + for (int x = 0; x < 16; ++x) { + for (int y = 0; y < (getMaxY() + 1); ++y) { + for (int z = 0; z < 16; ++z) { + Vector pt = min.add(x, y, z); + int index = y * 16 * 16 + z * 16 + x; + + // We have to restore the block if it was outside + if (!region.contains(pt)) { + editSession.smartSetBlock(pt, history[index]); + } else { // Otherwise fool with history + editSession.rememberChange(pt, history[index], + editSession.rawGetBlock(pt)); + } + } + } + } + } + + return true; + } + + /** + * Gets the single block inventory for a potentially double chest. + * Handles people who have an old version of Bukkit. + * This should be replaced with {@link org.bukkit.block.Chest#getBlockInventory()} + * in a few months (now = March 2012) // note from future dev - lol + * + * @param chest The chest to get a single block inventory for + * @return The chest's inventory + */ + private Inventory getBlockInventory(Chest chest) { + try { + return chest.getBlockInventory(); + } catch (Throwable t) { + if (chest.getInventory() instanceof DoubleChestInventory) { + DoubleChestInventory inven = (DoubleChestInventory) chest.getInventory(); + if (inven.getLeftSide().getHolder().equals(chest)) { + return inven.getLeftSide(); + } else if (inven.getRightSide().getHolder().equals(chest)) { + return inven.getRightSide(); + } else { + return inven; + } + } else { + return chest.getInventory(); + } + } + } + + @Override + public boolean clearContainerBlockContents(Vector pt) { + Block block = getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + if (block == null) { + return false; + } + BlockState state = block.getState(); + if (!(state instanceof org.bukkit.inventory.InventoryHolder)) { + return false; + } + + org.bukkit.inventory.InventoryHolder chest = (org.bukkit.inventory.InventoryHolder) state; + Inventory inven = chest.getInventory(); + if (chest instanceof Chest) { + inven = getBlockInventory((Chest) chest); + } + inven.clear(); + return true; + } + + @Override + @Deprecated + public boolean generateTree(EditSession editSession, Vector pt) { + return generateTree(TreeGenerator.TreeType.TREE, editSession, pt); + } + + @Override + @Deprecated + public boolean generateBigTree(EditSession editSession, Vector pt) { + return generateTree(TreeGenerator.TreeType.BIG_TREE, editSession, pt); + } + + @Override + @Deprecated + public boolean generateBirchTree(EditSession editSession, Vector pt) { + return generateTree(TreeGenerator.TreeType.BIRCH, editSession, pt); + } + + @Override + @Deprecated + public boolean generateRedwoodTree(EditSession editSession, Vector pt) { + return generateTree(TreeGenerator.TreeType.REDWOOD, editSession, pt); + } + + @Override + @Deprecated + public boolean generateTallRedwoodTree(EditSession editSession, Vector pt) { + return generateTree(TreeGenerator.TreeType.TALL_REDWOOD, editSession, pt); + } + + /** + * An EnumMap that stores which WorldEdit TreeTypes apply to which Bukkit TreeTypes + */ + private static final EnumMap treeTypeMapping = + new EnumMap(TreeGenerator.TreeType.class); + + static { + for (TreeGenerator.TreeType type : TreeGenerator.TreeType.values()) { + try { + TreeType bukkitType = TreeType.valueOf(type.name()); + treeTypeMapping.put(type, bukkitType); + } catch (IllegalArgumentException e) { + // Unhandled TreeType + } + } + // Other mappings for WE-specific values + treeTypeMapping.put(TreeGenerator.TreeType.SHORT_JUNGLE, TreeType.SMALL_JUNGLE); + treeTypeMapping.put(TreeGenerator.TreeType.RANDOM, TreeType.BROWN_MUSHROOM); + treeTypeMapping.put(TreeGenerator.TreeType.RANDOM_REDWOOD, TreeType.REDWOOD); + treeTypeMapping.put(TreeGenerator.TreeType.PINE, TreeType.REDWOOD); + treeTypeMapping.put(TreeGenerator.TreeType.RANDOM_BIRCH, TreeType.BIRCH); + treeTypeMapping.put(TreeGenerator.TreeType.RANDOM_JUNGLE, TreeType.JUNGLE); + treeTypeMapping.put(TreeGenerator.TreeType.RANDOM_MUSHROOM, TreeType.BROWN_MUSHROOM); + for (TreeGenerator.TreeType type : TreeGenerator.TreeType.values()) { + if (treeTypeMapping.get(type) == null) { + WorldEdit.logger.severe("No TreeType mapping for TreeGenerator.TreeType." + type); + } + } + } + + public static TreeType toBukkitTreeType(TreeGenerator.TreeType type) { + return treeTypeMapping.get(type); + } + + @Override + public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, Vector pt) { + World world = getWorld(); + TreeType bukkitType = toBukkitTreeType(type); + return type != null && world.generateTree(BukkitUtil.toLocation(world, pt), bukkitType, + new EditSessionBlockChangeDelegate(editSession)); + } + + @Override + public void dropItem(Vector pt, BaseItemStack item) { + World world = getWorld(); + ItemStack bukkitItem = new ItemStack(item.getType(), item.getAmount(), + item.getData()); + world.dropItemNaturally(BukkitUtil.toLocation(world, pt), bukkitItem); + } + + @SuppressWarnings("deprecation") + @Override + public boolean isValidBlockType(int type) { + return Material.getMaterial(type) != null && Material.getMaterial(type).isBlock(); + } + + @Override + public void checkLoadedChunk(Vector pt) { + World world = getWorld(); + + if (!world.isChunkLoaded(pt.getBlockX() >> 4, pt.getBlockZ() >> 4)) { + world.loadChunk(pt.getBlockX() >> 4, pt.getBlockZ() >> 4); + } + } + + @Override + public boolean equals(Object other) { + if (other == null) { + return false; + } else if ((other instanceof BukkitWorld)) { + return ((BukkitWorld) other).getWorld().equals(getWorld()); + } else if (other instanceof com.sk89q.worldedit.world.World) { + return ((com.sk89q.worldedit.world.World) other).getName().equals(getName()); + } else { + return false; + } + } + + @Override + public int hashCode() { + return getWorld().hashCode(); + } + + @Override + public int getMaxY() { + return getWorld().getMaxHeight() - 1; + } + + @Override + public void fixAfterFastMode(Iterable chunks) { + World world = getWorld(); + for (BlockVector2D chunkPos : chunks) { + world.refreshChunk(chunkPos.getBlockX(), chunkPos.getBlockZ()); + } + } + + @Override + public boolean playEffect(Vector position, int type, int data) { + World world = getWorld(); + + final Effect effect = effects.get(type); + if (effect == null) { + return false; + } + + world.playEffect(BukkitUtil.toLocation(world, position), effect, data); + + return true; + } + + @Override + public WorldData getWorldData() { + try { + Class wd = Class.forName("com.sk89q.worldedit.bukkit.BukkitWorldData"); + Method methodInstance = wd.getDeclaredMethod("getInstance"); + methodInstance.setAccessible(true); + return (WorldData) methodInstance.invoke(null); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + @Override + public void simulateBlockMine(Vector pt) { + getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).breakNaturally(); + } + + @Override + public BaseBlock getBlock(Vector position) { + BukkitImplAdapter adapter = BukkitQueue_0.adapter; + if (adapter != null) { + return adapter.getBlock(adapt(getWorld(), position)); + } else { + Block bukkitBlock = getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + return new BaseBlock(bukkitBlock.getTypeId(), bukkitBlock.getData()); + } + } + + @Override + public boolean setBlock(Vector position, BaseBlock block, boolean notifyAndLight) throws WorldEditException { + BukkitImplAdapter adapter = BukkitQueue_0.getAdapter(); + if (adapter != null) { + return adapter.setBlock(adapt(getWorld(), position), block, notifyAndLight); + } else { + Block bukkitBlock = getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + return bukkitBlock.setTypeIdAndData(block.getType(), (byte) block.getData(), notifyAndLight); + } + } + + @SuppressWarnings("deprecation") + @Override + public BaseBlock getLazyBlock(Vector position) { + World world = getWorld(); + Block bukkitBlock = world.getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + return new LazyBlock(bukkitBlock.getTypeId(), bukkitBlock.getData(), this, position); + } + + @Override + public BaseBiome getBiome(Vector2D position) { + BukkitImplAdapter adapter = BukkitQueue_0.getAdapter(); + if (adapter != null) { + int id = adapter.getBiomeId(getWorld().getBiome(position.getBlockX(), position.getBlockZ())); + return new BaseBiome(id); + } else { + return new BaseBiome(0); + } + } + + @Override + public boolean setBiome(Vector2D position, BaseBiome biome) { + BukkitImplAdapter adapter = BukkitQueue_0.getAdapter(); + if (adapter != null) { + Biome bukkitBiome = adapter.getBiome(biome.getId()); + getWorld().setBiome(position.getBlockX(), position.getBlockZ(), bukkitBiome); + return true; + } else { + return false; + } + } + + /** + * @deprecated Use {@link #setBlock(Vector, BaseBlock, boolean)} + */ + @Deprecated + public boolean setBlock(Vector pt, com.sk89q.worldedit.foundation.Block block, boolean notifyAdjacent) throws WorldEditException { + return setBlock(pt, (BaseBlock) block, notifyAdjacent); + } + + public static Class inject() { + return BukkitWorld.class; + } +} \ No newline at end of file diff --git a/bukkit/src/main/java/com/sk89q/worldedit/bukkit/DelegateEntity.java b/bukkit/src/main/java/com/sk89q/worldedit/bukkit/DelegateEntity.java new file mode 100644 index 00000000..c8e2232d --- /dev/null +++ b/bukkit/src/main/java/com/sk89q/worldedit/bukkit/DelegateEntity.java @@ -0,0 +1,46 @@ +package com.sk89q.worldedit.bukkit; + +import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.util.Location; +import javax.annotation.Nullable; + +public class DelegateEntity implements Entity { + private final Entity parent; + + public DelegateEntity(Entity parent) { + this.parent = parent; + } + + public Entity getParent() { + return parent; + } + + @Override + @Nullable + public BaseEntity getState() { + return parent.getState(); + } + + @Override + public Location getLocation() { + return parent.getLocation(); + } + + @Override + public Extent getExtent() { + return parent.getExtent(); + } + + @Override + public boolean remove() { + return parent.remove(); + } + + @Override + @Nullable + public T getFacet(Class cls) { + return parent.getFacet(cls); + } +} diff --git a/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java b/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java index 0ad0397e..45caadf5 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java @@ -350,7 +350,7 @@ public class ClipboardCommands { } @Command( - aliases = {"/paste", "/p"}, + aliases = {"/paste"}, usage = "", flags = "sao", desc = "Paste the clipboard's contents", diff --git a/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java b/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java index 52c53680..083dbd11 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java @@ -44,7 +44,7 @@ import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.util.command.parametric.Optional; -@Command(aliases = {"brush", "br", "/b", "tool"}, desc = "Bind functions to held items: [More Info](https://goo.gl/xPnPxj)") +@Command(aliases = {"brush", "br", "tool"}, desc = "Bind functions to held items: [More Info](https://goo.gl/xPnPxj)") public class ToolCommands { private final WorldEdit we; diff --git a/core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java b/core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java index 0547c558..fe343004 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java @@ -48,7 +48,7 @@ import java.util.Map; import java.util.Scanner; import java.util.TimeZone; -@Command(aliases = {"we", "worldedit", "fawe"}, desc = "Updating, informational, debug and help commands") +@Command(aliases = {"worldedit", "we", "fawe"}, desc = "Updating, informational, debug and help commands") public class WorldEditCommands { private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");