From 37da1fec407aa2f831c746ab32a8bd2eaffd3998 Mon Sep 17 00:00:00 2001 From: zml2008 Date: Thu, 5 Jan 2012 20:53:01 -0800 Subject: [PATCH] Added initial SpoutAPI compatibility --- pom.xml | 12 + .../java/com/sk89q/util/yaml/YAMLFormat.java | 2 +- .../java/com/sk89q/util/yaml/YAMLNode.java | 12 +- .../com/sk89q/util/yaml/YAMLProcessor.java | 7 +- .../util/yaml/YAMLProcessorException.java | 2 +- .../sk89q/worldedit/spout/SessionTimer.java | 51 ++ .../worldedit/spout/SpoutCommandSender.java | 110 +++ .../sk89q/worldedit/spout/SpoutPlayer.java | 156 ++++ .../worldedit/spout/SpoutPlayerBlockBag.java | 233 ++++++ .../spout/SpoutRawCommandExecutor.java | 46 ++ .../worldedit/spout/SpoutServerInterface.java | 87 ++ .../com/sk89q/worldedit/spout/SpoutUtil.java | 105 +++ .../com/sk89q/worldedit/spout/SpoutWorld.java | 758 ++++++++++++++++++ .../spout/WorldEditPlayerListener.java | 178 ++++ .../worldedit/spout/WorldEditPlugin.java | 354 ++++++++ .../spout/selections/CuboidSelection.java | 70 ++ .../selections/Polygonal2DSelection.java | 66 ++ .../spout/selections/RegionSelection.java | 107 +++ .../worldedit/spout/selections/Selection.java | 107 +++ src/main/resources/spoutplugin.yml | 7 + 20 files changed, 2459 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/sk89q/worldedit/spout/SessionTimer.java create mode 100644 src/main/java/com/sk89q/worldedit/spout/SpoutCommandSender.java create mode 100644 src/main/java/com/sk89q/worldedit/spout/SpoutPlayer.java create mode 100644 src/main/java/com/sk89q/worldedit/spout/SpoutPlayerBlockBag.java create mode 100644 src/main/java/com/sk89q/worldedit/spout/SpoutRawCommandExecutor.java create mode 100644 src/main/java/com/sk89q/worldedit/spout/SpoutServerInterface.java create mode 100644 src/main/java/com/sk89q/worldedit/spout/SpoutUtil.java create mode 100644 src/main/java/com/sk89q/worldedit/spout/SpoutWorld.java create mode 100644 src/main/java/com/sk89q/worldedit/spout/WorldEditPlayerListener.java create mode 100644 src/main/java/com/sk89q/worldedit/spout/WorldEditPlugin.java create mode 100644 src/main/java/com/sk89q/worldedit/spout/selections/CuboidSelection.java create mode 100644 src/main/java/com/sk89q/worldedit/spout/selections/Polygonal2DSelection.java create mode 100644 src/main/java/com/sk89q/worldedit/spout/selections/RegionSelection.java create mode 100644 src/main/java/com/sk89q/worldedit/spout/selections/Selection.java create mode 100644 src/main/resources/spoutplugin.yml diff --git a/pom.xml b/pom.xml index a80613d9e..eaa910c8b 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,10 @@ bukkit-releases http://repo.bukkit.org/content/repositories/releases + + spout-repo + http://repo.getspout.org + @@ -79,6 +83,13 @@ 1.9.0-rc1 test + + + + org.getspout + spoutapi + dev-SNAPSHOT + @@ -183,6 +194,7 @@ org.apache.maven.plugins maven-surefire-plugin + 2.7.2 **/TestOfflinePermissible.java diff --git a/src/main/java/com/sk89q/util/yaml/YAMLFormat.java b/src/main/java/com/sk89q/util/yaml/YAMLFormat.java index aa1cc9016..a6181b5c3 100644 --- a/src/main/java/com/sk89q/util/yaml/YAMLFormat.java +++ b/src/main/java/com/sk89q/util/yaml/YAMLFormat.java @@ -1,6 +1,6 @@ // $Id$ /* - * RegionBook + * WorldEdit * Copyright (C) 2010, 2011 sk89q and contributors * * This program is free software: you can redistribute it and/or modify diff --git a/src/main/java/com/sk89q/util/yaml/YAMLNode.java b/src/main/java/com/sk89q/util/yaml/YAMLNode.java index 4c1a79370..4283fe682 100644 --- a/src/main/java/com/sk89q/util/yaml/YAMLNode.java +++ b/src/main/java/com/sk89q/util/yaml/YAMLNode.java @@ -1,6 +1,6 @@ // $Id$ /* - * RegionBook + * WorldEdit * Copyright (C) 2010, 2011 sk89q * * This program is free software: you can redistribute it and/or modify @@ -24,7 +24,7 @@ import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector2D; import java.util.ArrayList; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -111,7 +111,7 @@ public class YAMLNode { */ private Object prepareSerialization(Object value) { if (value instanceof Vector) { - Map out = new HashMap(); + Map out = new LinkedHashMap(); Vector vec = (Vector) value; out.put("x", vec.getX()); out.put("y", vec.getY()); @@ -152,7 +152,7 @@ public class YAMLNode { if (o == null || !(o instanceof Map)) { // This will override existing configuration data! - o = new HashMap(); + o = new LinkedHashMap(); node.put(parts[i], o); } @@ -169,7 +169,7 @@ public class YAMLNode { * @return */ public YAMLNode addNode(String path) { - Map map = new HashMap(); + Map map = new LinkedHashMap(); YAMLNode node = new YAMLNode(map, writeDefaults); setProperty(path, map); return node; @@ -696,7 +696,7 @@ public class YAMLNode { return null; } else if (o instanceof Map) { Map nodes = - new HashMap(); + new LinkedHashMap(); for (Map.Entry entry : ((Map) o).entrySet()) { if (entry.getValue() instanceof Map) { diff --git a/src/main/java/com/sk89q/util/yaml/YAMLProcessor.java b/src/main/java/com/sk89q/util/yaml/YAMLProcessor.java index 7c742255a..eec16c575 100644 --- a/src/main/java/com/sk89q/util/yaml/YAMLProcessor.java +++ b/src/main/java/com/sk89q/util/yaml/YAMLProcessor.java @@ -1,6 +1,6 @@ // $Id$ /* - * RegionBook + * WorldEdit * Copyright (C) 2010, 2011 sk89q * * This program is free software: you can redistribute it and/or modify @@ -27,6 +27,7 @@ import org.yaml.snakeyaml.representer.Representer; import java.io.*; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; /** @@ -98,7 +99,7 @@ public class YAMLProcessor extends YAMLNode { if (stream == null) throw new IOException("Stream is null!"); read(yaml.load(new UnicodeReader(stream))); } catch (YAMLProcessorException e) { - root = new HashMap(); + root = new LinkedHashMap(); } finally { try { if (stream != null) { @@ -189,7 +190,7 @@ public class YAMLProcessor extends YAMLNode { private void read(Object input) throws YAMLProcessorException { try { if (null == input) { - root = new HashMap(); + root = new LinkedHashMap(); } else { root = (Map) input; } diff --git a/src/main/java/com/sk89q/util/yaml/YAMLProcessorException.java b/src/main/java/com/sk89q/util/yaml/YAMLProcessorException.java index 642b826dc..ac0eb3611 100644 --- a/src/main/java/com/sk89q/util/yaml/YAMLProcessorException.java +++ b/src/main/java/com/sk89q/util/yaml/YAMLProcessorException.java @@ -1,6 +1,6 @@ // $Id$ /* - * RegionBook + * WorldEdit * Copyright (C) 2010, 2011 sk89q * * This program is free software: you can redistribute it and/or modify diff --git a/src/main/java/com/sk89q/worldedit/spout/SessionTimer.java b/src/main/java/com/sk89q/worldedit/spout/SessionTimer.java new file mode 100644 index 000000000..fdfa3cb2d --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/spout/SessionTimer.java @@ -0,0 +1,51 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010, 2011 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +package com.sk89q.worldedit.spout; + +import com.sk89q.worldedit.SessionCheck; +import com.sk89q.worldedit.WorldEdit; +import org.getspout.api.Game; +import org.getspout.api.player.Player; + +/** + * Used to remove expired sessions in Bukkit. + * + * @author sk89q + */ +public class SessionTimer implements Runnable { + + private WorldEdit worldEdit; + private SessionCheck checker; + + public SessionTimer(WorldEdit worldEdit, final Game game) { + this.worldEdit = worldEdit; + this.checker = new SessionCheck() { + public boolean isOnlinePlayer(String name) { + Player player = game.getPlayer(name, true); + return player != null && player.isOnline(); + } + }; + } + + public void run() { + worldEdit.flushExpiredSessions(checker); + } + +} diff --git a/src/main/java/com/sk89q/worldedit/spout/SpoutCommandSender.java b/src/main/java/com/sk89q/worldedit/spout/SpoutCommandSender.java new file mode 100644 index 000000000..02d4032ad --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/spout/SpoutCommandSender.java @@ -0,0 +1,110 @@ +package com.sk89q.worldedit.spout; + +import com.sk89q.worldedit.LocalPlayer; +import com.sk89q.worldedit.LocalWorld; +import com.sk89q.worldedit.PlayerNeededException; +import com.sk89q.worldedit.ServerInterface; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldVector; +import com.sk89q.worldedit.bags.BlockBag; +import org.getspout.api.ChatColor; +import org.getspout.api.Spout; +import org.getspout.api.command.CommandSource; +import org.getspout.api.player.Player; + +import java.util.logging.Level; + +public class SpoutCommandSender extends LocalPlayer { + private CommandSource sender; + private WorldEditPlugin plugin; + + public SpoutCommandSender(WorldEditPlugin plugin, ServerInterface server, CommandSource sender) { + super(server); + this.plugin = plugin; + this.sender = sender; + } + + @Override + public String getName() { + //return sender.getName(); + return "Console"; + } + + @Override + public void printRaw(String msg) { + sender.sendRawMessage(msg); + } + + @Override + public void printDebug(String msg) { + sender.sendMessage(ChatColor.GRAY + msg); + + } + + @Override + public void print(String msg) { + sender.sendMessage(ChatColor.PURPLE + msg); + } + + @Override + public void printError(String msg) { + sender.sendMessage(ChatColor.RED + msg); + } + + @Override + public String[] getGroups() { + return new String[0]; + } + + @Override + public boolean hasPermission(String perm) { + // TODO: Implement permissions + // return sender.isOp(): + return true; + } + + @Override + public boolean isPlayer() { + return sender instanceof Player; + } + + @Override + public int getItemInHand() { + throw new PlayerNeededException(); + } + + @Override + public WorldVector getPosition() { + throw new PlayerNeededException(); + } + + @Override + public LocalWorld getWorld() { + throw new PlayerNeededException(); + } + + @Override + public double getPitch() { + throw new PlayerNeededException(); + } + + @Override + public double getYaw() { + throw new PlayerNeededException(); + } + + @Override + public void giveItem(int type, int amt) { + throw new PlayerNeededException(); + } + + @Override + public void setPosition(Vector pos, float pitch, float yaw) { + throw new PlayerNeededException(); + } + + @Override + public BlockBag getInventoryBlockBag() { + throw new PlayerNeededException(); + } +} diff --git a/src/main/java/com/sk89q/worldedit/spout/SpoutPlayer.java b/src/main/java/com/sk89q/worldedit/spout/SpoutPlayer.java new file mode 100644 index 000000000..062d0bfa0 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/spout/SpoutPlayer.java @@ -0,0 +1,156 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +package com.sk89q.worldedit.spout; + +import com.sk89q.util.StringUtil; +import com.sk89q.worldedit.LocalPlayer; +import com.sk89q.worldedit.LocalWorld; +import com.sk89q.worldedit.ServerInterface; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldVector; +import com.sk89q.worldedit.bags.BlockBag; +import com.sk89q.worldedit.cui.CUIEvent; +import org.getspout.api.geo.discrete.Point; +import org.getspout.api.geo.discrete.Transform; +import org.getspout.api.inventory.ItemStack; +import org.getspout.api.math.MathHelper; +import org.getspout.api.math.Quaternion; +import org.getspout.api.math.Vector3; +import org.getspout.api.player.Player; + +public class SpoutPlayer extends LocalPlayer { + private Player player; + private WorldEditPlugin plugin; + + public SpoutPlayer(WorldEditPlugin plugin, ServerInterface server, Player player) { + super(server); + this.plugin = plugin; + this.player = player; + } + + @Override + public int getItemInHand() { + ItemStack itemStack = null;//player.getItemInHand(); + return itemStack != null ? itemStack.getMaterial().getRawId() : 0; + } + + @Override + public String getName() { + return player.getName(); + } + + @Override + public WorldVector getPosition() { + Point loc = player.getEntity().getTransform().getPosition(); + return new WorldVector(SpoutUtil.getLocalWorld(loc.getWorld()), + loc.getX(), loc.getY(), loc.getZ()); + } + + @Override + public double getPitch() { + return MathHelper.getDirectionVector(player.getEntity().getTransform().getRotation()).getY(); + } + + @Override + public double getYaw() { + return MathHelper.getDirectionVector(player.getEntity().getTransform().getRotation()).getZ(); + } + + @Override + public void giveItem(int type, int amt) { + //player.getInventory().addItem(new ItemStack(type, amt)); + } + + @Override + public void printRaw(String msg) { + for (String part : msg.split("\n")) { + player.sendMessage(part); + } + } + + @Override + public void print(String msg) { + for (String part : msg.split("\n")) { + player.sendMessage("\u00A7d" + part); + } + } + + @Override + public void printDebug(String msg) { + for (String part : msg.split("\n")) { + player.sendMessage("\u00A77" + part); + } + } + + @Override + public void printError(String msg) { + for (String part : msg.split("\n")) { + player.sendMessage("\u00A7c" + part); + } + } + + @Override + public void setPosition(Vector pos, float pitch, float yaw) { + Transform t = player.getEntity().getTransform(); + t.setPosition(new Point(t.getPosition().getWorld(), (float) pos.getX(), (float) pos.getY(), (float) pos.getZ())); + t.setRotation(new Quaternion(pitch, Vector3.UNIT_Z).rotate(yaw, Vector3.UNIT_Y)); + } + + @Override + public String[] getGroups() { + return new String[0]; + } + + @Override + public BlockBag getInventoryBlockBag() { + return new SpoutPlayerBlockBag(player); + } + + @Override + public boolean hasPermission(String perm) { + return true; // TODO: Implement permissions + } + + @Override + public LocalWorld getWorld() { + return SpoutUtil.getLocalWorld(player.getEntity().getTransform().getPosition().getWorld()); + } + + @Override + public void dispatchCUIEvent(CUIEvent event) { + String[] params = event.getParameters(); + + if (params.length > 0) { + player.sendRawMessage("\u00A75\u00A76\u00A74\u00A75" + event.getTypeId() + + "|" + StringUtil.joinString(params, "|")); + } else { + player.sendRawMessage("\u00A75\u00A76\u00A74\u00A75" + event.getTypeId()); + } + } + + @Override + public void dispatchCUIHandshake() { + player.sendRawMessage("\u00A75\u00A76\u00A74\u00A75"); + } + + public Player getPlayer() { + return player; + } +} diff --git a/src/main/java/com/sk89q/worldedit/spout/SpoutPlayerBlockBag.java b/src/main/java/com/sk89q/worldedit/spout/SpoutPlayerBlockBag.java new file mode 100644 index 000000000..8c9d5d97c --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/spout/SpoutPlayerBlockBag.java @@ -0,0 +1,233 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +package com.sk89q.worldedit.spout; + +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.bags.BlockBag; +import com.sk89q.worldedit.bags.BlockBagException; +import com.sk89q.worldedit.bags.OutOfBlocksException; +import com.sk89q.worldedit.bags.OutOfSpaceException; +import com.sk89q.worldedit.blocks.BaseItem; +import com.sk89q.worldedit.blocks.BaseItemStack; +import com.sk89q.worldedit.blocks.BlockID; +import com.sk89q.worldedit.blocks.ItemType; +import org.getspout.api.inventory.ItemStack; +import org.getspout.api.material.MaterialData; +import org.getspout.api.player.Player; + +public class SpoutPlayerBlockBag extends BlockBag { + /** + * Player instance. + */ + private Player player; + /** + * The player's inventory; + */ + private ItemStack[] items; + + /** + * Construct the object. + * + * @param player + */ + public SpoutPlayerBlockBag(Player player) { + this.player = player; + } + + /** + * Loads inventory on first use. + */ + private void loadInventory() { + if (items == null) { + items = new ItemStack[0]; + //items = player.getInventory().getContents(); + } + } + + /** + * Get the player. + * + * @return + */ + public Player getPlayer() { + return player; + } + + /** + * Get a block. + * + * @param item + */ + @Override + public void fetchItem(BaseItem item) throws BlockBagException { + final int id = item.getType(); + final int damage = item.getDamage(); + int amount = (item instanceof BaseItemStack) ? ((BaseItemStack) item).getAmount() : 1; + assert(amount == 1); + boolean usesDamageValue = ItemType.usesDamageValue(id); + + if (id == BlockID.AIR) { + throw new IllegalArgumentException("Can't fetch air block"); + } + + loadInventory(); + + boolean found = false; + + for (int slot = 0; slot < items.length; ++slot) { + ItemStack bukkitItem = items[slot]; + + if (bukkitItem == null) { + continue; + } + + if (bukkitItem.getMaterial().getRawId() != id) { + // Type id doesn't fit + continue; + } + + if (usesDamageValue && bukkitItem.getDamage() != damage) { + // Damage value doesn't fit. + continue; + } + + int currentAmount = bukkitItem.getAmount(); + if (currentAmount < 0) { + // Unlimited + return; + } + + if (currentAmount > 1) { + bukkitItem.setAmount(currentAmount - 1); + found = true; + } else { + items[slot] = null; + found = true; + } + + break; + } + + if (!found) { + throw new OutOfBlocksException(); + } + } + + /** + * Store a block. + * + * @param item + */ + @Override + public void storeItem(BaseItem item) throws BlockBagException { + final int id = item.getType(); + final int damage = item.getDamage(); + int amount = (item instanceof BaseItemStack) ? ((BaseItemStack) item).getAmount() : 1; + assert(amount <= 64); + boolean usesDamageValue = ItemType.usesDamageValue(id); + + if (id == BlockID.AIR) { + throw new IllegalArgumentException("Can't store air block"); + } + + loadInventory(); + + int freeSlot = -1; + + for (int slot = 0; slot < items.length; ++slot) { + ItemStack bukkitItem = items[slot]; + + if (bukkitItem == null) { + // Delay using up a free slot until we know there are no stacks + // of this item to merge into + + if (freeSlot == -1) { + freeSlot = slot; + } + continue; + } + + if (bukkitItem.getMaterial().getRawId() != id) { + // Type id doesn't fit + continue; + } + + if (usesDamageValue && bukkitItem.getDamage() != damage) { + // Damage value doesn't fit. + continue; + } + + int currentAmount = bukkitItem.getAmount(); + if (currentAmount < 0) { + // Unlimited + return; + } + if (currentAmount >= 64) { + // Full stack + continue; + } + + int spaceLeft = 64 - currentAmount; + if (spaceLeft >= amount) { + bukkitItem.setAmount(currentAmount + amount); + return; + } + + bukkitItem.setAmount(64); + amount -= spaceLeft; + } + + if (freeSlot > -1) { + items[freeSlot] = new ItemStack(MaterialData.getMaterial((short)id), amount); + return; + } + + throw new OutOfSpaceException(id); + } + + /** + * Flush any changes. This is called at the end. + */ + @Override + public void flushChanges() { + if (items != null) { + //player.getInventory().setContents(items); + items = null; + } + } + + /** + * Adds a position to be used a source. + * + * @param pos + */ + @Override + public void addSourcePosition(Vector pos) { + } + + /** + * Adds a position to be used a source. + * + * @param pos + */ + @Override + public void addSingleSourcePosition(Vector pos) { + } +} diff --git a/src/main/java/com/sk89q/worldedit/spout/SpoutRawCommandExecutor.java b/src/main/java/com/sk89q/worldedit/spout/SpoutRawCommandExecutor.java new file mode 100644 index 000000000..c1d31cea2 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/spout/SpoutRawCommandExecutor.java @@ -0,0 +1,46 @@ +/* + * WorldEdit + * Copyright (C) 2012 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.spout; + +import org.bukkit.Bukkit; +import org.getspout.api.command.CommandException; +import org.getspout.api.command.CommandSource; +import org.getspout.api.command.RawCommandExecutor; +import org.getspout.api.util.MiscCompatibilityUtils; + +/** + * @author zml2008 + */ +public class SpoutRawCommandExecutor implements RawCommandExecutor { + + private final WorldEditPlugin plugin; + + public SpoutRawCommandExecutor(WorldEditPlugin plugin) { + this.plugin = plugin; + } + + @Override + public void execute(CommandSource source, String[] args, int baseIndex, boolean fuzzyLookup) throws CommandException { + Bukkit.getServer().getCommandAliases(); + args[baseIndex] = "/" + args[baseIndex]; + if (!plugin.getWorldEdit().handleCommand(plugin.wrapCommandSender(source), MiscCompatibilityUtils.arrayCopyOfRange(args, baseIndex, args.length))) { + throw new CommandException("Unknown command: '" + args[baseIndex] + "'!"); + } + } +} diff --git a/src/main/java/com/sk89q/worldedit/spout/SpoutServerInterface.java b/src/main/java/com/sk89q/worldedit/spout/SpoutServerInterface.java new file mode 100644 index 000000000..d41060442 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/spout/SpoutServerInterface.java @@ -0,0 +1,87 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +package com.sk89q.worldedit.spout; + +import com.sk89q.minecraft.util.commands.Command; +import com.sk89q.worldedit.LocalWorld; +import com.sk89q.worldedit.ServerInterface; +import org.getspout.api.Game; +import org.getspout.api.Spout; +import org.getspout.api.geo.World; +import org.getspout.api.material.Material; +import org.getspout.api.material.MaterialData; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class SpoutServerInterface extends ServerInterface { + public Game game; + public WorldEditPlugin plugin; + private final SpoutRawCommandExecutor executor; + + public SpoutServerInterface(WorldEditPlugin plugin, Game game) { + this.plugin = plugin; + this.game = game; + this.executor = new SpoutRawCommandExecutor(plugin); + } + + @Override + public int resolveItem(String name) { + Material mat = MaterialData.getMaterial(name); + return mat == null ? 0 : mat.getRawId(); + } + + @Override + public boolean isValidMobType(String type) { + return false; + //return CreatureType.fromName(type) != null; + } + + @Override + public void reload() { + plugin.loadConfiguration(); + } + + @Override + public int schedule(long delay, long period, Runnable task) { + return game.getScheduler().scheduleSyncRepeatingTask(plugin, task, delay, period); + } + + @Override + public List getWorlds() { + Collection worlds = game.getWorlds(); + List ret = new ArrayList(worlds.size()); + + for (World world : worlds) { + ret.add(SpoutUtil.getLocalWorld(world)); + } + + return ret; + } + + @Override + public void onCommandRegistration(List commands) { + for (Command command : commands) { + Spout.getGame().getRootCommand().sub(plugin, command.aliases()[0]) + .addAlias(command.aliases()).setRawExecutor(executor).closeSubCommand(); + } + } +} diff --git a/src/main/java/com/sk89q/worldedit/spout/SpoutUtil.java b/src/main/java/com/sk89q/worldedit/spout/SpoutUtil.java new file mode 100644 index 000000000..2fa85a25e --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/spout/SpoutUtil.java @@ -0,0 +1,105 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +package com.sk89q.worldedit.spout; + +import com.sk89q.worldedit.BlockVector; +import com.sk89q.worldedit.BlockWorldVector; +import com.sk89q.worldedit.LocalWorld; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldVector; +import org.getspout.api.Game; +import org.getspout.api.geo.World; +import org.getspout.api.geo.cuboid.Block; +import org.getspout.api.geo.discrete.Point; +import org.getspout.api.material.block.BlockFace; +import org.getspout.api.math.Vector3; +import org.getspout.api.player.Player; + +import java.util.HashMap; +import java.util.Map; + +public class SpoutUtil { + private SpoutUtil() { + } + + private static final Map wlw = new HashMap(); + + public static LocalWorld getLocalWorld(World w) { + LocalWorld lw = wlw.get(w); + if (lw == null) { + lw = new SpoutWorld(w); + wlw.put(w, lw); + } + return lw; + } + + public static BlockVector toVector(Block block) { + return new BlockVector(block.getX(), block.getY(), block.getZ()); + } + + public static BlockVector toVector(BlockFace face) { + return toBlockVector(face.getOffset()); + } + + public static BlockVector toBlockVector(Vector3 vector) { + return new BlockVector(vector.getX(), vector.getY(), vector.getZ()); + } + + public static BlockWorldVector toWorldVector(Block block) { + return new BlockWorldVector(getLocalWorld(block.getWorld()), block.getX(), block.getY(), block.getZ()); + } + + public static Vector toVector(Point loc) { + return new Vector(loc.getX(), loc.getY(), loc.getZ()); + } + + public static Vector toVector(org.getspout.api.math.Vector3 vector) { + return new Vector(vector.getX(), vector.getY(), vector.getZ()); + } + + public static Point toPoint(WorldVector pt) { + return new Point(toWorld(pt), (float)pt.getX(), (float)pt.getY(), (float)pt.getZ()); + } + + public static Point toPoint(World world, Vector pt) { + return new Point(world, (float)pt.getX(), (float)pt.getY(), (float)pt.getZ()); + } + + public static Point center(Point loc) { + return new Point( + loc.getWorld(), + loc.getX() + 0.5F, + loc.getY() + 0.5F, + loc.getZ() + 0.5F + ); + } + + public static Player matchSinglePlayer(Game game, String name) { + return game.getPlayer(name, false); + } + + public static Block toBlock(BlockWorldVector pt) { + return toWorld(pt).getBlock(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + } + + public static World toWorld(WorldVector pt) { + return ((SpoutWorld) pt.getWorld()).getWorld(); + } +} diff --git a/src/main/java/com/sk89q/worldedit/spout/SpoutWorld.java b/src/main/java/com/sk89q/worldedit/spout/SpoutWorld.java new file mode 100644 index 000000000..89a7e202b --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/spout/SpoutWorld.java @@ -0,0 +1,758 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +package com.sk89q.worldedit.spout; + +import com.sk89q.worldedit.BlockVector2D; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.EntityType; +import com.sk89q.worldedit.LocalWorld; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.blocks.BaseItemStack; +import com.sk89q.worldedit.regions.Region; + +import org.getspout.api.geo.World; +import org.getspout.api.geo.discrete.Point; +import org.getspout.api.material.MaterialData; + +public class SpoutWorld extends LocalWorld { + private World world; + + /** + * Construct the object. + * @param world + */ + public SpoutWorld(World world) { + this.world = world; + } + + /** + * Get the world handle. + * + * @return + */ + public World getWorld() { + return world; + } + + /** + * Get the name of the world + * + * @return + */ + @Override + public String getName() { + return world.getName(); + } + + /** + * Set block type. + * + * @param pt + * @param type + * @return + */ + @Override + public boolean setBlockType(Vector pt, int type) { + return world.getBlock(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).setBlockId((short)type) != type; + } + + /** + * Set block type. + * + * @param pt + * @param type + * @return + */ + @Override + public boolean setBlockTypeFast(Vector pt, int type) { + return setBlockType(pt, type); + } + + /** + * set block type & data + * @param pt + * @param type + * @param data + * @return + */ + @Override + public boolean setTypeIdAndData(Vector pt, int type, int data) { + return world.setBlockId(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), (short)type) != type + && world.setBlockData(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), (byte)data) != data; + } + + /** + * set block type & data + * Everything is threaded, so no need for fastmode here. + * @param pt + * @param type + * @param data + * @return + */ + @Override + public boolean setTypeIdAndDataFast(Vector pt, int type, int data) { + return setTypeIdAndData(pt, type, data); + //return world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).setTypeIdAndData(type, (byte) data, false); + } + + /** + * Get block type. + * + * @param pt + * @return + */ + @Override + public int getBlockType(Vector pt) { + return world.getBlockId(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + } + + /** + * Set block data. + * + * @param pt + * @param data + */ + @Override + public void setBlockData(Vector pt, int data) { + world.setBlockData(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), (byte)data); + } + + /** + * Set block data. + * + * @param pt + * @param data + */ + @Override + public void setBlockDataFast(Vector pt, int data) { + setBlockData(pt, data); + } + + /** + * Get block data. + * + * @param pt + * @return + */ + @Override + public int getBlockData(Vector pt) { + return world.getBlockData(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + } + + /** + * Get block light level. + * + * @param pt + * @return + */ + @Override + public int getBlockLightLevel(Vector pt) { + return world.getBlockMaterial(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).getLightLevel(); + } + + /** + * Regenerate an area. + * + * @param region + * @param editSession + * @return + */ + @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 { + world.regenerateChunk(chunk.getBlockX(), chunk.getBlockZ()); + } catch (Throwable t) { + t.printStackTrace(); + } + + // 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;*/ + return false; + } + + /** + * Attempts to accurately copy a BaseBlock's extra data to the world. + * + * @param pt + * @param block + * @return + */ + @Override + public boolean copyToWorld(Vector pt, BaseBlock block) { + /*if (block instanceof SignBlock) { + // Signs + setSignText(pt, ((SignBlock) block).getText()); + return true; + } + + if (block instanceof FurnaceBlock) { + // Furnaces + Block bukkitBlock = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + if (bukkitBlock == null) return false; + BlockState state = bukkitBlock.getState(); + if (!(state instanceof Furnace)) return false; + Furnace bukkit = (Furnace) state; + FurnaceBlock we = (FurnaceBlock) block; + bukkit.setBurnTime(we.getBurnTime()); + bukkit.setCookTime(we.getCookTime()); + return setContainerBlockContents(pt, ((ContainerBlock) block).getItems()); + } + + if (block instanceof ContainerBlock) { + // Chests/dispenser + return setContainerBlockContents(pt, ((ContainerBlock) block).getItems()); + } + + if (block instanceof MobSpawnerBlock) { + // Mob spawners + Block bukkitBlock = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + if (bukkitBlock == null) return false; + BlockState state = bukkitBlock.getState(); + if (!(state instanceof CreatureSpawner)) return false; + CreatureSpawner bukkit = (CreatureSpawner) state; + MobSpawnerBlock we = (MobSpawnerBlock) block; + bukkit.setCreatureTypeId(we.getMobType()); + bukkit.setDelay(we.getDelay()); + return true; + } + + if (block instanceof NoteBlock) { + // Note block + Block bukkitBlock = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + if (bukkitBlock == null) return false; + BlockState state = bukkitBlock.getState(); + if (!(state instanceof org.bukkit.block.NoteBlock)) return false; + org.bukkit.block.NoteBlock bukkit = (org.bukkit.block.NoteBlock) state; + NoteBlock we = (NoteBlock) block; + bukkit.setRawNote(we.getNote()); + return true; + }*/ + + return false; + } + + /** + * Attempts to read a BaseBlock's extra data from the world. + * + * @param pt + * @param block + * @return + */ + @Override + public boolean copyFromWorld(Vector pt, BaseBlock block) { + /*if (block instanceof SignBlock) { + // Signs + ((SignBlock) block).setText(getSignText(pt)); + return true; + } + + if (block instanceof FurnaceBlock) { + // Furnaces + Block bukkitBlock = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + if (bukkitBlock == null) return false; + BlockState state = bukkitBlock.getState(); + if (!(state instanceof Furnace)) return false; + Furnace bukkit = (Furnace) state; + FurnaceBlock we = (FurnaceBlock) block; + we.setBurnTime(bukkit.getBurnTime()); + we.setCookTime(bukkit.getCookTime()); + ((ContainerBlock) block).setItems(getContainerBlockContents(pt)); + return true; + } + + if (block instanceof ContainerBlock) { + // Chests/dispenser + ((ContainerBlock) block).setItems(getContainerBlockContents(pt)); + return true; + } + + if (block instanceof MobSpawnerBlock) { + // Mob spawners + Block bukkitBlock = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + if (bukkitBlock == null) return false; + BlockState state = bukkitBlock.getState(); + if (!(state instanceof CreatureSpawner)) return false; + CreatureSpawner bukkit = (CreatureSpawner) state; + MobSpawnerBlock we = (MobSpawnerBlock) block; + we.setMobType(bukkit.getCreatureTypeId()); + we.setDelay((short) bukkit.getDelay()); + return true; + } + + if (block instanceof NoteBlock) { + // Note block + Block bukkitBlock = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + if (bukkitBlock == null) return false; + BlockState state = bukkitBlock.getState(); + if (!(state instanceof org.bukkit.block.NoteBlock)) return false; + org.bukkit.block.NoteBlock bukkit = (org.bukkit.block.NoteBlock) state; + NoteBlock we = (NoteBlock) block; + we.setNote(bukkit.getRawNote()); + }*/ + + return false; + } + + /** + * Clear a chest's contents. + * + * @param pt + */ + @Override + public boolean clearContainerBlockContents(Vector pt) { + /* Block block = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + if (block == null) { + return false; + } + BlockState state = block.getState(); + if (!(state instanceof org.bukkit.block.ContainerBlock)) { + return false; + } + + org.bukkit.block.ContainerBlock chest = (org.bukkit.block.ContainerBlock) state; + Inventory inven = chest.getInventory(); + inven.clear(); + return true;*/ + return false; + } + + /** + * Generate a tree at a location. + * + * @param pt + * @return + */ + @Override + public boolean generateTree(EditSession editSession, Vector pt) { + /*return world.generateTree(SpoutUtil.toLocation(world, pt), TreeType.TREE, + new EditSessionBlockChangeDelegate(editSession));*/ + return false; + } + + /** + * Generate a big tree at a location. + * + * @param pt + * @return + */ + @Override + public boolean generateBigTree(EditSession editSession, Vector pt) { + /*return world.generateTree(SpoutUtil.toLocation(world, pt), TreeType.BIG_TREE, + new EditSessionBlockChangeDelegate(editSession));*/ + return false; + } + + /** + * Generate a birch tree at a location. + * + * @param pt + * @return + */ + @Override + public boolean generateBirchTree(EditSession editSession, Vector pt) { + /*return world.generateTree(SpoutUtil.toLocation(world, pt), TreeType.BIRCH, + new EditSessionBlockChangeDelegate(editSession));*/ + return false; + } + + /** + * Generate a redwood tree at a location. + * + * @param pt + * @return + */ + @Override + public boolean generateRedwoodTree(EditSession editSession, Vector pt) { + /*return world.generateTree(SpoutUtil.toLocation(world, pt), TreeType.REDWOOD, + new EditSessionBlockChangeDelegate(editSession));*/ + return false; + } + + /** + * Generate a redwood tree at a location. + * + * @param pt + * @return + */ + @Override + public boolean generateTallRedwoodTree(EditSession editSession, Vector pt) { + /*return world.generateTree(SpoutUtil.toLocation(world, pt), TreeType.TALL_REDWOOD, + new EditSessionBlockChangeDelegate(editSession));*/ + return false; + } + + /** + * Drop an item. + * + * @param pt + * @param item + */ + @Override + public void dropItem(Vector pt, BaseItemStack item) { + /*ItemStack bukkitItem = new ItemStack(item.getType(), item.getAmount(), + (byte) item.getDamage()); + world.dropItemNaturally(toLocation(pt), bukkitItem);*/ + + } + + /** + * Kill mobs in an area. + * + * @param origin The center of the area to kill mobs in. + * @param radius Maximum distance to kill mobs at; radius < 0 means kill all mobs + * @param flags various flags that determine what to kill + * @return + */ + @Override + public int killMobs(Vector origin, double radius, int flags) { + boolean killPets = (flags & KillFlags.PETS) != 0; + boolean killNPCs = (flags & KillFlags.NPCS) != 0; + boolean killAnimals = (flags & KillFlags.ANIMALS) != 0; + + int num = 0; + double radiusSq = radius * radius; + + Point bukkitOrigin = SpoutUtil.toPoint(world, origin); + + /* + for (LivingEntity ent : world.getLivingEntities()) { + if (ent instanceof HumanEntity) { + continue; + } + + if (!killAnimals && ent instanceof Animals) { + continue; + } + + if (!killPets && ent instanceof Tameable && ((Tameable) ent).isTamed()) { + continue; // tamed wolf + } + + try { + // Temporary solution until org.bukkit.entity.NPC is widely deployed. + if (!killNPCs && Class.forName("org.bukkit.entity.NPC").isAssignableFrom(ent.getClass())) { + continue; + } + } catch (ClassNotFoundException e) {} + + if (radius < 0 || bukkitOrigin.distanceSquared(ent.getLocation()) <= radiusSq) { + ent.remove(); + ++num; + } + }*/ + + return num; + } + + /** + * Remove entities in an area. + * + * @param origin + * @param radius + * @return + */ + @Override + public int removeEntities(EntityType type, Vector origin, int radius) { + int num = 0; + double radiusSq = radius * radius; + + /*for (Entity ent : world.getEntities()) { + if (radius != -1 + && origin.distanceSq(SpoutUtil.toVector(ent.getTransform().getPosition())) > radiusSq) { + continue; + } + + if (type == EntityType.ARROWS) { + if (ent instanceof Arrow) { + ent.remove(); + ++num; + } + } else if (type == EntityType.BOATS) { + if (ent instanceof Boat) { + ent.remove(); + ++num; + } + } else if (type == EntityType.ITEMS) { + if (ent instanceof Item) { + ent.remove(); + ++num; + } + } else if (type == EntityType.MINECARTS) { + if (ent instanceof Minecart) { + ent.remove(); + ++num; + } + } else if (type == EntityType.PAINTINGS) { + if (ent instanceof Painting) { + ent.remove(); + ++num; + } + } else if (type == EntityType.TNT) { + if (ent instanceof TNTPrimed) { + ent.remove(); + ++num; + } + } else if (type == EntityType.XP_ORBS) { + if (ent instanceof ExperienceOrb) { + ent.remove(); + ++num; + } + } + }*/ + + return num; + } + + private Point toLocation(Vector pt) { + return new Point(world, (float)pt.getX(), (float)pt.getY(), (float)pt.getZ()); + } + + /** + * Set a sign's text. + * + * @param pt + * @param text + * @return + */ + private boolean setSignText(Vector pt, String[] text) { + /*Block block = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + if (block == null) return false; + BlockState state = block.getState(); + if (state == null || !(state instanceof Sign)) return false; + Sign sign = (Sign) state; + sign.setLine(0, text[0]); + sign.setLine(1, text[1]); + sign.setLine(2, text[2]); + sign.setLine(3, text[3]); + sign.update(); + return true;*/ + return false; + } + + /** + * Get a sign's text. + * + * @param pt + * @return + */ + private String[] getSignText(Vector pt) { + /*Block block = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + if (block == null) return new String[] { "", "", "", "" }; + BlockState state = block.getState(); + if (state == null || !(state instanceof Sign)) return new String[] { "", "", "", "" }; + Sign sign = (Sign) state; + String line0 = sign.getLine(0); + String line1 = sign.getLine(1); + String line2 = sign.getLine(2); + String line3 = sign.getLine(3); + return new String[] { + line0 != null ? line0 : "", + line1 != null ? line1 : "", + line2 != null ? line2 : "", + line3 != null ? line3 : "", + }; + */ + return new String[] {"", "", "", ""}; + } + + /** + * Get a container block's contents. + * + * @param pt + * @return + */ + private BaseItemStack[] getContainerBlockContents(Vector pt) { + /*Block block = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + if (block == null) { + return new BaseItemStack[0]; + } + BlockState state = block.getState(); + if (!(state instanceof org.bukkit.block.ContainerBlock)) { + return new BaseItemStack[0]; + } + + org.bukkit.block.ContainerBlock container = (org.bukkit.block.ContainerBlock) state; + Inventory inven = container.getInventory(); + int size = inven.getContents().length + BaseItemStack[] contents = new BaseItemStack[size]; + + for (int i = 0; i < size; ++i) { + ItemStack bukkitStack = inven.getItem(i); + if (bukkitStack.getMaterial() != MaterialData.air) { + contents[i] = new BaseItemStack( + bukkitStack.getMaterial().getRawId(), + bukkitStack.getAmount(), + bukkitStack.getDamage()); + try { + for (Map.Entry entry : bukkitStack.getEnchantments().entrySet()) { + contents[i].getEnchantments().put(entry.getKey().getId(), entry.getValue()); + } + } catch (Throwable ignore) {} + } + }*/ + + return new BaseItemStack[0]; + } + + /** + * Set a container block's contents. + * + * @param pt + * @param contents + * @return + */ + private boolean setContainerBlockContents(Vector pt, BaseItemStack[] contents) { + /*Block block = world.getBlock(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + if (block == null) { + return false; + } + BlockState state = block.getState(); + if (!(state instanceof org.bukkit.block.ContainerBlock)) { + return false; + } + + org.bukkit.block.ContainerBlock chest = (org.bukkit.block.ContainerBlock) state; + Inventory inven = chest.getInventory(); + int size = inven.getSize(); + + for (int i = 0; i < size; ++i) { + if (i >= contents.length) { + break; + } + + if (contents[i] != null) { + ItemStack toAdd = new ItemStack(contents[i].getType(), + contents[i].getAmount(), + (byte) contents[i].getDamage()); + try { + for (Map.Entry entry : contents[i].getEnchantments().entrySet()) { + toAdd.addEnchantment(Enchantment.getById(entry.getKey()), entry.getValue()); + } + } catch (Throwable ignore) {} + inven.setItem(i, toAdd); + } else { + inven.setItem(i, null); + } + } + + return true;*/ + return false; + } + + /** + * Returns whether a block has a valid ID. + * + * @param type + * @return + */ + @Override + public boolean isValidBlockType(int type) { + return type <= 255 && MaterialData.getMaterial((short)type) != null; + } + + @Override + public void checkLoadedChunk(Vector pt) { + /*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 instanceof SpoutWorld)) { + return false; + } + + return ((SpoutWorld) other).world.equals(world); + } + + @Override + public int hashCode() { + return world.hashCode(); + } + + @Override + public int getMaxY() { + return world.getHeight() - 1; + } + + @Override + public void fixAfterFastMode(Iterable chunks) { + /*for (BlockVector2D chunkPos : chunks) { + world.refreshChunk(chunkPos.getBlockX(), chunkPos.getBlockZ()); + }*/ + } + + /*private static final Map effects = new HashMap(); + static { + for (Effect effect : Effect.values()) { + effects.put(effect.getId(), effect); + } + }*/ + + @Override + public boolean playEffect(Vector position, int type, int data) { + /*final Effect effect = effects.get(type); + if (effect == null) { + return false; + } + + world.playEffect(SpoutUtil.toLocation(world, position), effect, data); + + return true; + */ + return false; + } +} diff --git a/src/main/java/com/sk89q/worldedit/spout/WorldEditPlayerListener.java b/src/main/java/com/sk89q/worldedit/spout/WorldEditPlayerListener.java new file mode 100644 index 000000000..5fa41457e --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/spout/WorldEditPlayerListener.java @@ -0,0 +1,178 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +package com.sk89q.worldedit.spout; + +import com.sk89q.util.StringUtil; +import com.sk89q.worldedit.LocalPlayer; +import com.sk89q.worldedit.LocalWorld; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.WorldVector; +import org.getspout.api.Spout; +import org.getspout.api.event.EventHandler; +import org.getspout.api.event.Listener; +import org.getspout.api.event.Order; +import org.getspout.api.event.player.PlayerChatEvent; +import org.getspout.api.event.player.PlayerInteractEvent; +import org.getspout.api.event.player.PlayerInteractEvent.Action; +import org.getspout.api.event.player.PlayerJoinEvent; +import org.getspout.api.event.player.PlayerLeaveEvent; +import org.getspout.api.event.server.PreCommandEvent; +import org.getspout.api.geo.discrete.Point; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Handles all events thrown in relation to a Player + */ +public class WorldEditPlayerListener implements Listener { + /** + * Plugin. + */ + private WorldEditPlugin plugin; + + private boolean ignoreLeftClickAir = false; + + private final static Pattern cuipattern = Pattern.compile("u00a74u00a75u00a73u00a74([^|]*)\\|?(.*)"); + + /** + * Construct the object; + * + * @param plugin + */ + public WorldEditPlayerListener(WorldEditPlugin plugin) { + this.plugin = plugin; + } + + @EventHandler(event = PlayerJoinEvent.class, order = Order.EARLIEST) + public void onPlayerJoin(PlayerJoinEvent event) { + plugin.wrapPlayer(event.getPlayer()).dispatchCUIHandshake(); + } + + /** + * Called when a player leaves a server + * + * @param event Relevant event details + */ + @EventHandler(event = PlayerLeaveEvent.class) + public void onPlayerQuit(PlayerLeaveEvent event) { + plugin.getWorldEdit().markExpire(plugin.wrapPlayer(event.getPlayer())); + } + + /** + * Called when a player attempts to use a command + * + * @param event Relevant event details + */ + //@EventHandler(event = PreCommandEvent.class, order = Order.EARLY) + public void onPlayerCommandPreprocess(PreCommandEvent event) { + + String[] split = event.getMessage().split(" "); + + if (split.length > 0) { + split[0] = "/" + split[0]; + split = plugin.getWorldEdit().commandDetection(split); + event.setMessage(StringUtil.joinString(split, " ")); + } + } + + /** + * Called when a player interacts + * + * @param event Relevant event details + */ + @EventHandler(event = PlayerInteractEvent.class) + public void onPlayerInteract(PlayerInteractEvent event) { + + final LocalPlayer player = plugin.wrapPlayer(event.getPlayer()); + final LocalWorld world = player.getWorld(); + final WorldEdit we = plugin.getWorldEdit(); + + PlayerInteractEvent.Action action = event.getAction(); + if (action == Action.LEFT_CLICK) { + if (event.isAir() && ignoreLeftClickAir) { + return; + } + + if (!event.isAir()) { + final Point clickedBlock = event.getInteractedPoint(); + final WorldVector pos = new WorldVector(world, clickedBlock.getX(), + clickedBlock.getY(), clickedBlock.getZ()); + + + if (we.handleBlockLeftClick(player, pos)) { + event.setCancelled(true); + } + } + + if (we.handleArmSwing(player)) { + event.setCancelled(true); + } + + if (!event.isAir() && !ignoreLeftClickAir) { + final int taskId = Spout.getGame().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { + public void run() { + ignoreLeftClickAir = false; + } + }, 2); + + if (taskId != -1) { + ignoreLeftClickAir = true; + } + } + } else if (action == Action.RIGHT_CLICK) { + if (!event.isAir()) { + final Point clickedBlock = event.getInteractedPoint(); + final WorldVector pos = new WorldVector(world, clickedBlock.getX(), + clickedBlock.getY(), clickedBlock.getZ()); + + if (we.handleBlockRightClick(player, pos)) { + event.setCancelled(true); + } + } + + if (we.handleRightClick(player)) { + event.setCancelled(true); + } + } + } + + @EventHandler(event = PlayerChatEvent.class) + public void onPlayerChat(PlayerChatEvent event) { + if (event.isCancelled()) { + return; + } + + Matcher matcher = cuipattern.matcher(event.getMessage()); + if (matcher.find()) { + String type = matcher.group(1); + String args = matcher.group(2); + + if( type.equals("v") ) { + try { + plugin.getSession(event.getPlayer()).setCUIVersion(Integer.parseInt(args)); + event.setCancelled(true); + } catch( NumberFormatException e ) { + } + } + + } + } +} diff --git a/src/main/java/com/sk89q/worldedit/spout/WorldEditPlugin.java b/src/main/java/com/sk89q/worldedit/spout/WorldEditPlugin.java new file mode 100644 index 000000000..91b297951 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/spout/WorldEditPlugin.java @@ -0,0 +1,354 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +package com.sk89q.worldedit.spout; + +import com.sk89q.util.yaml.YAMLProcessor; +import com.sk89q.worldedit.*; +import com.sk89q.worldedit.bags.BlockBag; +import com.sk89q.worldedit.regions.CuboidRegion; +import com.sk89q.worldedit.regions.Polygonal2DRegion; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.regions.RegionSelector; +import com.sk89q.worldedit.spout.selections.CuboidSelection; +import com.sk89q.worldedit.spout.selections.Polygonal2DSelection; +import com.sk89q.worldedit.spout.selections.Selection; +import com.sk89q.worldedit.util.YAMLConfiguration; +import org.getspout.api.command.CommandSource; +import org.getspout.api.geo.World; +import org.getspout.api.player.Player; +import org.getspout.api.plugin.CommonPlugin; +import org.getspout.api.util.Named; + +import java.io.*; +import java.util.jar.JarFile; +import java.util.logging.Logger; +import java.util.zip.ZipEntry; + +/** + * Plugin for Spout. + * + * @author sk89q + */ +public class WorldEditPlugin extends CommonPlugin implements Named { + /** + * WorldEdit messages get sent here. + */ + private static final Logger logger = Logger.getLogger("Minecraft.WorldEdit"); + + /** + * The server interface that all server-related API goes through. + */ + private ServerInterface server; + /** + * Main WorldEdit instance. + */ + private WorldEdit controller; + + /** + * Holds the configuration for WorldEdit. + */ + private YAMLConfiguration config; + + /** + * Called on plugin enable. + */ + public void onEnable() { + final String pluginYmlVersion = getDescription().getVersion(); + final String manifestVersion = WorldEdit.getVersion(); + + logger.info("WorldEdit " + pluginYmlVersion + " enabled."); + if (!manifestVersion.equalsIgnoreCase(pluginYmlVersion)) { + WorldEdit.setVersion(manifestVersion + " (" + pluginYmlVersion + ")"); + } + + // Make the data folders that WorldEdit uses + getDataFolder().mkdirs(); + + // Create the default configuration file + createDefaultConfiguration("config.yml"); + + // Set up configuration and such, including the permissions + // resolver + config = new YAMLConfiguration(new YAMLProcessor(new File(getDataFolder(), "config.yml"), true), logger); + + // Load the configuration + loadConfiguration(); + + // Setup interfaces + server = new SpoutServerInterface(this, getGame()); + controller = new WorldEdit(server, config); + + // Now we can register events! + registerEvents(); + + getGame().getScheduler().scheduleAsyncRepeatingTask(this, + new SessionTimer(controller, getGame()), 120, 120); + } + + /** + * Called on plugin disable. + */ + public void onDisable() { + for (Player player : getGame().getOnlinePlayers()) { + LocalPlayer lPlayer = wrapPlayer(player); + if (controller.getSession(lPlayer).hasCUISupport()) { + lPlayer.dispatchCUIHandshake(); + } + } + controller.clearSessions(); + config.unload(); + getGame().getScheduler().cancelTasks(this); + } + + /** + * Loads and reloads all configuration. + */ + protected void loadConfiguration() { + config.unload(); + config.load(); + } + + /** + * Register the events used by WorldEdit. + */ + protected void registerEvents() { + getGame().getEventManager().registerEvents(new WorldEditPlayerListener(this), this); + } + + /** + * Create a default configuration file from the .jar. + * + * @param name + */ + protected void createDefaultConfiguration(String name) { + File actual = new File(getDataFolder(), name); + if (!actual.exists()) { + InputStream input = + null; + try { + JarFile file = new JarFile(getFile()); + ZipEntry copy = file.getEntry("defaults/" + name); + if (copy == null) throw new FileNotFoundException(); + input = file.getInputStream(copy); + } catch (IOException e) { + logger.severe(getDescription().getName() + ": Unable to read default configuration: " + name); + } + if (input != null) { + FileOutputStream output = null; + + try { + output = new FileOutputStream(actual); + byte[] buf = new byte[8192]; + int length = 0; + while ((length = input.read(buf)) > 0) { + output.write(buf, 0, length); + } + + logger.info(getDescription().getName() + + ": Default configuration file written: " + name); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (input != null) { + input.close(); + } + } catch (IOException e) {} + + try { + if (output != null) { + output.close(); + } + } catch (IOException e) {} + } + } + } + } + + /** + * Gets the session for the player. + * + * @param player + * @return + */ + public LocalSession getSession(Player player) { + return controller.getSession(wrapPlayer(player)); + } + + /** + * Gets the session for the player. + * + * @param player + * @return + */ + public EditSession createEditSession(Player player) { + LocalPlayer wePlayer = wrapPlayer(player); + LocalSession session = controller.getSession(wePlayer); + BlockBag blockBag = session.getBlockBag(wePlayer); + + EditSession editSession = + new EditSession(wePlayer.getWorld(), session.getBlockChangeLimit(), blockBag); + editSession.enableQueue(); + + return editSession; + } + + /** + * Remember an edit session. + * + * @param player + * @param editSession + */ + public void remember(Player player, EditSession editSession) { + LocalPlayer wePlayer = wrapPlayer(player); + LocalSession session = controller.getSession(wePlayer); + + session.remember(editSession); + editSession.flushQueue(); + + controller.flushBlockBag(wePlayer, editSession); + } + + /** + * Wrap an operation into an EditSession. + * + * @param player + * @param op + * @throws Throwable + */ + public void perform(Player player, WorldEditOperation op) + throws Throwable { + LocalPlayer wePlayer = wrapPlayer(player); + LocalSession session = controller.getSession(wePlayer); + + EditSession editSession = createEditSession(player); + try { + op.run(session, wePlayer, editSession); + } finally { + remember(player, editSession); + } + } + + /** + * Returns the configuration used by WorldEdit. + * + * @return + */ + public YAMLConfiguration getLocalConfiguration() { + return config; + } + + /** + * Used to wrap a Bukkit Player as a LocalPlayer. + * + * @param player + * @return + */ + public SpoutPlayer wrapPlayer(Player player) { + return new SpoutPlayer(this, this.server, player); + } + + public LocalPlayer wrapCommandSender(CommandSource sender) { + if (sender instanceof Player) { + return wrapPlayer((Player) sender); + } + + return new SpoutCommandSender(this, this.server, sender); + } + + /** + * Get the server interface. + * + * @return + */ + public ServerInterface getServerInterface() { + return server; + } + + /** + * Get WorldEdit. + * + * @return + */ + public WorldEdit getWorldEdit() { + return controller; + } + + /** + * Gets the region selection for the player. + * + * @param player + * @return the selection or null if there was none + */ + public Selection getSelection(Player player) { + if (player == null) { + throw new IllegalArgumentException("Null player not allowed"); + } + if (!player.isOnline()) { + throw new IllegalArgumentException("Offline player not allowed"); + } + + LocalSession session = controller.getSession(wrapPlayer(player)); + RegionSelector selector = session.getRegionSelector(SpoutUtil.getLocalWorld(player.getEntity().getTransform().getPosition().getWorld())); + + try { + Region region = selector.getRegion(); + World world = ((SpoutWorld) session.getSelectionWorld()).getWorld(); + + if (region instanceof CuboidRegion) { + return new CuboidSelection(world, selector, (CuboidRegion) region); + } else if (region instanceof Polygonal2DRegion) { + return new Polygonal2DSelection(world, selector, (Polygonal2DRegion) region); + } else { + return null; + } + } catch (IncompleteRegionException e) { + return null; + } + } + + /** + * Sets the region selection for a player. + * + * @param player + * @param selection + */ + public void setSelection(Player player, Selection selection) { + if (player == null) { + throw new IllegalArgumentException("Null player not allowed"); + } + if (!player.isOnline()) { + throw new IllegalArgumentException("Offline player not allowed"); + } + if (selection == null) { + throw new IllegalArgumentException("Null selection not allowed"); + } + + LocalSession session = controller.getSession(wrapPlayer(player)); + RegionSelector sel = selection.getRegionSelector(); + session.setRegionSelector(SpoutUtil.getLocalWorld(player.getEntity().getTransform().getPosition().getWorld()), sel); + session.dispatchCUISelection(wrapPlayer(player)); + } + + @Override + public String getName() { + return getDescription().getName(); + } +} diff --git a/src/main/java/com/sk89q/worldedit/spout/selections/CuboidSelection.java b/src/main/java/com/sk89q/worldedit/spout/selections/CuboidSelection.java new file mode 100644 index 000000000..a389d524c --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/spout/selections/CuboidSelection.java @@ -0,0 +1,70 @@ +/* + * WorldEdit + * Copyright (C) 2012 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// $Id$ + +package com.sk89q.worldedit.spout.selections; + +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.spout.SpoutUtil; +import com.sk89q.worldedit.regions.CuboidRegion; +import com.sk89q.worldedit.regions.CuboidRegionSelector; +import com.sk89q.worldedit.regions.RegionSelector; +import org.getspout.api.geo.World; +import org.getspout.api.geo.discrete.Point; + +public class CuboidSelection extends RegionSelection { + + protected CuboidRegion cuboid; + + public CuboidSelection(World world, Point pt1, Point pt2) { + this(world, SpoutUtil.toVector(pt1), SpoutUtil.toVector(pt2)); + } + + public CuboidSelection(World world, Vector pt1, Vector pt2) { + super(world); + + // Validate input + if (pt1 == null) { + throw new IllegalArgumentException("Null point 1 not permitted"); + } + + if (pt2 == null) { + throw new IllegalArgumentException("Null point 2 not permitted"); + } + + // Create new selector + CuboidRegionSelector sel = new CuboidRegionSelector(SpoutUtil.getLocalWorld(world)); + + // set up selector + sel.selectPrimary(pt1); + sel.selectSecondary(pt2); + + // set up CuboidSelection + cuboid = sel.getIncompleteRegion(); + + // set up RegionSelection + setRegionSelector(sel); + setRegion(cuboid); + } + + public CuboidSelection(World world, RegionSelector sel, CuboidRegion region) { + super(world, sel, region); + this.cuboid = region; + } +} diff --git a/src/main/java/com/sk89q/worldedit/spout/selections/Polygonal2DSelection.java b/src/main/java/com/sk89q/worldedit/spout/selections/Polygonal2DSelection.java new file mode 100644 index 000000000..f56e4394c --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/spout/selections/Polygonal2DSelection.java @@ -0,0 +1,66 @@ +/* + * WorldEdit + * Copyright (C) 2012 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// $Id$ + + +package com.sk89q.worldedit.spout.selections; + +import com.sk89q.worldedit.BlockVector2D; +import com.sk89q.worldedit.LocalWorld; +import com.sk89q.worldedit.regions.Polygonal2DRegion; +import com.sk89q.worldedit.regions.Polygonal2DRegionSelector; +import com.sk89q.worldedit.regions.RegionSelector; +import com.sk89q.worldedit.spout.SpoutUtil; +import org.getspout.api.geo.World; + +import java.util.Collections; +import java.util.List; + +public class Polygonal2DSelection extends RegionSelection { + + protected Polygonal2DRegion poly2d; + + public Polygonal2DSelection(World world, RegionSelector sel, Polygonal2DRegion region) { + super(world, sel, region); + this.poly2d = region; + } + + public Polygonal2DSelection(World world, List points, int minY, int maxY) { + super(world); + LocalWorld lWorld = SpoutUtil.getLocalWorld(world); + + // Validate input + minY = Math.min(Math.max(0, minY), world.getHeight()); + maxY = Math.min(Math.max(0, maxY), world.getHeight()); + + // Create and set up new selector + Polygonal2DRegionSelector sel = new Polygonal2DRegionSelector(lWorld, points, minY, maxY); + + // set up CuboidSelection + poly2d = sel.getIncompleteRegion(); + + // set up RegionSelection + setRegionSelector(sel); + setRegion(poly2d); + } + + public List getNativePoints() { + return Collections.unmodifiableList(poly2d.getPoints()); + } +} diff --git a/src/main/java/com/sk89q/worldedit/spout/selections/RegionSelection.java b/src/main/java/com/sk89q/worldedit/spout/selections/RegionSelection.java new file mode 100644 index 000000000..c0b39f313 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/spout/selections/RegionSelection.java @@ -0,0 +1,107 @@ +/* + * WorldEdit + * Copyright (C) 2012 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// $Id$ + + +package com.sk89q.worldedit.spout.selections; + +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.regions.RegionSelector; +import com.sk89q.worldedit.spout.SpoutUtil; +import org.getspout.api.geo.World; +import org.getspout.api.geo.discrete.Point; + +public abstract class RegionSelection implements Selection { + + private World world; + private RegionSelector selector; + private Region region; + + public RegionSelection(World world) { + this.world = world; + } + + public RegionSelection(World world, RegionSelector selector, Region region) { + this.world = world; + this.region = region; + this.selector = selector; + } + + protected Region getRegion() { + return region; + } + + protected void setRegion(Region region) { + this.region = region; + } + + public RegionSelector getRegionSelector() { + return selector; + } + + protected void setRegionSelector(RegionSelector selector) { + this.selector = selector; + } + + public Point getMinimumPoint() { + return SpoutUtil.toPoint(world, region.getMinimumPoint()); + } + + public Vector getNativeMinimumPoint() { + return region.getMinimumPoint(); + } + + public Point getMaximumPoint() { + return SpoutUtil.toPoint(world, region.getMaximumPoint()); + } + + public Vector getNativeMaximumPoint() { + return region.getMaximumPoint(); + } + + public World getWorld() { + return world; + } + + public int getArea() { + return region.getArea(); + } + + public int getWidth() { + return region.getWidth(); + } + + public int getHeight() { + return region.getHeight(); + } + + public int getLength() { + return region.getLength(); + } + + public boolean contains(Point pt) { + if (!pt.getWorld().equals(world)) { + return false; + } + + return region.contains(SpoutUtil.toVector(pt)); + } + +} diff --git a/src/main/java/com/sk89q/worldedit/spout/selections/Selection.java b/src/main/java/com/sk89q/worldedit/spout/selections/Selection.java new file mode 100644 index 000000000..5695f64da --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/spout/selections/Selection.java @@ -0,0 +1,107 @@ +/* + * WorldEdit + * Copyright (C) 2012 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// $Id$ + + +package com.sk89q.worldedit.spout.selections; + +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.regions.RegionSelector; +import org.getspout.api.geo.World; +import org.getspout.api.geo.discrete.Point; + +public interface Selection { + /** + * Get the lower point of a region. + * + * @return min. point + */ + public Point getMinimumPoint(); + + /** + * Get the lower point of a region. + * + * @return min. point + */ + public Vector getNativeMinimumPoint(); + + /** + * Get the upper point of a region. + * + * @return max. point + */ + public Point getMaximumPoint(); + + /** + * Get the upper point of a region. + * + * @return max. point + */ + public Vector getNativeMaximumPoint(); + + /** + * Get the region selector. This is for internal use. + * + * @return + */ + public RegionSelector getRegionSelector(); + + /** + * Get the world. + * + * @return + */ + public World getWorld(); + + /** + * Get the number of blocks in the region. + * + * @return number of blocks + */ + public int getArea(); + + /** + * Get X-size. + * + * @return width + */ + public int getWidth(); + + /** + * Get Y-size. + * + * @return height + */ + public int getHeight(); + + /** + * Get Z-size. + * + * @return length + */ + public int getLength(); + + /** + * Returns true based on whether the region contains the point, + * + * @param pt + * @return + */ + public boolean contains(Point pt); +} diff --git a/src/main/resources/spoutplugin.yml b/src/main/resources/spoutplugin.yml new file mode 100644 index 000000000..69b5d3f79 --- /dev/null +++ b/src/main/resources/spoutplugin.yml @@ -0,0 +1,7 @@ +name: WorldEdit +main: com.sk89q.worldedit.spout.WorldEditPlugin +version: ${project.version} +platform: BOTH + +# Permissions aren't here. Read http://wiki.sk89q.com/wiki/WEPIF/DinnerPerms +# for how WorldEdit permissions actually work.