diff --git a/README b/README index 5875d6b..7b893e3 100644 --- a/README +++ b/README @@ -1,185 +1,192 @@ -============= - Description -============= -This is a port of the Stargate plugin from hMod. -Create gates that allow for instant-teleportation between large distances. Gates can be always-open, or triggered, they can be hidden, or accessible to everybody, they can share a network, or they can be split into clusters. -This port will import your existing locations.dat file from the hMod Stargate plugin, as well as any custom .gate files you had! -iConomy support added back in, only costs are create, destroy and use. No permission bypasses. - -This version of Stargate is still heavily under development. There are going to be issues for a while yet. - -============= -Known Issues -============= - - There are many bugs with portal material not showing properly. This is a bug I can not track down, and have no fix for at the moment. - -============= - Permissions -============= - - stargate.use - Allow this player/group to use stargates. - - stargate.create - Allow this player/group to create new stargates. - - stargate.create.personal - Allow this player/group to create new stargates on a network defined as their name. - - stargate.destroy - Allow this player/group to destroy existing stargates. (Deprecated) - - stargate.destroy.all - Allow this player/group to destroy any existing stargate (Replaces stargate.destroy) - - stargate.destroy.owner - Allow this player/group to destroy any stargate that they are the owner of. - - stargate.hidden - Allow this player/group to see all hidden stargates. - - stargate.private - Allow this player/group to use all private stargates. - - stargate.free - This player/group is not charged to use gates even if the gate has a cost. - -============= -Instructions -============= -Building a gate: - OO - O O - These are Obsidian blocks. You need 10. - O O - Place a sign on either of these two blocks of Obsidian. - O O - OO - - Type a name on the first line on the sign, it must be less than 12 characters long. - - Type a set destination name on the second line if desired. - - Type a network name on the third line if desired. - - Type any options on the 4th line if desired. - -Sign Layout: - - Line 1: Gate Name (Max 12 characters) - - Line 2: Destination Name [Optional] (Max 12 characters, used for fixed-gates only) - - Line 3: Network name [Optional] (Max 12 characters) - - Line 4: Options [Optional] ('A' for always-on fixed gate, 'H' for hidden networked gate) - -Using a gate: - - Right click the sign to choose a destination. - - Right/left click the button to open up a portal. - - Step through. - -Fixed gates: - - Fixed gates go to only one set destination. - - Fixed gates can be linked to other fixed gates, or normal gates. A normal gate cannot open a portal to a fixed gate however. - - To create a fixed gate, specify a destination on the second line of the stargate sign. - - Set the 4th line of the stargate sign to "A" to enable an always-open fixed gate. - -Gate networks: - - Gates are all part of a network, by default this is "central". - - You can specify (and create) your own network on the third line of the sign when making a new gate. - - Gates on one network will not see gates on the second network, and vice versa. - -Hidden Gates: - - Hidden gates are like normal gates, but only show on the destination list of other gates under certain conditions. - - A hidden gate is only visible to the creator of the gate, or somebody with the stargate.hidden permission. - - Set the 4th line of the stargate sign to "H" to make it a hidden gate. - -============== -Configuration -============== -default-gate-network - The default gate network -not-selected-message - The message when no destination is selected -portal-destroy-message - The message when a gate is destroyed -portal-create-message - The message when a gate is created -not-owner-message - The message when you aren't allowed to push the gate button -other-side-blocked-message - The message when the gate you're dialing is open -teleport-message - The message when you are teleported -portal-folder - The folder your portal databases are saved in -gate-folder - The folder containing your .gate files -destroyexplosion - Whether to destroy a stargate with explosions, or stop an explosion if it contains a gates controls. -useiconomy - Whether or not to use iConomy -createcost - The cost to create a stargate -destroycost - The cost to destroy a stargate (Can be negative for a "refund" -usecost - The cost to use a stargate -not-enough-money-message - The message displayed if a player lacks money to do something - -============= - Changes -============= -[Version 0.3.4] - - Added 'stargate.free' permission - - Added iConomy cost into .gate files -[Version 0.3.3] - - Moved sign update into a schedule event, should fix signs -[Version 0.3.2] - - Updated to latest RB - - Implemented proper vehicle handling - - Added iConomy to vehicle handling - - Can now set cost to go to creator on use -[Version 0.3.1] - - Changed version numbering. - - Changed how plugins are hooked into. -[Version 0.30] - - Fixed a bug in iConomy checking. -[Version 0.29] - - Added iConomy support. Currently only works with iConomy 4.4 until Niji fixes 4.5 - - Thanks @Jonbas for the base iConomy implementation -[Version 0.28] - - Fixed an issue with removing stargates during load -[Version 0.27] - - Fixed portal count on load -[Version 0.26] - - Added stargate.create.personal for personal stargate networks - - Fixed a bug with destroying stargates by removing sign/button -[Version 0.25] - - Fixed a bug with worlds in subfolders - - Fixed gates being destroyed with explosions - - Added stargate.destroy.owner -[Version 0.24] - - Fixed a loading bug in which invalid gates caused file truncation -[Version 0.23] - - Added a check to make sure "nethergate.gate" exists, otherwise create it -[Version 0.22] - - Fixed multi-world stargates causing an NPE -[Version 0.21] - - Code cleanup - - Added a few more errors when a gate can't be loaded - - Hopefully fixed path issue on some Linux installs -[Version 0.20] - - Fixed the bug SIGN_CHANGE exception when using plugins such as Lockette -[Version 0.19] - - Set button facing on new gates, fixes weirdass button glitch - - Beginning of very buggy multi-world support -[Version 0.18] - - Small permissions handling update. -[Version 0.17] - - Core GM support removed, depends on FakePermissions if you use GM. -[Version 0.16] - - Fixed Permissions, will work with GroupManager, Permissions 2.0, or Permissions 2.1 - - Left-clicking to activate a stargate works again -[Version 0.15] - - Built against b424jnks -- As such nothing lower is supported at the moment. - - Moved gate destruction code to onBlockBreak since onBlockDamage no longer handles breaking blocks. - - Removed long constructor. -[Version 0.14] - - Fixed infinite loop in fixed gates. - - Fixed gate destination will not open when dialed into. -[Version 0.13] - - Fixed gates no longer show in destination list. -[Version 0.12] - - Implemented fixed destination block using * in .gate file. This is the recommended method of doing an exit point for custom gates, as the automatic method doesn't work in a lot of cases. - - Split networks up in memory, can now use same name in different networks. As a result, fixed gates must now specify a network. - - Added the ability to have a private gate, which only you can activate. Use the 'P' option to create. - - Fixed but not AlwaysOn gates now open the destination gate. - - Fixed gates now show their network. Existing fixed gates are added to the default network (Sorry! It had to be done) -[Version 0.11] - - Fuuuu- Some code got undid and broke everything. Fixed. -[Version 0.10] - - Hopefully fixed the "No position found" bug. - - If dest > origin, any blocks past origin.size will drop you at dest[0] - - Switched to scheduler instead of our own thread for closing gates and deactivating signs - - No longer depend on Permissions, use it as an option. isOp() used as defaults. -[Version 0.09] - - Gates can now be any shape -[Version 0.08] - - Gates can now consist of any material. - - You can left or right click the button to open a gate - - Gates are now initialized on sign placement, not more right clicking! -[Version 0.07] - - Fixed where the default gate is saved to. -[Version 0.06] - - Forgot to make gates load from new location, oops -[Version 0.05] - - Moved Stargate files into the plugins/Stargate/ folder - - Added migration code so old gates/portals are ported to new folder structure - - Create default config.yml if it doesn't exist - - Fixed removing a gate, it is now completely removed -[Version 0.04] - - Updated to multi-world Bukkit -[Version 0.03] - - Changed package to net.TheDgtl.* - - Everything now uses Blox instead of Block objects +============= + Description +============= +This is a port of the Stargate plugin from hMod. +Create gates that allow for instant-teleportation between large distances. Gates can be always-open, or triggered, they can be hidden, or accessible to everybody, they can share a network, or they can be split into clusters. +This port will import your existing locations.dat file from the hMod Stargate plugin! +iConomy support added back in, only costs are create, destroy and use. + +============= +Known Issues +============= + - There are many bugs with portal material not showing properly. This is a bug I can not track down, and have no fix for at the moment. + +============= + Permissions +============= + - stargate.use - Allow this player/group to use stargates. + - stargate.create - Allow this player/group to create new stargates. + - stargate.create.personal - Allow this player/group to create new stargates on a network defined as their name. + - stargate.destroy - Allow this player/group to destroy existing stargates. (Deprecated) + - stargate.destroy.all - Allow this player/group to destroy any existing stargate (Replaces stargate.destroy) + - stargate.destroy.owner - Allow this player/group to destroy any stargate that they are the owner of. + - stargate.hidden - Allow this player/group to see all hidden stargates. + - stargate.private - Allow this player/group to use all private stargates. + - stargate.free - This player/group is not charged to use gates even if the gate has a cost. + - stargate.world.{worldname} - Allow this user/group access to gates on the world {worldname} + - stargate.network.{networkname} - Allow this user/group access to the network {networkname} + +============= +Instructions +============= +Building a gate: + OO + O O - These are Obsidian blocks. You need 10. + O O - Place a sign on either of these two blocks of Obsidian. + O O + OO + +Sign Layout: + - Line 1: Gate Name (Max 12 characters) + - Line 2: Destination Name [Optional] (Max 12 characters, used for fixed-gates only) + - Line 3: Network name [Optional] (Max 12 characters) + - Line 4: Options [Optional] ('A' for always-on fixed gate, 'H' for hidden networked gate, 'P' for a private gate, 'F' for a free gate) + +Options: +The options are the single letter, not the word. So to make a private hidden gate, your 4th line would be 'PH'. + +Using a gate: + - Right click the sign to choose a destination. + - Right click the button to open up a portal. + - Step through. + +Fixed gates: + - Fixed gates go to only one set destination. + - Fixed gates can be linked to other fixed gates, or normal gates. A normal gate cannot open a portal to a fixed gate however. + - To create a fixed gate, specify a destination on the second line of the stargate sign. + - Set the 4th line of the stargate sign to "A" to enable an always-open fixed gate. + +Gate networks: + - Gates are all part of a network, by default this is "central". + - You can specify (and create) your own network on the third line of the sign when making a new gate. + - Gates on one network will not see gates on the second network, and vice versa. + - Gates on different worlds, but in the same network, will see eachother. + +Hidden Gates: + - Hidden gates are like normal gates, but only show on the destination list of other gates under certain conditions. + - A hidden gate is only visible to the creator of the gate, or somebody with the stargate.hidden permission. + - Set the 4th line of the stargate sign to 'H' to make it a hidden gate. + +============== +Configuration +============== +default-gate-network - The default gate network +not-selected-message - The message when no destination is selected +portal-destroy-message - The message when a gate is destroyed +portal-create-message - The message when a gate is created +not-owner-message - The message when you aren't allowed to push the gate button +other-side-blocked-message - The message when the gate you're dialing is open +teleport-message - The message when you are teleported +portal-folder - The folder your portal databases are saved in +gate-folder - The folder containing your .gate files +destroyexplosion - Whether to destroy a stargate with explosions, or stop an explosion if it contains a gates controls. +useiconomy - Whether or not to use iConomy +createcost - The cost to create a stargate +destroycost - The cost to destroy a stargate (Can be negative for a "refund" +usecost - The cost to use a stargate +not-enough-money-message - The message displayed if a player lacks money to do something +networkfilter - Whether or not to disallow users access to a network if they don't have the 'stargate.network.{networkname}' permission. +worldfilter - Whether or not to disallow users access to a network if they don't have the 'stargate.world.{worldname}' permission. + +============= + Changes +============= +[Version 0.3.5] + - Added 'stargate.world.*' permissions + - Added 'stargate.network.*' permissions + - Added 'networkfilter' config option + - Added 'worldfilter' config option +[Version 0.3.4] + - Added 'stargate.free' permission + - Added iConomy cost into .gate files +[Version 0.3.3] + - Moved sign update into a schedule event, should fix signs +[Version 0.3.2] + - Updated to latest RB + - Implemented proper vehicle handling + - Added iConomy to vehicle handling + - Can now set cost to go to creator on use +[Version 0.3.1] + - Changed version numbering. + - Changed how plugins are hooked into. +[Version 0.30] + - Fixed a bug in iConomy checking. +[Version 0.29] + - Added iConomy support. Currently only works with iConomy 4.4 until Niji fixes 4.5 + - Thanks @Jonbas for the base iConomy implementation +[Version 0.28] + - Fixed an issue with removing stargates during load +[Version 0.27] + - Fixed portal count on load +[Version 0.26] + - Added stargate.create.personal for personal stargate networks + - Fixed a bug with destroying stargates by removing sign/button +[Version 0.25] + - Fixed a bug with worlds in subfolders + - Fixed gates being destroyed with explosions + - Added stargate.destroy.owner +[Version 0.24] + - Fixed a loading bug in which invalid gates caused file truncation +[Version 0.23] + - Added a check to make sure "nethergate.gate" exists, otherwise create it +[Version 0.22] + - Fixed multi-world stargates causing an NPE +[Version 0.21] + - Code cleanup + - Added a few more errors when a gate can't be loaded + - Hopefully fixed path issue on some Linux installs +[Version 0.20] + - Fixed the bug SIGN_CHANGE exception when using plugins such as Lockette +[Version 0.19] + - Set button facing on new gates, fixes weirdass button glitch + - Beginning of very buggy multi-world support +[Version 0.18] + - Small permissions handling update. +[Version 0.17] + - Core GM support removed, depends on FakePermissions if you use GM. +[Version 0.16] + - Fixed Permissions, will work with GroupManager, Permissions 2.0, or Permissions 2.1 + - Left-clicking to activate a stargate works again +[Version 0.15] + - Built against b424jnks -- As such nothing lower is supported at the moment. + - Moved gate destruction code to onBlockBreak since onBlockDamage no longer handles breaking blocks. + - Removed long constructor. +[Version 0.14] + - Fixed infinite loop in fixed gates. + - Fixed gate destination will not open when dialed into. +[Version 0.13] + - Fixed gates no longer show in destination list. +[Version 0.12] + - Implemented fixed destination block using * in .gate file. This is the recommended method of doing an exit point for custom gates, as the automatic method doesn't work in a lot of cases. + - Split networks up in memory, can now use same name in different networks. As a result, fixed gates must now specify a network. + - Added the ability to have a private gate, which only you can activate. Use the 'P' option to create. + - Fixed but not AlwaysOn gates now open the destination gate. + - Fixed gates now show their network. Existing fixed gates are added to the default network (Sorry! It had to be done) +[Version 0.11] + - Fuuuu- Some code got undid and broke everything. Fixed. +[Version 0.10] + - Hopefully fixed the "No position found" bug. + - If dest > origin, any blocks past origin.size will drop you at dest[0] + - Switched to scheduler instead of our own thread for closing gates and deactivating signs + - No longer depend on Permissions, use it as an option. isOp() used as defaults. +[Version 0.09] + - Gates can now be any shape +[Version 0.08] + - Gates can now consist of any material. + - You can left or right click the button to open a gate + - Gates are now initialized on sign placement, not more right clicking! +[Version 0.07] + - Fixed where the default gate is saved to. +[Version 0.06] + - Forgot to make gates load from new location, oops +[Version 0.05] + - Moved Stargate files into the plugins/Stargate/ folder + - Added migration code so old gates/portals are ported to new folder structure + - Create default config.yml if it doesn't exist + - Fixed removing a gate, it is now completely removed +[Version 0.04] + - Updated to multi-world Bukkit +[Version 0.03] + - Changed package to net.TheDgtl.* + - Everything now uses Blox instead of Block objects - Started on vehicle code, but it's still buggy \ No newline at end of file diff --git a/src/net/TheDgtl/Stargate/Portal.java b/src/net/TheDgtl/Stargate/Portal.java index 5907dcf..e485a9c 100644 --- a/src/net/TheDgtl/Stargate/Portal.java +++ b/src/net/TheDgtl/Stargate/Portal.java @@ -1,888 +1,892 @@ -package net.TheDgtl.Stargate; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Scanner; -import java.util.logging.Level; - -import org.bukkit.ChatColor; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.block.Sign; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Minecart; -import org.bukkit.entity.Player; -import org.bukkit.entity.Vehicle; -import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.material.Button; -import org.bukkit.material.MaterialData; -import org.bukkit.util.Vector; - -/** - * Portal.java - Plug-in for hey0's minecraft mod. - * @author Shaun (sturmeh) - * @author Dinnerbone - */ -public class Portal { - // Variables used to store portal lists - private static final HashMap lookupBlocks = new HashMap(); - private static final HashMap lookupEntrances = new HashMap(); - private static final ArrayList allPortals = new ArrayList(); - private static final HashMap> allPortalsNet = new HashMap>(); - private static final HashMap> lookupNamesNet = new HashMap>(); - - // Gate location block info - private Blox topLeft; - private int modX; - private int modZ; - private float rotX; - // Block references - private SignPost id; - private Blox button; - private Blox[] frame; - private Blox[] entrances; - // Gate information - private String name; - private String destination; - private String network; - private Gate gate; - private String owner = ""; - private boolean hidden = false; - private boolean alwaysOn = false; - private boolean priv = false; - private boolean free = false; - private World world; - // Gate options - private boolean verified; - private boolean fixed; - // In-use information - private Player player; - private Player activePlayer; - private ArrayList destinations = new ArrayList(); - private boolean isOpen = false; - private long openTime; - - private Portal(Blox topLeft, int modX, int modZ, - float rotX, SignPost id, Blox button, - String dest, String name, - boolean verified, String network, Gate gate, - String owner, boolean hidden, boolean alwaysOn, boolean priv, boolean free) { - this.topLeft = topLeft; - this.modX = modX; - this.modZ = modZ; - this.rotX = rotX; - this.id = id; - this.destination = dest; - this.button = button; - this.verified = verified; - this.fixed = dest.length() > 0; - this.network = network; - this.name = name; - this.gate = gate; - this.owner = owner; - this.hidden = hidden; - this.alwaysOn = alwaysOn; - this.priv = priv; - this.free = free; - this.world = topLeft.getWorld(); - - if (this.alwaysOn && !this.fixed) { - this.alwaysOn = false; - Stargate.log.log(Level.WARNING, "Can not create a non-fixed always-on gate."); - } - - this.register(); - if (verified) { - this.drawSign(); - } - } - - public boolean isOpen() { - return isOpen || isAlwaysOn(); - } - - public boolean isAlwaysOn() { - return alwaysOn && isFixed(); - } - - public boolean isHidden() { - return hidden; - } - - public boolean isPrivate() { - return priv; - } - - public boolean isFree() { - return free; - } - - public boolean open(boolean force) { - return open(null, force); - } - - public boolean open(Player openFor, boolean force) { - if (isOpen() && !force) return false; - - world.loadChunk(world.getChunkAt(topLeft.getBlock())); - - for (Blox inside : getEntrances()) { - inside.setType(gate.getPortalBlockOpen()); - } - - isOpen = true; - openTime = System.currentTimeMillis() / 1000; - Stargate.openList.add(this); - Stargate.activeList.remove(this); - // Open remote gate - if (!isAlwaysOn()) { - player = openFor; - - Portal end = getDestination(); - if (end != null && !end.isFixed() && !end.isOpen()) { - end.open(openFor, false); - end.setDestination(this); - if (end.isVerified()) end.drawSign(); - } - } - - return true; - } - - public void close(boolean force) { - if (isAlwaysOn() && !force) return; // Never close an always open gate - - // Close this gate, then the dest gate. - for (Blox inside : getEntrances()) { - inside.setType(gate.getPortalBlockClosed()); - } - - player = null; - isOpen = false; - Stargate.openList.remove(this); - Stargate.activeList.remove(this); - - if (!isAlwaysOn()) { - Portal end = getDestination(); - - if (end != null && end.isOpen()) { - end.deactivate(); // Clear it's destination first. - end.close(false); - } - } - - deactivate(); - } - - public boolean isOpenFor(Player player) { - if ((isAlwaysOn()) || (this.player == null)) { - return true; - } - return (player != null) && (player.getName().equalsIgnoreCase(this.player.getName())); - } - - public boolean isFixed() { - return fixed; - } - - public boolean isPowered() { - RelativeBlockVector[] controls = gate.getControls(); - - for (RelativeBlockVector vector : controls) { - MaterialData mat = getBlockAt(vector).getBlock().getState().getData(); - - if (mat instanceof Button && ((Button)mat).isPowered()) - return true; - } - - return false; - } - - public void teleport(Player player, Portal origin, PlayerMoveEvent event) { - Location traveller = player.getLocation(); - Location exit = getExit(traveller, origin); - - exit.setYaw(origin.getRotation() - traveller.getYaw() + this.getRotation() + 180); - - // Change "from" so we don't get hack warnings. Cancel player move event. - event.setFrom(exit); - player.teleport(exit); - event.setCancelled(true); - } - - public void teleport(final Vehicle vehicle, Portal origin) { - Location traveller = new Location(this.world, vehicle.getLocation().getX(), vehicle.getLocation().getY(), vehicle.getLocation().getZ()); - Location exit = getExit(traveller, origin); - - double velocity = vehicle.getVelocity().length(); - - // Stop and teleport - vehicle.setVelocity(new Vector()); - - // Get new velocity - final Vector newVelocity = new Vector(); - switch ((int)id.getBlock().getData()) { - case 2: - newVelocity.setZ(-1); - break; - case 3: - newVelocity.setZ(1); - break; - case 4: - newVelocity.setX(-1); - break; - case 5: - newVelocity.setX(1); - break; - } - newVelocity.multiply(velocity); - - final Entity passenger = vehicle.getPassenger(); - vehicle.eject(); - vehicle.remove(); - final Minecart mc = exit.getWorld().spawnMinecart(exit); - if (passenger != null) { - passenger.teleport(exit); - Stargate.server.getScheduler().scheduleSyncDelayedTask(Stargate.stargate, new Runnable() { - public void run() { - mc.setPassenger(passenger); - mc.setVelocity(newVelocity); - } - }, 1); - } else { - mc.setVelocity(newVelocity); - } - } - - public Location getExit(Location traveller, Portal origin) { - Location loc = null; - // Check if the gate has an exit block - if (gate.getExit() != null) { - Blox exit = getBlockAt(gate.getExit()); - loc = exit.modRelativeLoc(0D, 0D, 1D, traveller.getYaw(), traveller.getPitch(), modX, 1, modZ); - } else { - Stargate.log.log(Level.WARNING, "[Stargate] Missing destination point in .gate file " + gate.getFilename()); - } - if (loc != null) { - Block block = world.getBlockAt(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); - - if (block.getType() == Material.STEP) { - loc.setY(loc.getY() + 0.5); - } - - loc.setPitch(traveller.getPitch()); - return loc; - } - return traveller; - } - - public float getRotation() { - return rotX; - } - - public void setName(String name) { - this.name = filterName(name); - - drawSign(); - } - - public String getName() { - return name; - } - - public void setDestination(Portal destination) { - setDestination(destination.getName()); - } - - public void setDestination(String destination) { - this.destination = destination; - } - - public Portal getDestination() { - return Portal.getByName(destination, getNetwork()); - } - - public String getDestinationName() { - return destination; - } - - public boolean isChunkLoaded() { - return topLeft.getWorld().isChunkLoaded(topLeft.getBlock().getChunk()); - } - - public void loadChunk() { - topLeft.getWorld().loadChunk(topLeft.getBlock().getChunk()); - } - - public boolean isVerified() { - for (RelativeBlockVector control : gate.getControls()) - verified = verified || getBlockAt(control).getBlock().getTypeId() == gate.getControlBlock(); - return verified; - } - - public boolean wasVerified() { - return verified; - } - - public boolean checkIntegrity() { - return gate.matches(topLeft, modX, modZ); - } - - public Gate getGate() { - return gate; - } - - public String getOwner() { - return owner; - } - - public void activate(Player player) { - destinations.clear(); - destination = ""; - drawSign(); - Stargate.activeList.add(this); - activePlayer = player; - for (String dest : allPortalsNet.get(getNetwork().toLowerCase())) { - Portal portal = getByName(dest, getNetwork()); - // Not fixed, not this portal, and visible to this player. - if ( (!portal.isFixed()) && - (!dest.equalsIgnoreCase(getName())) && // Not this portal - (!portal.isHidden() || Stargate.hasPerm(player, "stargate.hidden", player.isOp()) || portal.getOwner().equals(player.getName())) - ) { - destinations.add(portal.getName()); - } - } - } - - public void deactivate() { - Stargate.activeList.remove(this); - if (isFixed()) { - return; - } - destinations.clear(); - destination = ""; - activePlayer = null; - drawSign(); - } - - public boolean isActive() { - return fixed || (destinations.size() > 0); - } - - public Player getActivePlayer() { - return activePlayer; - } - - public String getNetwork() { - return network; - } - - public long getOpenTime() { - return openTime; - } - - public void cycleDestination(Player player) { - if (!isActive() || getActivePlayer() != player) { - activate(player); - } - - if (destinations.size() > 0) { - int index = destinations.indexOf(destination); - if (++index >= destinations.size()) { - index = 0; - } - destination = destinations.get(index); - } - openTime = System.currentTimeMillis() / 1000; - drawSign(); - } - - public final void drawSign() { - id.setText(0, "--" + name + "--"); - int max = destinations.size() - 1; - int done = 0; - - if (!isActive()) { - id.setText(++done, "Right click to"); - id.setText(++done, "use the gate"); - id.setText(++done, " (" + network + ") "); - } else { - if (isFixed()) { - id.setText(++done, "To: " + destination); - id.setText(++done, " (" + network + ") "); - } else { - int index = destinations.indexOf(destination); - - if ((index == max) && (max > 1) && (++done <= 3)) { - id.setText(done, destinations.get(index - 2)); - } - if ((index > 0) && (++done <= 3)) { - id.setText(done, destinations.get(index - 1)); - } - if (++done <= 3) { - id.setText(done, " >" + destination + "< "); - } - if ((max >= index + 1) && (++done <= 3)) { - id.setText(done, destinations.get(index + 1)); - } - if ((max >= index + 2) && (++done <= 3)) { - id.setText(done, destinations.get(index + 2)); - } - } - } - - for (done++; done <= 3; done++) { - id.setText(done, ""); - } - - id.update(); - } - - public Blox[] getEntrances() { - if (entrances == null) { - RelativeBlockVector[] space = gate.getEntrances(); - entrances = new Blox[space.length]; - int i = 0; - - for (RelativeBlockVector vector : space) { - entrances[i++] = getBlockAt(vector); - } - } - return entrances; - } - - public Blox[] getFrame() { - if (frame == null) { - RelativeBlockVector[] border = gate.getBorder(); - RelativeBlockVector[] controls = gate.getControls(); - frame = new Blox[border.length + controls.length]; - int i = 0; - - for (RelativeBlockVector vector : border) { - frame[i++] = getBlockAt(vector); - } - - for (RelativeBlockVector vector : controls) { - frame[i++] = getBlockAt(vector); - } - } - - return frame; - } - - public void unregister(boolean removeAll) { - Stargate.log.info("[Stargate] Unregistering gate " + getName()); - close(true); - lookupNamesNet.get(getNetwork().toLowerCase()).remove(getName().toLowerCase()); - - for (Blox block : getFrame()) { - lookupBlocks.remove(block); - } - // Include the sign and button - lookupBlocks.remove(new Blox(id.getBlock())); - if (button != null) { - lookupBlocks.remove(button); - } - - for (Blox entrance : getEntrances()) { - lookupEntrances.remove(entrance); - } - - if (removeAll) - allPortals.remove(this); - - allPortalsNet.get(getNetwork().toLowerCase()).remove(getName().toLowerCase()); - - if (id.getBlock().getType() == Material.WALL_SIGN) { - id.setText(0, getName()); - id.setText(1, ""); - id.setText(2, ""); - id.setText(3, ""); - id.update(); - } - - for (String originName : allPortalsNet.get(getNetwork().toLowerCase())) { - Portal origin = Portal.getByName(originName, getNetwork()); - if ((origin != null) && (origin.isAlwaysOn()) && (origin.getDestinationName().equalsIgnoreCase(getName())) && (origin.isVerified())) { - origin.close(true); - } - } - - saveAllGates(world); - } - - private Blox getBlockAt(RelativeBlockVector vector) { - return topLeft.modRelative(vector.getRight(), vector.getDepth(), vector.getDistance(), modX, 1, modZ); - } - - private void register() { - if (!lookupNamesNet.containsKey(getNetwork().toLowerCase())) - lookupNamesNet.put(getNetwork().toLowerCase(), new HashMap()); - lookupNamesNet.get(getNetwork().toLowerCase()).put(getName().toLowerCase(), this); - - for (Blox block : getFrame()) { - lookupBlocks.put(block, this); - } - // Include the sign and button - lookupBlocks.put(new Blox(id.getBlock()), this); - if (button != null) { - lookupBlocks.put(button, this); - } - - for (Blox entrance : getEntrances()) { - lookupEntrances.put(entrance, this); - } - - allPortals.add(this); - // Check if this network exists - if (!allPortalsNet.containsKey(getNetwork().toLowerCase())) - allPortalsNet.put(getNetwork().toLowerCase(), new ArrayList()); - allPortalsNet.get(getNetwork().toLowerCase()).add(getName().toLowerCase()); - } - - public static Portal createPortal(SignPost id, Player player) { - Block idParent = id.getParent(); - if (idParent == null) return null; - if (Gate.getGatesByControlBlock(idParent).length == 0) return null; - - Blox parent = new Blox(player.getWorld(), idParent.getX(), idParent.getY(), idParent.getZ()); - Blox topleft = null; - String name = filterName(id.getText(0)); - String destName = filterName(id.getText(1)); - String network = filterName(id.getText(2)); - String options = filterName(id.getText(3)); - boolean hidden = (options.indexOf('h') != -1 || options.indexOf('H') != -1); - boolean alwaysOn = (options.indexOf('a') != -1 || options.indexOf('A') != -1); - boolean priv = (options.indexOf('p') != -1 || options.indexOf('P') != -1); - boolean free = (options.indexOf('f') != - 1|| options.indexOf('F') != -1); - - // Check if the user can only create personal gates, set network if so - if (Stargate.hasPerm(player, "stargate.create.personal", false) && - !Stargate.hasPerm(player, "stargate.create", player.isOp()) ) { - network = player.getName(); - if (network.length() > 11) network = network.substring(0, 11); - } - - // Can not create a non-fixed always-on gate. - if (alwaysOn && destName.length() == 0) { - alwaysOn = false; - } - - if ((network.length() < 1) || (network.length() > 11)) { - network = Stargate.getDefaultNetwork(); - } - if ((name.length() < 1) || (name.length() > 11) || (getByName(name, network) != null)) { - return null; - } - - int modX = 0; - int modZ = 0; - float rotX = 0f; - int facing = 0; - - if (idParent.getX() > id.getBlock().getX()) { - modZ -= 1; - rotX = 90f; - facing = 2; - } else if (idParent.getX() < id.getBlock().getX()) { - modZ += 1; - rotX = 270f; - facing = 1; - } else if (idParent.getZ() > id.getBlock().getZ()) { - modX += 1; - rotX = 180f; - facing = 4; - } else if (idParent.getZ() < id.getBlock().getZ()) { - modX -= 1; - rotX = 0f; - facing = 3; - } - - Gate[] possibleGates = Gate.getGatesByControlBlock(idParent); - Gate gate = null; - RelativeBlockVector buttonVector = null; - - for (Gate possibility : possibleGates) { - if ((gate == null) && (buttonVector == null)) { - RelativeBlockVector[] vectors = possibility.getControls(); - RelativeBlockVector otherControl = null; - - for (RelativeBlockVector vector : vectors) { - Blox tl = parent.modRelative(-vector.getRight(), -vector.getDepth(), -vector.getDistance(), modX, 1, modZ); - - if (gate == null) { - if (possibility.matches(tl, modX, modZ)) { - gate = possibility; - topleft = tl; - - if (otherControl != null) { - buttonVector = otherControl; - } - } - } else if (otherControl != null) { - buttonVector = vector; - } - - otherControl = vector; - } - } - } - - if ((gate == null) || (buttonVector == null)) { - return null; - } - - if (iConomyHandler.useiConomy() && !Stargate.hasPerm(player, "stargate.free", player.isOp()) && !iConomyHandler.chargePlayer(player.getName(), null, gate.getCreateCost())) { - if (!iConomyHandler.inFundMsg.isEmpty()) { - player.sendMessage(ChatColor.RED + iConomyHandler.inFundMsg); - } - return null; - } - - Portal portal = null; - - Blox button = null; - // No button on an always-open gate. - if (!alwaysOn) { - button = topleft.modRelative(buttonVector.getRight(), buttonVector.getDepth(), buttonVector.getDistance() + 1, modX, 1, modZ); - button.setType(Material.STONE_BUTTON.getId()); - button.setData(facing); - } - portal = new Portal(topleft, modX, modZ, rotX, id, button, destName, name, true, network, gate, player.getName(), hidden, alwaysOn, priv, free); - - // Open always on gate - if (portal.isAlwaysOn()) { - Portal dest = Portal.getByName(destName, portal.getNetwork()); - if (dest != null) - portal.open(true); - } - - // Open any always on gate pointing at this gate - for (String originName : allPortalsNet.get(portal.getNetwork().toLowerCase())) { - Portal origin = Portal.getByName(originName, portal.getNetwork()); - if (origin != null && origin.isAlwaysOn() && origin.getDestinationName().equalsIgnoreCase(portal.getName()) && origin.isVerified()) - origin.open(true); - } - - saveAllGates(topleft.getWorld()); - - return portal; - } - - public static Portal getByName(String name, String network) { - if (!lookupNamesNet.containsKey(network.toLowerCase())) return null; - return lookupNamesNet.get(network.toLowerCase()).get(name.toLowerCase()); - - } - - public static Portal getByEntrance(Location location) { - return getByEntrance(new Blox(location).getBlock()); - } - - public static Portal getByEntrance(Block block) { - return lookupEntrances.get(new Blox(block)); - } - - public static Portal getByBlock(Block block) { - return lookupBlocks.get(new Blox(block)); - } - - public static void saveAllGates(World world) { - String loc = Stargate.getSaveLocation() + "/" + world.getName() + ".db"; - - try { - BufferedWriter bw = new BufferedWriter(new FileWriter(loc, false)); - - for (Portal portal : allPortals) { - String wName = portal.world.getName(); - if (!wName.equalsIgnoreCase(world.getName())) continue; - StringBuilder builder = new StringBuilder(); - Blox sign = new Blox(portal.id.getBlock()); - Blox button = portal.button; - - builder.append(portal.name); - builder.append(':'); - builder.append(sign.toString()); - builder.append(':'); - builder.append((button != null) ? button.toString() : ""); - builder.append(':'); - builder.append(portal.modX); - builder.append(':'); - builder.append(portal.modZ); - builder.append(':'); - builder.append(portal.rotX); - builder.append(':'); - builder.append(portal.topLeft.toString()); - builder.append(':'); - builder.append(portal.gate.getFilename()); - builder.append(':'); - builder.append(portal.isFixed() ? portal.getDestinationName() : ""); - builder.append(':'); - builder.append(portal.getNetwork()); - builder.append(':'); - builder.append(portal.getOwner()); - builder.append(':'); - builder.append(portal.isHidden()); - builder.append(':'); - builder.append(portal.isAlwaysOn()); - builder.append(':'); - builder.append(portal.isPrivate()); - builder.append(':'); - builder.append(portal.world.getName()); - builder.append(':'); - builder.append(portal.isFree()); - - bw.append(builder.toString()); - bw.newLine(); - } - - bw.close(); - } catch (Exception e) { - Stargate.log.log(Level.SEVERE, "Exception while writing stargates to " + loc + ": " + e); - } - } - - public static void clearGates() { - lookupBlocks.clear(); - lookupNamesNet.clear(); - lookupEntrances.clear(); - allPortals.clear(); - allPortalsNet.clear(); - } - - public static void loadAllGates(World world) { - String location = Stargate.getSaveLocation(); - - File db = new File(location, world.getName() + ".db"); - - if (db.exists()) { - int l = 0; - int portalCount = 0; - try { - Scanner scanner = new Scanner(db); - while (scanner.hasNextLine()) { - l++; - String line = scanner.nextLine().trim(); - if (line.startsWith("#") || line.isEmpty()) { - continue; - } - String[] split = line.split(":"); - if (split.length < 8) { - Stargate.log.info("[Stargate] Invalid line - " + l); - continue; - } - String name = split[0]; - Blox s = new Blox(world, split[1]); - if (!(s.getBlock().getState() instanceof Sign)) { - Stargate.log.info("[Stargate] Invalid sign on line " + l + " [" + s.getBlock() + "]"); - continue; - } - SignPost sign = new SignPost(s); - Blox button = (split[2].length() > 0) ? new Blox(world, split[2]) : null; - int modX = Integer.parseInt(split[3]); - int modZ = Integer.parseInt(split[4]); - float rotX = Float.parseFloat(split[5]); - Blox topLeft = new Blox(world, split[6]); - Gate gate = (split[7].contains(";")) ? Gate.getGateByName("nethergate.gate") : Gate.getGateByName(split[7]); - if (gate == null) { - Stargate.log.info("[Stargate] Invalid gate layout on line " + l + " [" + split[7] + "]"); - continue; - } - - String dest = (split.length > 8) ? split[8] : ""; - String network = (split.length > 9) ? split[9] : Stargate.getDefaultNetwork(); - if (network.isEmpty()) network = Stargate.getDefaultNetwork(); - String owner = (split.length > 10) ? split[10] : ""; - boolean hidden = (split.length > 11) ? split[11].equalsIgnoreCase("true") : false; - boolean alwaysOn = (split.length > 12) ? split[12].equalsIgnoreCase("true") : false; - boolean priv = (split.length > 13) ? split[13].equalsIgnoreCase("true") : false; - boolean free = (split.length > 15) ? split[15].equalsIgnoreCase("true") : false; - - Portal portal = new Portal(topLeft, modX, modZ, rotX, sign, button, dest, name, false, network, gate, owner, hidden, alwaysOn, priv, free); - portal.close(true); - } - scanner.close(); - - // Open any always-on gates. Do this here as it should be more efficient than in the loop. - int OpenCount = 0; - //for (Portal portal : allPortals) { - for (Iterator iter = allPortals.iterator(); iter.hasNext(); ) { - Portal portal = iter.next(); - if (portal == null) continue; - - // Verify portal integrity/register portal - if (!portal.wasVerified()) { - if (!portal.isVerified() || !portal.checkIntegrity()) { - portal.unregister(false); - iter.remove(); - Stargate.log.info("[Stargate] Destroying stargate at " + portal.toString()); - continue; - } else { - portal.drawSign(); - portalCount++; - } - } - - if (!portal.isAlwaysOn()) continue; - - Portal dest = portal.getDestination(); - if (dest != null) { - portal.open(true); - OpenCount++; - } - } - Stargate.log.info("[Stargate] {" + world.getName() + "} Loaded " + portalCount + " stargates with " + OpenCount + " set as always-on"); - } catch (Exception e) { - Stargate.log.log(Level.SEVERE, "Exception while reading stargates from " + db.getName() + ": " + l); - e.printStackTrace(); - } - } else { - Stargate.log.info("[Stargate] {" + world.getName() + "} No stargates for world "); - } - } - - public static void closeAllGates() { - Stargate.log.info("Closing all stargates."); - for (Portal p : allPortals) { - if (p == null) continue; - p.close(true); - } - } - - public static String filterName(String input) { - return input.replaceAll("[\\|:#]", "").trim(); - } - - @Override - public String toString() { - return String.format("Portal [id=%s, network=%s name=%s, type=%s]", id, network, name, gate.getFilename()); - } - - @Override - public int hashCode() { - return getName().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - - Portal portal = (Portal) obj; - return (this.getNetwork().equalsIgnoreCase(portal.getNetwork()) && - this.getName().equalsIgnoreCase(portal.getName())); - } -} +package net.TheDgtl.Stargate; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Scanner; +import java.util.logging.Level; + +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.Sign; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Minecart; +import org.bukkit.entity.Player; +import org.bukkit.entity.Vehicle; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.material.Button; +import org.bukkit.material.MaterialData; +import org.bukkit.util.Vector; + +/** + * Portal.java - Plug-in for hey0's minecraft mod. + * @author Shaun (sturmeh) + * @author Dinnerbone + */ +public class Portal { + // Variables used to store portal lists + private static final HashMap lookupBlocks = new HashMap(); + private static final HashMap lookupEntrances = new HashMap(); + private static final ArrayList allPortals = new ArrayList(); + private static final HashMap> allPortalsNet = new HashMap>(); + private static final HashMap> lookupNamesNet = new HashMap>(); + + // Gate location block info + private Blox topLeft; + private int modX; + private int modZ; + private float rotX; + // Block references + private SignPost id; + private Blox button; + private Blox[] frame; + private Blox[] entrances; + // Gate information + private String name; + private String destination; + private String network; + private Gate gate; + private String owner = ""; + private boolean hidden = false; + private boolean alwaysOn = false; + private boolean priv = false; + private boolean free = false; + private World world; + // Gate options + private boolean verified; + private boolean fixed; + // In-use information + private Player player; + private Player activePlayer; + private ArrayList destinations = new ArrayList(); + private boolean isOpen = false; + private long openTime; + + private Portal(Blox topLeft, int modX, int modZ, + float rotX, SignPost id, Blox button, + String dest, String name, + boolean verified, String network, Gate gate, + String owner, boolean hidden, boolean alwaysOn, boolean priv, boolean free) { + this.topLeft = topLeft; + this.modX = modX; + this.modZ = modZ; + this.rotX = rotX; + this.id = id; + this.destination = dest; + this.button = button; + this.verified = verified; + this.fixed = dest.length() > 0; + this.network = network; + this.name = name; + this.gate = gate; + this.owner = owner; + this.hidden = hidden; + this.alwaysOn = alwaysOn; + this.priv = priv; + this.free = free; + this.world = topLeft.getWorld(); + + if (this.alwaysOn && !this.fixed) { + this.alwaysOn = false; + Stargate.log.log(Level.WARNING, "Can not create a non-fixed always-on gate."); + } + + this.register(); + if (verified) { + this.drawSign(); + } + } + + public boolean isOpen() { + return isOpen || isAlwaysOn(); + } + + public boolean isAlwaysOn() { + return alwaysOn && isFixed(); + } + + public boolean isHidden() { + return hidden; + } + + public boolean isPrivate() { + return priv; + } + + public boolean isFree() { + return free; + } + + public boolean open(boolean force) { + return open(null, force); + } + + public boolean open(Player openFor, boolean force) { + if (isOpen() && !force) return false; + + world.loadChunk(world.getChunkAt(topLeft.getBlock())); + + for (Blox inside : getEntrances()) { + inside.setType(gate.getPortalBlockOpen()); + } + + isOpen = true; + openTime = System.currentTimeMillis() / 1000; + Stargate.openList.add(this); + Stargate.activeList.remove(this); + // Open remote gate + if (!isAlwaysOn()) { + player = openFor; + + Portal end = getDestination(); + if (end != null && !end.isFixed() && !end.isOpen()) { + end.open(openFor, false); + end.setDestination(this); + if (end.isVerified()) end.drawSign(); + } + } + + return true; + } + + public void close(boolean force) { + if (isAlwaysOn() && !force) return; // Never close an always open gate + + // Close this gate, then the dest gate. + for (Blox inside : getEntrances()) { + inside.setType(gate.getPortalBlockClosed()); + } + + player = null; + isOpen = false; + Stargate.openList.remove(this); + Stargate.activeList.remove(this); + + if (!isAlwaysOn()) { + Portal end = getDestination(); + + if (end != null && end.isOpen()) { + end.deactivate(); // Clear it's destination first. + end.close(false); + } + } + + deactivate(); + } + + public boolean isOpenFor(Player player) { + if ((isAlwaysOn()) || (this.player == null)) { + return true; + } + return (player != null) && (player.getName().equalsIgnoreCase(this.player.getName())); + } + + public boolean isFixed() { + return fixed; + } + + public boolean isPowered() { + RelativeBlockVector[] controls = gate.getControls(); + + for (RelativeBlockVector vector : controls) { + MaterialData mat = getBlockAt(vector).getBlock().getState().getData(); + + if (mat instanceof Button && ((Button)mat).isPowered()) + return true; + } + + return false; + } + + public void teleport(Player player, Portal origin, PlayerMoveEvent event) { + Location traveller = player.getLocation(); + Location exit = getExit(traveller, origin); + + exit.setYaw(origin.getRotation() - traveller.getYaw() + this.getRotation() + 180); + + // Change "from" so we don't get hack warnings. Cancel player move event. + event.setFrom(exit); + player.teleport(exit); + event.setCancelled(true); + } + + public void teleport(final Vehicle vehicle, Portal origin) { + Location traveller = new Location(this.world, vehicle.getLocation().getX(), vehicle.getLocation().getY(), vehicle.getLocation().getZ()); + Location exit = getExit(traveller, origin); + + double velocity = vehicle.getVelocity().length(); + + // Stop and teleport + vehicle.setVelocity(new Vector()); + + // Get new velocity + final Vector newVelocity = new Vector(); + switch ((int)id.getBlock().getData()) { + case 2: + newVelocity.setZ(-1); + break; + case 3: + newVelocity.setZ(1); + break; + case 4: + newVelocity.setX(-1); + break; + case 5: + newVelocity.setX(1); + break; + } + newVelocity.multiply(velocity); + + final Entity passenger = vehicle.getPassenger(); + vehicle.eject(); + vehicle.remove(); + final Minecart mc = exit.getWorld().spawnMinecart(exit); + if (passenger != null) { + passenger.teleport(exit); + Stargate.server.getScheduler().scheduleSyncDelayedTask(Stargate.stargate, new Runnable() { + public void run() { + mc.setPassenger(passenger); + mc.setVelocity(newVelocity); + } + }, 1); + } else { + mc.setVelocity(newVelocity); + } + } + + public Location getExit(Location traveller, Portal origin) { + Location loc = null; + // Check if the gate has an exit block + if (gate.getExit() != null) { + Blox exit = getBlockAt(gate.getExit()); + loc = exit.modRelativeLoc(0D, 0D, 1D, traveller.getYaw(), traveller.getPitch(), modX, 1, modZ); + } else { + Stargate.log.log(Level.WARNING, "[Stargate] Missing destination point in .gate file " + gate.getFilename()); + } + if (loc != null) { + Block block = world.getBlockAt(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + + if (block.getType() == Material.STEP) { + loc.setY(loc.getY() + 0.5); + } + + loc.setPitch(traveller.getPitch()); + return loc; + } + return traveller; + } + + public float getRotation() { + return rotX; + } + + public void setName(String name) { + this.name = filterName(name); + + drawSign(); + } + + public String getName() { + return name; + } + + public void setDestination(Portal destination) { + setDestination(destination.getName()); + } + + public void setDestination(String destination) { + this.destination = destination; + } + + public Portal getDestination() { + return Portal.getByName(destination, getNetwork()); + } + + public String getDestinationName() { + return destination; + } + + public boolean isChunkLoaded() { + return topLeft.getWorld().isChunkLoaded(topLeft.getBlock().getChunk()); + } + + public void loadChunk() { + topLeft.getWorld().loadChunk(topLeft.getBlock().getChunk()); + } + + public boolean isVerified() { + for (RelativeBlockVector control : gate.getControls()) + verified = verified || getBlockAt(control).getBlock().getTypeId() == gate.getControlBlock(); + return verified; + } + + public boolean wasVerified() { + return verified; + } + + public boolean checkIntegrity() { + return gate.matches(topLeft, modX, modZ); + } + + public Gate getGate() { + return gate; + } + + public String getOwner() { + return owner; + } + + public void activate(Player player) { + destinations.clear(); + destination = ""; + drawSign(); + Stargate.activeList.add(this); + activePlayer = player; + if (Stargate.worldFilter) Stargate.log.info("[Stargate] Filtering by world"); + for (String dest : allPortalsNet.get(getNetwork().toLowerCase())) { + Portal portal = getByName(dest, getNetwork()); + // Check if this player can access the dest world + if (Stargate.worldFilter && !Stargate.hasPerm(player, "stargate.world." + portal.topLeft.getWorld().getName(), player.isOp())) continue; + // Check if dest is this portal + if (dest.equalsIgnoreCase(getName())) continue; + // Check if dest is a fixed gate + if (portal.isFixed()) continue; + // Visible to this player. + if (!portal.isHidden() || Stargate.hasPerm(player, "stargate.hidden", player.isOp()) || portal.getOwner().equals(player.getName())) { + destinations.add(portal.getName()); + } + } + } + + public void deactivate() { + Stargate.activeList.remove(this); + if (isFixed()) { + return; + } + destinations.clear(); + destination = ""; + activePlayer = null; + drawSign(); + } + + public boolean isActive() { + return fixed || (destinations.size() > 0); + } + + public Player getActivePlayer() { + return activePlayer; + } + + public String getNetwork() { + return network; + } + + public long getOpenTime() { + return openTime; + } + + public void cycleDestination(Player player) { + if (!isActive() || getActivePlayer() != player) { + activate(player); + } + + if (destinations.size() > 0) { + int index = destinations.indexOf(destination); + if (++index >= destinations.size()) { + index = 0; + } + destination = destinations.get(index); + } + openTime = System.currentTimeMillis() / 1000; + drawSign(); + } + + public final void drawSign() { + id.setText(0, "--" + name + "--"); + int max = destinations.size() - 1; + int done = 0; + + if (!isActive()) { + id.setText(++done, "Right click to"); + id.setText(++done, "use the gate"); + id.setText(++done, " (" + network + ") "); + } else { + if (isFixed()) { + id.setText(++done, "To: " + destination); + id.setText(++done, " (" + network + ") "); + } else { + int index = destinations.indexOf(destination); + + if ((index == max) && (max > 1) && (++done <= 3)) { + id.setText(done, destinations.get(index - 2)); + } + if ((index > 0) && (++done <= 3)) { + id.setText(done, destinations.get(index - 1)); + } + if (++done <= 3) { + id.setText(done, " >" + destination + "< "); + } + if ((max >= index + 1) && (++done <= 3)) { + id.setText(done, destinations.get(index + 1)); + } + if ((max >= index + 2) && (++done <= 3)) { + id.setText(done, destinations.get(index + 2)); + } + } + } + + for (done++; done <= 3; done++) { + id.setText(done, ""); + } + + id.update(); + } + + public Blox[] getEntrances() { + if (entrances == null) { + RelativeBlockVector[] space = gate.getEntrances(); + entrances = new Blox[space.length]; + int i = 0; + + for (RelativeBlockVector vector : space) { + entrances[i++] = getBlockAt(vector); + } + } + return entrances; + } + + public Blox[] getFrame() { + if (frame == null) { + RelativeBlockVector[] border = gate.getBorder(); + RelativeBlockVector[] controls = gate.getControls(); + frame = new Blox[border.length + controls.length]; + int i = 0; + + for (RelativeBlockVector vector : border) { + frame[i++] = getBlockAt(vector); + } + + for (RelativeBlockVector vector : controls) { + frame[i++] = getBlockAt(vector); + } + } + + return frame; + } + + public void unregister(boolean removeAll) { + Stargate.log.info("[Stargate] Unregistering gate " + getName()); + close(true); + lookupNamesNet.get(getNetwork().toLowerCase()).remove(getName().toLowerCase()); + + for (Blox block : getFrame()) { + lookupBlocks.remove(block); + } + // Include the sign and button + lookupBlocks.remove(new Blox(id.getBlock())); + if (button != null) { + lookupBlocks.remove(button); + } + + for (Blox entrance : getEntrances()) { + lookupEntrances.remove(entrance); + } + + if (removeAll) + allPortals.remove(this); + + allPortalsNet.get(getNetwork().toLowerCase()).remove(getName().toLowerCase()); + + if (id.getBlock().getType() == Material.WALL_SIGN) { + id.setText(0, getName()); + id.setText(1, ""); + id.setText(2, ""); + id.setText(3, ""); + id.update(); + } + + for (String originName : allPortalsNet.get(getNetwork().toLowerCase())) { + Portal origin = Portal.getByName(originName, getNetwork()); + if ((origin != null) && (origin.isAlwaysOn()) && (origin.getDestinationName().equalsIgnoreCase(getName())) && (origin.isVerified())) { + origin.close(true); + } + } + + saveAllGates(world); + } + + private Blox getBlockAt(RelativeBlockVector vector) { + return topLeft.modRelative(vector.getRight(), vector.getDepth(), vector.getDistance(), modX, 1, modZ); + } + + private void register() { + if (!lookupNamesNet.containsKey(getNetwork().toLowerCase())) + lookupNamesNet.put(getNetwork().toLowerCase(), new HashMap()); + lookupNamesNet.get(getNetwork().toLowerCase()).put(getName().toLowerCase(), this); + + for (Blox block : getFrame()) { + lookupBlocks.put(block, this); + } + // Include the sign and button + lookupBlocks.put(new Blox(id.getBlock()), this); + if (button != null) { + lookupBlocks.put(button, this); + } + + for (Blox entrance : getEntrances()) { + lookupEntrances.put(entrance, this); + } + + allPortals.add(this); + // Check if this network exists + if (!allPortalsNet.containsKey(getNetwork().toLowerCase())) + allPortalsNet.put(getNetwork().toLowerCase(), new ArrayList()); + allPortalsNet.get(getNetwork().toLowerCase()).add(getName().toLowerCase()); + } + + public static Portal createPortal(SignPost id, Player player) { + Block idParent = id.getParent(); + if (idParent == null) return null; + if (Gate.getGatesByControlBlock(idParent).length == 0) return null; + + Blox parent = new Blox(player.getWorld(), idParent.getX(), idParent.getY(), idParent.getZ()); + Blox topleft = null; + String name = filterName(id.getText(0)); + String destName = filterName(id.getText(1)); + String network = filterName(id.getText(2)); + String options = filterName(id.getText(3)); + boolean hidden = (options.indexOf('h') != -1 || options.indexOf('H') != -1); + boolean alwaysOn = (options.indexOf('a') != -1 || options.indexOf('A') != -1); + boolean priv = (options.indexOf('p') != -1 || options.indexOf('P') != -1); + boolean free = (options.indexOf('f') != - 1|| options.indexOf('F') != -1); + + // Check if the user can only create personal gates, set network if so + if (Stargate.hasPerm(player, "stargate.create.personal", false) && + !Stargate.hasPerm(player, "stargate.create", player.isOp()) ) { + network = player.getName(); + if (network.length() > 11) network = network.substring(0, 11); + } + + // Can not create a non-fixed always-on gate. + if (alwaysOn && destName.length() == 0) { + alwaysOn = false; + } + + if ((network.length() < 1) || (network.length() > 11)) { + network = Stargate.getDefaultNetwork(); + } + if ((name.length() < 1) || (name.length() > 11) || (getByName(name, network) != null)) { + return null; + } + + int modX = 0; + int modZ = 0; + float rotX = 0f; + int facing = 0; + + if (idParent.getX() > id.getBlock().getX()) { + modZ -= 1; + rotX = 90f; + facing = 2; + } else if (idParent.getX() < id.getBlock().getX()) { + modZ += 1; + rotX = 270f; + facing = 1; + } else if (idParent.getZ() > id.getBlock().getZ()) { + modX += 1; + rotX = 180f; + facing = 4; + } else if (idParent.getZ() < id.getBlock().getZ()) { + modX -= 1; + rotX = 0f; + facing = 3; + } + + Gate[] possibleGates = Gate.getGatesByControlBlock(idParent); + Gate gate = null; + RelativeBlockVector buttonVector = null; + + for (Gate possibility : possibleGates) { + if ((gate == null) && (buttonVector == null)) { + RelativeBlockVector[] vectors = possibility.getControls(); + RelativeBlockVector otherControl = null; + + for (RelativeBlockVector vector : vectors) { + Blox tl = parent.modRelative(-vector.getRight(), -vector.getDepth(), -vector.getDistance(), modX, 1, modZ); + + if (gate == null) { + if (possibility.matches(tl, modX, modZ)) { + gate = possibility; + topleft = tl; + + if (otherControl != null) { + buttonVector = otherControl; + } + } + } else if (otherControl != null) { + buttonVector = vector; + } + + otherControl = vector; + } + } + } + + if ((gate == null) || (buttonVector == null)) { + return null; + } + + if (iConomyHandler.useiConomy() && !Stargate.hasPerm(player, "stargate.free", player.isOp()) && !iConomyHandler.chargePlayer(player.getName(), null, gate.getCreateCost())) { + if (!iConomyHandler.inFundMsg.isEmpty()) { + player.sendMessage(ChatColor.RED + iConomyHandler.inFundMsg); + } + return null; + } + + Portal portal = null; + + Blox button = null; + // No button on an always-open gate. + if (!alwaysOn) { + button = topleft.modRelative(buttonVector.getRight(), buttonVector.getDepth(), buttonVector.getDistance() + 1, modX, 1, modZ); + button.setType(Material.STONE_BUTTON.getId()); + button.setData(facing); + } + portal = new Portal(topleft, modX, modZ, rotX, id, button, destName, name, true, network, gate, player.getName(), hidden, alwaysOn, priv, free); + + // Open always on gate + if (portal.isAlwaysOn()) { + Portal dest = Portal.getByName(destName, portal.getNetwork()); + if (dest != null) + portal.open(true); + } + + // Open any always on gate pointing at this gate + for (String originName : allPortalsNet.get(portal.getNetwork().toLowerCase())) { + Portal origin = Portal.getByName(originName, portal.getNetwork()); + if (origin != null && origin.isAlwaysOn() && origin.getDestinationName().equalsIgnoreCase(portal.getName()) && origin.isVerified()) + origin.open(true); + } + + saveAllGates(topleft.getWorld()); + + return portal; + } + + public static Portal getByName(String name, String network) { + if (!lookupNamesNet.containsKey(network.toLowerCase())) return null; + return lookupNamesNet.get(network.toLowerCase()).get(name.toLowerCase()); + + } + + public static Portal getByEntrance(Location location) { + return getByEntrance(new Blox(location).getBlock()); + } + + public static Portal getByEntrance(Block block) { + return lookupEntrances.get(new Blox(block)); + } + + public static Portal getByBlock(Block block) { + return lookupBlocks.get(new Blox(block)); + } + + public static void saveAllGates(World world) { + String loc = Stargate.getSaveLocation() + "/" + world.getName() + ".db"; + + try { + BufferedWriter bw = new BufferedWriter(new FileWriter(loc, false)); + + for (Portal portal : allPortals) { + String wName = portal.world.getName(); + if (!wName.equalsIgnoreCase(world.getName())) continue; + StringBuilder builder = new StringBuilder(); + Blox sign = new Blox(portal.id.getBlock()); + Blox button = portal.button; + + builder.append(portal.name); + builder.append(':'); + builder.append(sign.toString()); + builder.append(':'); + builder.append((button != null) ? button.toString() : ""); + builder.append(':'); + builder.append(portal.modX); + builder.append(':'); + builder.append(portal.modZ); + builder.append(':'); + builder.append(portal.rotX); + builder.append(':'); + builder.append(portal.topLeft.toString()); + builder.append(':'); + builder.append(portal.gate.getFilename()); + builder.append(':'); + builder.append(portal.isFixed() ? portal.getDestinationName() : ""); + builder.append(':'); + builder.append(portal.getNetwork()); + builder.append(':'); + builder.append(portal.getOwner()); + builder.append(':'); + builder.append(portal.isHidden()); + builder.append(':'); + builder.append(portal.isAlwaysOn()); + builder.append(':'); + builder.append(portal.isPrivate()); + builder.append(':'); + builder.append(portal.world.getName()); + builder.append(':'); + builder.append(portal.isFree()); + + bw.append(builder.toString()); + bw.newLine(); + } + + bw.close(); + } catch (Exception e) { + Stargate.log.log(Level.SEVERE, "Exception while writing stargates to " + loc + ": " + e); + } + } + + public static void clearGates() { + lookupBlocks.clear(); + lookupNamesNet.clear(); + lookupEntrances.clear(); + allPortals.clear(); + allPortalsNet.clear(); + } + + public static void loadAllGates(World world) { + String location = Stargate.getSaveLocation(); + + File db = new File(location, world.getName() + ".db"); + + if (db.exists()) { + int l = 0; + int portalCount = 0; + try { + Scanner scanner = new Scanner(db); + while (scanner.hasNextLine()) { + l++; + String line = scanner.nextLine().trim(); + if (line.startsWith("#") || line.isEmpty()) { + continue; + } + String[] split = line.split(":"); + if (split.length < 8) { + Stargate.log.info("[Stargate] Invalid line - " + l); + continue; + } + String name = split[0]; + Blox s = new Blox(world, split[1]); + if (!(s.getBlock().getState() instanceof Sign)) { + Stargate.log.info("[Stargate] Invalid sign on line " + l + " [" + s.getBlock() + "]"); + continue; + } + SignPost sign = new SignPost(s); + Blox button = (split[2].length() > 0) ? new Blox(world, split[2]) : null; + int modX = Integer.parseInt(split[3]); + int modZ = Integer.parseInt(split[4]); + float rotX = Float.parseFloat(split[5]); + Blox topLeft = new Blox(world, split[6]); + Gate gate = (split[7].contains(";")) ? Gate.getGateByName("nethergate.gate") : Gate.getGateByName(split[7]); + if (gate == null) { + Stargate.log.info("[Stargate] Invalid gate layout on line " + l + " [" + split[7] + "]"); + continue; + } + + String dest = (split.length > 8) ? split[8] : ""; + String network = (split.length > 9) ? split[9] : Stargate.getDefaultNetwork(); + if (network.isEmpty()) network = Stargate.getDefaultNetwork(); + String owner = (split.length > 10) ? split[10] : ""; + boolean hidden = (split.length > 11) ? split[11].equalsIgnoreCase("true") : false; + boolean alwaysOn = (split.length > 12) ? split[12].equalsIgnoreCase("true") : false; + boolean priv = (split.length > 13) ? split[13].equalsIgnoreCase("true") : false; + boolean free = (split.length > 15) ? split[15].equalsIgnoreCase("true") : false; + + Portal portal = new Portal(topLeft, modX, modZ, rotX, sign, button, dest, name, false, network, gate, owner, hidden, alwaysOn, priv, free); + portal.close(true); + } + scanner.close(); + + // Open any always-on gates. Do this here as it should be more efficient than in the loop. + int OpenCount = 0; + //for (Portal portal : allPortals) { + for (Iterator iter = allPortals.iterator(); iter.hasNext(); ) { + Portal portal = iter.next(); + if (portal == null) continue; + + // Verify portal integrity/register portal + if (!portal.wasVerified()) { + if (!portal.isVerified() || !portal.checkIntegrity()) { + portal.unregister(false); + iter.remove(); + Stargate.log.info("[Stargate] Destroying stargate at " + portal.toString()); + continue; + } else { + portal.drawSign(); + portalCount++; + } + } + + if (!portal.isAlwaysOn()) continue; + + Portal dest = portal.getDestination(); + if (dest != null) { + portal.open(true); + OpenCount++; + } + } + Stargate.log.info("[Stargate] {" + world.getName() + "} Loaded " + portalCount + " stargates with " + OpenCount + " set as always-on"); + } catch (Exception e) { + Stargate.log.log(Level.SEVERE, "Exception while reading stargates from " + db.getName() + ": " + l); + e.printStackTrace(); + } + } else { + Stargate.log.info("[Stargate] {" + world.getName() + "} No stargates for world "); + } + } + + public static void closeAllGates() { + Stargate.log.info("Closing all stargates."); + for (Portal p : allPortals) { + if (p == null) continue; + p.close(true); + } + } + + public static String filterName(String input) { + return input.replaceAll("[\\|:#]", "").trim(); + } + + @Override + public String toString() { + return String.format("Portal [id=%s, network=%s name=%s, type=%s]", id, network, name, gate.getFilename()); + } + + @Override + public int hashCode() { + return getName().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + + Portal portal = (Portal) obj; + return (this.getNetwork().equalsIgnoreCase(portal.getNetwork()) && + this.getName().equalsIgnoreCase(portal.getName())); + } +} diff --git a/src/net/TheDgtl/Stargate/Stargate.java b/src/net/TheDgtl/Stargate/Stargate.java index cab7484..a825d43 100644 --- a/src/net/TheDgtl/Stargate/Stargate.java +++ b/src/net/TheDgtl/Stargate/Stargate.java @@ -1,593 +1,601 @@ -package net.TheDgtl.Stargate; - -import java.io.File; -import java.util.Iterator; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.logging.Logger; - -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.Server; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.entity.Vehicle; -import org.bukkit.event.Event; -import org.bukkit.event.Event.Priority; -import org.bukkit.event.block.Action; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockFromToEvent; -import org.bukkit.event.block.BlockListener; -import org.bukkit.event.block.BlockPhysicsEvent; -import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.block.SignChangeEvent; -import org.bukkit.event.entity.EntityExplodeEvent; -import org.bukkit.event.entity.EntityListener; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerListener; -import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.server.PluginDisableEvent; -import org.bukkit.event.server.PluginEnableEvent; -import org.bukkit.event.server.ServerListener; -import org.bukkit.event.vehicle.VehicleListener; -import org.bukkit.event.vehicle.VehicleMoveEvent; -import org.bukkit.event.world.WorldListener; -import org.bukkit.event.world.WorldLoadEvent; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.PluginDescriptionFile; -import org.bukkit.plugin.PluginManager; -import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.util.config.Configuration; - -// Permissions -import com.nijikokun.bukkit.Permissions.Permissions; -// iConomy -import com.nijiko.coelho.iConomy.iConomy; - -/** - * Stargate.java - A customizeable portal plugin for Bukkit - * @author Shaun (sturmeh) - * @author Dinnerbone - * @author Steven "Drakia" Scott - */ -public class Stargate extends JavaPlugin { - // Permissions - private static Permissions permissions = null; - - private final bListener blockListener = new bListener(); - private final pListener playerListener = new pListener(); - private final vListener vehicleListener = new vListener(); - private final wListener worldListener = new wListener(); - private final eListener entityListener = new eListener(); - private final sListener serverListener = new sListener(); - - public static Logger log; - private Configuration config; - private PluginManager pm; - public static Server server; - public static Stargate stargate; - - private static String portalFolder; - private static String gateFolder; - private static String teleMsg = "Teleported"; - private static String regMsg = "Gate Created"; - private static String dmgMsg = "Gate Destroyed"; - private static String denyMsg = "Access Denied"; - private static String invMsg = "Invalid Destination"; - private static String blockMsg = "Destination Blocked"; - private static String defNetwork = "central"; - private static boolean destroyExplosion = false; - private static int activeLimit = 10; - private static int openLimit = 10; - - public static ConcurrentLinkedQueue openList = new ConcurrentLinkedQueue(); - public static ConcurrentLinkedQueue activeList = new ConcurrentLinkedQueue(); - //private HashMap vehicles = new HashMap(); - - public void onDisable() { - Portal.closeAllGates(); - Portal.clearGates(); - } - - public void onEnable() { - PluginDescriptionFile pdfFile = this.getDescription(); - pm = getServer().getPluginManager(); - config = this.getConfiguration(); - log = Logger.getLogger("Minecraft"); - Stargate.server = getServer(); - Stargate.stargate = this; - - // Set portalFile and gateFolder to the plugin folder as defaults. - portalFolder = getDataFolder() + "/portals"; - gateFolder = getDataFolder() + "/gates/"; - - log.info(pdfFile.getName() + " v." + pdfFile.getVersion() + " is enabled."); - - pm.registerEvent(Event.Type.BLOCK_FROMTO, blockListener, Priority.Normal, this); - pm.registerEvent(Event.Type.BLOCK_PHYSICS, blockListener, Priority.Normal, this); - - this.reloadConfig(); - this.migrate(); - this.reloadGates(); - - // Check to see if iConomy/Permissions is loaded yet. - permissions = (Permissions)checkPlugin("Permissions"); - iConomyHandler.iconomy = (iConomy)checkPlugin("iConomy"); - - pm.registerEvent(Event.Type.PLAYER_MOVE, playerListener, Priority.Normal, this); - - //pm.registerEvent(Event.Type.BLOCK_RIGHTCLICKED, blockListener, Priority.Normal, this); - //pm.registerEvent(Event.Type.BLOCK_PLACED, blockListener, Priority.Normal, this); - //pm.registerEvent(Event.Type.BLOCK_DAMAGED, blockListener, Priority.Normal, this); - pm.registerEvent(Event.Type.PLAYER_INTERACT, playerListener, Priority.Normal, this); - pm.registerEvent(Event.Type.BLOCK_BREAK, blockListener, Priority.Normal, this); - pm.registerEvent(Event.Type.VEHICLE_MOVE, vehicleListener, Priority.Normal, this); - pm.registerEvent(Event.Type.SIGN_CHANGE, blockListener, Priority.Normal, this); - - pm.registerEvent(Event.Type.WORLD_LOAD, worldListener, Priority.Normal, this); - - pm.registerEvent(Event.Type.ENTITY_EXPLODE, entityListener, Priority.Normal, this); - - // iConomy Loading - pm.registerEvent(Event.Type.PLUGIN_ENABLE, serverListener, Priority.Monitor, this); - pm.registerEvent(Event.Type.PLUGIN_DISABLE, serverListener, Priority.Monitor, this); - - getServer().getScheduler().scheduleSyncRepeatingTask(this, new SGThread(), 0L, 100L); - } - - public void reloadConfig() { - config.load(); - portalFolder = config.getString("portal-folder", portalFolder); - gateFolder = config.getString("gate-folder", gateFolder); - teleMsg = config.getString("teleport-message", teleMsg); - regMsg = config.getString("portal-create-message", regMsg); - dmgMsg = config.getString("portal-destroy-message", dmgMsg); - denyMsg = config.getString("not-owner-message", denyMsg); - invMsg = config.getString("not-selected-message", invMsg); - blockMsg = config.getString("other-side-blocked-message", blockMsg); - defNetwork = config.getString("default-gate-network", defNetwork).trim(); - destroyExplosion = config.getBoolean("destroyexplosion", destroyExplosion); - // iConomy - iConomyHandler.useiConomy = config.getBoolean("useiconomy", iConomyHandler.useiConomy); - iConomyHandler.createCost = config.getInt("createcost", iConomyHandler.createCost); - iConomyHandler.destroyCost = config.getInt("destroycost", iConomyHandler.destroyCost); - iConomyHandler.useCost = config.getInt("usecost", iConomyHandler.useCost); - iConomyHandler.inFundMsg = config.getString("not-enough-money-message", iConomyHandler.inFundMsg); - - saveConfig(); - } - - public void saveConfig() { - config.setProperty("portal-folder", portalFolder); - config.setProperty("gate-folder", gateFolder); - config.setProperty("teleport-message", teleMsg); - config.setProperty("portal-create-message", regMsg); - config.setProperty("portal-destroy-message", dmgMsg); - config.setProperty("not-owner-message", denyMsg); - config.setProperty("not-selected-message", invMsg); - config.setProperty("other-side-blocked-message", blockMsg); - config.setProperty("default-gate-network", defNetwork); - config.setProperty("destroyexplosion", destroyExplosion); - // iConomy - config.setProperty("useiconomy", iConomyHandler.useiConomy); - config.setProperty("createcost", iConomyHandler.createCost); - config.setProperty("destroycost", iConomyHandler.destroyCost); - config.setProperty("usecost", iConomyHandler.useCost); - config.setProperty("not-enough-money-message", iConomyHandler.inFundMsg); - - config.save(); - } - - public void reloadGates() { - Gate.loadGates(gateFolder); - // Replace nethergate.gate if it doesn't have an exit point. - if (Gate.getGateByName("nethergate.gate") == null || Gate.getGateByName("nethergate.gate").getExit() == null) { - Gate.populateDefaults(gateFolder); - } - log.info("[Stargate] Loaded " + Gate.getGateCount() + " gate layouts"); - for (World world : getServer().getWorlds()) { - Portal.loadAllGates(world); - } - } - - private void migrate() { - // Only migrate if new file doesn't exist. - File newPortalDir = new File(portalFolder); - if (!newPortalDir.exists()) { - newPortalDir.mkdirs(); - } - File newFile = new File(portalFolder, getServer().getWorlds().get(0).getName() + ".db"); - if (!newFile.exists()) { - newFile.getParentFile().mkdirs(); - // Migrate not-so-old stargate db - File oldishFile = new File("plugins/Stargate/stargate.db"); - if (oldishFile.exists()) { - Stargate.log.info("[Stargate] Migrating existing stargate.db"); - oldishFile.renameTo(newFile); - } - } - - // Migrate old gates if applicaple - File oldDir = new File("stargates"); - if (oldDir.exists()) { - File newDir = new File(gateFolder); - if (!newDir.exists()) newDir.mkdirs(); - for (File file : oldDir.listFiles(new Gate.StargateFilenameFilter())) { - Stargate.log.info("[Stargate] Migrating existing gate " + file.getName()); - file.renameTo(new File(gateFolder, file.getName())); - } - } - } - - public static String getSaveLocation() { - return portalFolder; - } - - public static String getDefaultNetwork() { - return defNetwork; - } - - private void onButtonPressed(Player player, Portal gate) { - Portal destination = gate.getDestination(); - - if (!gate.isOpen()) { - if (!gate.isFree() && !hasPerm(player, "stargate.free", player.isOp()) && - iConomyHandler.useiConomy() && iConomyHandler.getBalance(player.getName()) < gate.getGate().getUseCost()) { - player.sendMessage(ChatColor.RED + iConomyHandler.inFundMsg); - } else if ((!gate.isFixed()) && gate.isActive() && (gate.getActivePlayer() != player)) { - gate.deactivate(); - if (!denyMsg.isEmpty()) { - player.sendMessage(ChatColor.RED + denyMsg); - } - } else if (gate.isPrivate() && !gate.getOwner().equals(player.getName()) && !hasPerm(player, "stargate.private", player.isOp())) { - if (!denyMsg.isEmpty()) { - player.sendMessage(ChatColor.RED + denyMsg); - } - } else if ((destination == null) || (destination == gate)) { - if (!invMsg.isEmpty()) { - player.sendMessage(ChatColor.RED + invMsg); - } - } else if ((destination.isOpen()) && (!destination.isAlwaysOn())) { - if (!blockMsg.isEmpty()) { - player.sendMessage(ChatColor.RED + blockMsg); - } - } else { - gate.open(player, false); - } - } else { - gate.close(false); - } - } - - /* - * Check whether the player has the given permissions. - */ - public static boolean hasPerm(Player player, String perm, boolean def) { - if (permissions != null) { - return permissions.getHandler().has(player, perm); - } else { - return def; - } - } - - /* - * Check if a plugin is loaded/enabled already. Returns the plugin if so, null otherwise - */ - private Plugin checkPlugin(String p) { - Plugin plugin = pm.getPlugin(p); - return checkPlugin(plugin); - } - - private Plugin checkPlugin(Plugin plugin) { - if (plugin != null && plugin.isEnabled()) { - log.info("[Stargate] Found " + plugin.getDescription().getName() + " (v" + plugin.getDescription().getVersion() + ")"); - return plugin; - } - return null; - } - - private class vListener extends VehicleListener { - @Override - public void onVehicleMove(VehicleMoveEvent event) { - Entity passenger = event.getVehicle().getPassenger(); - Vehicle vehicle = event.getVehicle(); - - Portal portal = Portal.getByEntrance(event.getTo()); - if (portal == null || !portal.isOpen()) return; - - if (passenger instanceof Player) { - Player player = (Player)passenger; - if (!portal.isOpenFor(player)) { - player.sendMessage(ChatColor.RED + denyMsg); - return; - } - Portal dest = portal.getDestination(); - if (dest == null) return; - - if (portal.isFree() || !iConomyHandler.useiConomy() || hasPerm(player, "stargate.free", player.isOp()) || - iConomyHandler.chargePlayer(player.getName(), null, portal.getGate().getUseCost())) { - if (!portal.isFree() && iConomyHandler.useiConomy()) { - player.sendMessage(ChatColor.GREEN + "Deducted " + iConomy.getBank().format(portal.getGate().getUseCost())); - } - if (!teleMsg.isEmpty()) { - player.sendMessage(ChatColor.BLUE + teleMsg); - } - dest.teleport(vehicle, portal); - } else { - if (!iConomyHandler.inFundMsg.isEmpty()) { - player.sendMessage(ChatColor.RED + iConomyHandler.inFundMsg); - } - } - portal.close(false); - } - } - } - - private class pListener extends PlayerListener { - @Override - public void onPlayerMove(PlayerMoveEvent event) { - Player player = event.getPlayer(); - Portal portal = Portal.getByEntrance(event.getTo()); - - if ((portal != null) && (portal.isOpen())) { - if (portal.isOpenFor(player)) { - Portal destination = portal.getDestination(); - - if (destination != null) { - if (portal.isFree() || !iConomyHandler.useiConomy() || hasPerm(player, "stargate.free", player.isOp()) || - iConomyHandler.chargePlayer(player.getName(), null, portal.getGate().getUseCost())) { - if (!portal.isFree() && iConomyHandler.useiConomy()) { - player.sendMessage(ChatColor.GREEN + "Deducted " + iConomy.getBank().format(portal.getGate().getUseCost())); - } - if (!teleMsg.isEmpty()) { - player.sendMessage(ChatColor.BLUE + teleMsg); - } - - destination.teleport(player, portal, event); - } else { - if (!iConomyHandler.inFundMsg.isEmpty()) { - player.sendMessage(ChatColor.RED + iConomyHandler.inFundMsg); - } - } - portal.close(false); - } - } else { - if (!denyMsg.isEmpty()) { - player.sendMessage(ChatColor.RED + denyMsg); - } - } - } - } - - @Override - public void onPlayerInteract(PlayerInteractEvent event) { - Player player = event.getPlayer(); - Block block = event.getClickedBlock(); - - // Right click - if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { - if (block.getType() == Material.WALL_SIGN) { - Portal portal = Portal.getByBlock(block); - // Cycle through a stargates locations - if (portal != null) { - if (hasPerm(player, "stargate.use", true)) { - if ((!portal.isOpen()) && (!portal.isFixed())) { - portal.cycleDestination(player); - } - } else { - if (!denyMsg.isEmpty()) { - player.sendMessage(denyMsg); - } - } - } - } - - // Implement right-click to toggle a stargate, gets around spawn protection problem. - if ((block.getType() == Material.STONE_BUTTON)) { - if (hasPerm(player, "stargate.use", true)) { - Portal portal = Portal.getByBlock(block); - if (portal != null) { - onButtonPressed(player, portal); - } - } - } - } - - // Left click - if (event.getAction() == Action.LEFT_CLICK_BLOCK) { - // Check if we're pushing a button. - if (block.getType() == Material.STONE_BUTTON) { - if (hasPerm(player, "stargate.use", true)) { - Portal portal = Portal.getByBlock(block); - if (portal != null) { - onButtonPressed(player, portal); - } - } - } - } - } - } - - private class bListener extends BlockListener { - @Override - public void onBlockPlace(BlockPlaceEvent event) { - // Stop player from placing a block touching a portals controls - if (event.getBlockAgainst().getType() == Material.STONE_BUTTON || - event.getBlockAgainst().getType() == Material.WALL_SIGN) { - Portal portal = Portal.getByBlock(event.getBlockAgainst()); - if (portal != null) event.setCancelled(true); - } - } - - @Override - public void onSignChange(SignChangeEvent event) { - Player player = event.getPlayer(); - Block block = event.getBlock(); - if (block.getType() != Material.WALL_SIGN) return; - - // Initialize a stargate - if (hasPerm(player, "stargate.create", player.isOp()) || - hasPerm(player, "stargate.create.personal", false)) { - SignPost sign = new SignPost(new Blox(block)); - // Set sign text so we can create a gate with it. - sign.setText(0, event.getLine(0)); - sign.setText(1, event.getLine(1)); - sign.setText(2, event.getLine(2)); - sign.setText(3, event.getLine(3)); - Portal portal = Portal.createPortal(sign, player); - if (portal == null) return; - - if (iConomyHandler.useiConomy()) { - player.sendMessage(ChatColor.GREEN + "Deducted " + iConomy.getBank().format(portal.getGate().getCreateCost())); - } - if (!regMsg.isEmpty()) { - player.sendMessage(ChatColor.GREEN + regMsg); - } - log.info("[Stargate] Initialized stargate: " + portal.getName()); - portal.drawSign(); - // Set event text so our new sign is instantly initialized - event.setLine(0, sign.getText(0)); - event.setLine(1, sign.getText(1)); - event.setLine(2, sign.getText(2)); - event.setLine(3, sign.getText(3)); - } - } - - @Override - public void onBlockBreak(BlockBreakEvent event) { - Block block = event.getBlock(); - Player player = event.getPlayer(); - if (block.getType() != Material.WALL_SIGN && block.getType() != Material.STONE_BUTTON && Gate.getGatesByControlBlock(block).length == 0) { - return; - } - - Portal portal = Portal.getByBlock(block); - if (portal == null) return; - - if (hasPerm(player, "stargate.destroy", player.isOp()) || hasPerm(player, "stargate.destroy.all", player.isOp()) || - ( portal.getOwner().equalsIgnoreCase(player.getName()) && hasPerm(player, "stargate.destroy.owner", false) )) { - // Can't afford - if (iConomyHandler.useiConomy()) { - if(iConomyHandler.getBalance(player.getName()) < portal.getGate().getDestroyCost()) { - if (!iConomyHandler.inFundMsg.isEmpty()) { - player.sendMessage(ChatColor.RED + iConomyHandler.inFundMsg); - event.setCancelled(true); - return; - } - } - iConomyHandler.chargePlayer(player.getName(), null, portal.getGate().getDestroyCost()); - if (portal.getGate().getDestroyCost() > 0) { - player.sendMessage(ChatColor.GREEN + "Deducted " + iConomy.getBank().format(portal.getGate().getDestroyCost())); - } else if (portal.getGate().getDestroyCost() < 0) { - player.sendMessage(ChatColor.GREEN + "Refunded " + iConomy.getBank().format(-portal.getGate().getDestroyCost())); - } - } - - portal.unregister(true); - if (!dmgMsg.isEmpty()) { - player.sendMessage(ChatColor.RED + dmgMsg); - } - return; - } - - event.setCancelled(true); - } - - @Override - public void onBlockPhysics(BlockPhysicsEvent event) { - Block block = event.getBlock(); - if (block.getType() == Material.PORTAL) { - event.setCancelled((Portal.getByEntrance(block) != null)); - } - } - - @Override - public void onBlockFromTo(BlockFromToEvent event) { - Portal portal = Portal.getByEntrance(event.getBlock()); - - if (portal != null) { - event.setCancelled((event.getBlock().getY() == event.getToBlock().getY())); - } - } - } - - private class wListener extends WorldListener { - @Override - public void onWorldLoad(WorldLoadEvent event) { - World w = event.getWorld(); - // We have to make sure the world is actually loaded. This gets called twice for some reason. - if (w.getBlockAt(w.getSpawnLocation()).getWorld() != null) { - Portal.loadAllGates(w); - } - } - } - - private class eListener extends EntityListener { - @Override - public void onEntityExplode(EntityExplodeEvent event) { - if (event.isCancelled()) return; - for (Block b : event.blockList()) { - if (b.getTypeId() != Material.WALL_SIGN.getId() && b.getTypeId() != Material.STONE_BUTTON.getId()) continue; - Portal portal = Portal.getByBlock(b); - if (portal == null) continue; - if (destroyExplosion) { - portal.unregister(true); - } else { - b.setType(b.getType()); - event.setCancelled(true); - } - } - } - } - - private class sListener extends ServerListener { - @Override - public void onPluginEnable(PluginEnableEvent event) { - if (iConomyHandler.iconomy == null) { - if (event.getPlugin().getDescription().getName().equalsIgnoreCase("iConomy")) { - iConomyHandler.iconomy = (iConomy)checkPlugin(event.getPlugin()); - } - } - if (permissions == null) { - if (event.getPlugin().getDescription().getName().equalsIgnoreCase("Permissions")) { - permissions = (Permissions)checkPlugin(event.getPlugin()); - } - } - } - - @Override - public void onPluginDisable(PluginDisableEvent event) { - if (event.getPlugin() == iConomyHandler.iconomy) { - log.info("[Stargate] iConomy plugin lost."); - iConomyHandler.iconomy = null; - } - if (event.getPlugin() == permissions) { - log.info("[Stargate] Permissions plugin lost."); - permissions = null; - } - } - } - - private class SGThread implements Runnable { - public void run() { - long time = System.currentTimeMillis() / 1000; - // Close open portals - for (Iterator iter = Stargate.openList.iterator(); iter.hasNext();) { - Portal p = iter.next(); - if (time > p.getOpenTime() + Stargate.openLimit) { - p.close(false); - iter.remove(); - } - } - // Deactivate active portals - for (Iterator iter = Stargate.activeList.iterator(); iter.hasNext();) { - Portal p = iter.next(); - if (time > p.getOpenTime() + Stargate.activeLimit) { - p.deactivate(); - iter.remove(); - } - } - } - } -} +package net.TheDgtl.Stargate; + +import java.io.File; +import java.util.Iterator; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.logging.Logger; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.Server; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Vehicle; +import org.bukkit.event.Event; +import org.bukkit.event.Event.Priority; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockFromToEvent; +import org.bukkit.event.block.BlockListener; +import org.bukkit.event.block.BlockPhysicsEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.SignChangeEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.EntityListener; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerListener; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.server.PluginDisableEvent; +import org.bukkit.event.server.PluginEnableEvent; +import org.bukkit.event.server.ServerListener; +import org.bukkit.event.vehicle.VehicleListener; +import org.bukkit.event.vehicle.VehicleMoveEvent; +import org.bukkit.event.world.WorldListener; +import org.bukkit.event.world.WorldLoadEvent; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginDescriptionFile; +import org.bukkit.plugin.PluginManager; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.util.config.Configuration; + +// Permissions +import com.nijikokun.bukkit.Permissions.Permissions; +// iConomy +import com.nijiko.coelho.iConomy.iConomy; + +/** + * Stargate.java - A customizeable portal plugin for Bukkit + * @author Shaun (sturmeh) + * @author Dinnerbone + * @author Steven "Drakia" Scott + */ +public class Stargate extends JavaPlugin { + // Permissions + private static Permissions permissions = null; + + private final bListener blockListener = new bListener(); + private final pListener playerListener = new pListener(); + private final vListener vehicleListener = new vListener(); + private final wListener worldListener = new wListener(); + private final eListener entityListener = new eListener(); + private final sListener serverListener = new sListener(); + + public static Logger log; + private Configuration config; + private PluginManager pm; + public static Server server; + public static Stargate stargate; + + private static String portalFolder; + private static String gateFolder; + private static String teleMsg = "Teleported"; + private static String regMsg = "Gate Created"; + private static String dmgMsg = "Gate Destroyed"; + private static String denyMsg = "Access Denied"; + private static String invMsg = "Invalid Destination"; + private static String blockMsg = "Destination Blocked"; + private static String defNetwork = "central"; + private static boolean destroyExplosion = false; + public static boolean networkFilter = false; + public static boolean worldFilter = false; + private static int activeLimit = 10; + private static int openLimit = 10; + + public static ConcurrentLinkedQueue openList = new ConcurrentLinkedQueue(); + public static ConcurrentLinkedQueue activeList = new ConcurrentLinkedQueue(); + //private HashMap vehicles = new HashMap(); + + public void onDisable() { + Portal.closeAllGates(); + Portal.clearGates(); + } + + public void onEnable() { + PluginDescriptionFile pdfFile = this.getDescription(); + pm = getServer().getPluginManager(); + config = this.getConfiguration(); + log = Logger.getLogger("Minecraft"); + Stargate.server = getServer(); + Stargate.stargate = this; + + // Set portalFile and gateFolder to the plugin folder as defaults. + portalFolder = getDataFolder() + "/portals"; + gateFolder = getDataFolder() + "/gates/"; + + log.info(pdfFile.getName() + " v." + pdfFile.getVersion() + " is enabled."); + + pm.registerEvent(Event.Type.BLOCK_FROMTO, blockListener, Priority.Normal, this); + pm.registerEvent(Event.Type.BLOCK_PHYSICS, blockListener, Priority.Normal, this); + + this.reloadConfig(); + this.migrate(); + this.reloadGates(); + + // Check to see if iConomy/Permissions is loaded yet. + permissions = (Permissions)checkPlugin("Permissions"); + iConomyHandler.iconomy = (iConomy)checkPlugin("iConomy"); + + pm.registerEvent(Event.Type.PLAYER_MOVE, playerListener, Priority.Normal, this); + + //pm.registerEvent(Event.Type.BLOCK_RIGHTCLICKED, blockListener, Priority.Normal, this); + //pm.registerEvent(Event.Type.BLOCK_PLACED, blockListener, Priority.Normal, this); + //pm.registerEvent(Event.Type.BLOCK_DAMAGED, blockListener, Priority.Normal, this); + pm.registerEvent(Event.Type.PLAYER_INTERACT, playerListener, Priority.Normal, this); + pm.registerEvent(Event.Type.BLOCK_BREAK, blockListener, Priority.Normal, this); + pm.registerEvent(Event.Type.VEHICLE_MOVE, vehicleListener, Priority.Normal, this); + pm.registerEvent(Event.Type.SIGN_CHANGE, blockListener, Priority.Normal, this); + + pm.registerEvent(Event.Type.WORLD_LOAD, worldListener, Priority.Normal, this); + + pm.registerEvent(Event.Type.ENTITY_EXPLODE, entityListener, Priority.Normal, this); + + // iConomy Loading + pm.registerEvent(Event.Type.PLUGIN_ENABLE, serverListener, Priority.Monitor, this); + pm.registerEvent(Event.Type.PLUGIN_DISABLE, serverListener, Priority.Monitor, this); + + getServer().getScheduler().scheduleSyncRepeatingTask(this, new SGThread(), 0L, 100L); + } + + public void reloadConfig() { + config.load(); + portalFolder = config.getString("portal-folder", portalFolder); + gateFolder = config.getString("gate-folder", gateFolder); + teleMsg = config.getString("teleport-message", teleMsg); + regMsg = config.getString("portal-create-message", regMsg); + dmgMsg = config.getString("portal-destroy-message", dmgMsg); + denyMsg = config.getString("not-owner-message", denyMsg); + invMsg = config.getString("not-selected-message", invMsg); + blockMsg = config.getString("other-side-blocked-message", blockMsg); + defNetwork = config.getString("default-gate-network", defNetwork).trim(); + destroyExplosion = config.getBoolean("destroyexplosion", destroyExplosion); + networkFilter = config.getBoolean("networkfilter", networkFilter); + worldFilter = config.getBoolean("worldfilter", worldFilter); + // iConomy + iConomyHandler.useiConomy = config.getBoolean("useiconomy", iConomyHandler.useiConomy); + iConomyHandler.createCost = config.getInt("createcost", iConomyHandler.createCost); + iConomyHandler.destroyCost = config.getInt("destroycost", iConomyHandler.destroyCost); + iConomyHandler.useCost = config.getInt("usecost", iConomyHandler.useCost); + iConomyHandler.inFundMsg = config.getString("not-enough-money-message", iConomyHandler.inFundMsg); + + saveConfig(); + } + + public void saveConfig() { + config.setProperty("portal-folder", portalFolder); + config.setProperty("gate-folder", gateFolder); + config.setProperty("teleport-message", teleMsg); + config.setProperty("portal-create-message", regMsg); + config.setProperty("portal-destroy-message", dmgMsg); + config.setProperty("not-owner-message", denyMsg); + config.setProperty("not-selected-message", invMsg); + config.setProperty("other-side-blocked-message", blockMsg); + config.setProperty("default-gate-network", defNetwork); + config.setProperty("destroyexplosion", destroyExplosion); + config.setProperty("networkfilter", networkFilter); + config.setProperty("worldfilter", worldFilter); + // iConomy + config.setProperty("useiconomy", iConomyHandler.useiConomy); + config.setProperty("createcost", iConomyHandler.createCost); + config.setProperty("destroycost", iConomyHandler.destroyCost); + config.setProperty("usecost", iConomyHandler.useCost); + config.setProperty("not-enough-money-message", iConomyHandler.inFundMsg); + + config.save(); + } + + public void reloadGates() { + Gate.loadGates(gateFolder); + // Replace nethergate.gate if it doesn't have an exit point. + if (Gate.getGateByName("nethergate.gate") == null || Gate.getGateByName("nethergate.gate").getExit() == null) { + Gate.populateDefaults(gateFolder); + } + log.info("[Stargate] Loaded " + Gate.getGateCount() + " gate layouts"); + for (World world : getServer().getWorlds()) { + Portal.loadAllGates(world); + } + } + + private void migrate() { + // Only migrate if new file doesn't exist. + File newPortalDir = new File(portalFolder); + if (!newPortalDir.exists()) { + newPortalDir.mkdirs(); + } + File newFile = new File(portalFolder, getServer().getWorlds().get(0).getName() + ".db"); + if (!newFile.exists()) { + newFile.getParentFile().mkdirs(); + // Migrate not-so-old stargate db + File oldishFile = new File("plugins/Stargate/stargate.db"); + if (oldishFile.exists()) { + Stargate.log.info("[Stargate] Migrating existing stargate.db"); + oldishFile.renameTo(newFile); + } + } + + // Migrate old gates if applicaple + File oldDir = new File("stargates"); + if (oldDir.exists()) { + File newDir = new File(gateFolder); + if (!newDir.exists()) newDir.mkdirs(); + for (File file : oldDir.listFiles(new Gate.StargateFilenameFilter())) { + Stargate.log.info("[Stargate] Migrating existing gate " + file.getName()); + file.renameTo(new File(gateFolder, file.getName())); + } + } + } + + public static String getSaveLocation() { + return portalFolder; + } + + public static String getDefaultNetwork() { + return defNetwork; + } + + private void onButtonPressed(Player player, Portal gate) { + Portal destination = gate.getDestination(); + + if (!gate.isOpen()) { + if (!gate.isFree() && !hasPerm(player, "stargate.free", player.isOp()) && + iConomyHandler.useiConomy() && iConomyHandler.getBalance(player.getName()) < gate.getGate().getUseCost()) { + player.sendMessage(ChatColor.RED + iConomyHandler.inFundMsg); + } else if ((!gate.isFixed()) && gate.isActive() && (gate.getActivePlayer() != player)) { + gate.deactivate(); + if (!denyMsg.isEmpty()) { + player.sendMessage(ChatColor.RED + denyMsg); + } + } else if (gate.isPrivate() && !gate.getOwner().equals(player.getName()) && !hasPerm(player, "stargate.private", player.isOp())) { + if (!denyMsg.isEmpty()) { + player.sendMessage(ChatColor.RED + denyMsg); + } + } else if ((destination == null) || (destination == gate)) { + if (!invMsg.isEmpty()) { + player.sendMessage(ChatColor.RED + invMsg); + } + } else if ((destination.isOpen()) && (!destination.isAlwaysOn())) { + if (!blockMsg.isEmpty()) { + player.sendMessage(ChatColor.RED + blockMsg); + } + } else { + gate.open(player, false); + } + } else { + gate.close(false); + } + } + + /* + * Check whether the player has the given permissions. + */ + public static boolean hasPerm(Player player, String perm, boolean def) { + if (permissions != null) { + return permissions.getHandler().has(player, perm); + } else { + return def; + } + } + + /* + * Check if a plugin is loaded/enabled already. Returns the plugin if so, null otherwise + */ + private Plugin checkPlugin(String p) { + Plugin plugin = pm.getPlugin(p); + return checkPlugin(plugin); + } + + private Plugin checkPlugin(Plugin plugin) { + if (plugin != null && plugin.isEnabled()) { + log.info("[Stargate] Found " + plugin.getDescription().getName() + " (v" + plugin.getDescription().getVersion() + ")"); + return plugin; + } + return null; + } + + private class vListener extends VehicleListener { + @Override + public void onVehicleMove(VehicleMoveEvent event) { + Entity passenger = event.getVehicle().getPassenger(); + Vehicle vehicle = event.getVehicle(); + + Portal portal = Portal.getByEntrance(event.getTo()); + if (portal == null || !portal.isOpen()) return; + + if (passenger instanceof Player) { + Player player = (Player)passenger; + if (!portal.isOpenFor(player)) { + player.sendMessage(ChatColor.RED + denyMsg); + return; + } + Portal dest = portal.getDestination(); + if (dest == null) return; + + if (portal.isFree() || !iConomyHandler.useiConomy() || hasPerm(player, "stargate.free", player.isOp()) || + iConomyHandler.chargePlayer(player.getName(), null, portal.getGate().getUseCost())) { + if (!portal.isFree() && iConomyHandler.useiConomy()) { + player.sendMessage(ChatColor.GREEN + "Deducted " + iConomy.getBank().format(portal.getGate().getUseCost())); + } + if (!teleMsg.isEmpty()) { + player.sendMessage(ChatColor.BLUE + teleMsg); + } + dest.teleport(vehicle, portal); + } else { + if (!iConomyHandler.inFundMsg.isEmpty()) { + player.sendMessage(ChatColor.RED + iConomyHandler.inFundMsg); + } + } + portal.close(false); + } + } + } + + private class pListener extends PlayerListener { + @Override + public void onPlayerMove(PlayerMoveEvent event) { + Player player = event.getPlayer(); + Portal portal = Portal.getByEntrance(event.getTo()); + + if ((portal != null) && (portal.isOpen())) { + if (portal.isOpenFor(player)) { + Portal destination = portal.getDestination(); + + if (destination != null) { + if (portal.isFree() || !iConomyHandler.useiConomy() || hasPerm(player, "stargate.free", player.isOp()) || + iConomyHandler.chargePlayer(player.getName(), null, portal.getGate().getUseCost())) { + if (!portal.isFree() && iConomyHandler.useiConomy()) { + player.sendMessage(ChatColor.GREEN + "Deducted " + iConomy.getBank().format(portal.getGate().getUseCost())); + } + if (!teleMsg.isEmpty()) { + player.sendMessage(ChatColor.BLUE + teleMsg); + } + + destination.teleport(player, portal, event); + } else { + if (!iConomyHandler.inFundMsg.isEmpty()) { + player.sendMessage(ChatColor.RED + iConomyHandler.inFundMsg); + } + } + portal.close(false); + } + } else { + if (!denyMsg.isEmpty()) { + player.sendMessage(ChatColor.RED + denyMsg); + } + } + } + } + + @Override + public void onPlayerInteract(PlayerInteractEvent event) { + Player player = event.getPlayer(); + Block block = event.getClickedBlock(); + + // Right click + if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { + if (block.getType() == Material.WALL_SIGN) { + Portal portal = Portal.getByBlock(block); + // Cycle through a stargates locations + if (portal != null) { + if (!hasPerm(player, "stargate.use", true) || + (networkFilter && !hasPerm(player, "stargate.network." + portal.getNetwork(), player.isOp()))) { + if (!denyMsg.isEmpty()) { + player.sendMessage(denyMsg); + } + return; + } + + if ((!portal.isOpen()) && (!portal.isFixed())) { + portal.cycleDestination(player); + } + } + } + + // Implement right-click to toggle a stargate, gets around spawn protection problem. + if ((block.getType() == Material.STONE_BUTTON)) { + if (hasPerm(player, "stargate.use", true)) { + Portal portal = Portal.getByBlock(block); + if (portal != null) { + onButtonPressed(player, portal); + } + } + } + } + + // Left click + if (event.getAction() == Action.LEFT_CLICK_BLOCK) { + // Check if we're pushing a button. + if (block.getType() == Material.STONE_BUTTON) { + if (hasPerm(player, "stargate.use", true)) { + Portal portal = Portal.getByBlock(block); + if (portal != null) { + onButtonPressed(player, portal); + } + } + } + } + } + } + + private class bListener extends BlockListener { + @Override + public void onBlockPlace(BlockPlaceEvent event) { + // Stop player from placing a block touching a portals controls + if (event.getBlockAgainst().getType() == Material.STONE_BUTTON || + event.getBlockAgainst().getType() == Material.WALL_SIGN) { + Portal portal = Portal.getByBlock(event.getBlockAgainst()); + if (portal != null) event.setCancelled(true); + } + } + + @Override + public void onSignChange(SignChangeEvent event) { + Player player = event.getPlayer(); + Block block = event.getBlock(); + if (block.getType() != Material.WALL_SIGN) return; + + // Initialize a stargate + if (hasPerm(player, "stargate.create", player.isOp()) || + hasPerm(player, "stargate.create.personal", false)) { + SignPost sign = new SignPost(new Blox(block)); + // Set sign text so we can create a gate with it. + sign.setText(0, event.getLine(0)); + sign.setText(1, event.getLine(1)); + sign.setText(2, event.getLine(2)); + sign.setText(3, event.getLine(3)); + Portal portal = Portal.createPortal(sign, player); + if (portal == null) return; + + if (iConomyHandler.useiConomy()) { + player.sendMessage(ChatColor.GREEN + "Deducted " + iConomy.getBank().format(portal.getGate().getCreateCost())); + } + if (!regMsg.isEmpty()) { + player.sendMessage(ChatColor.GREEN + regMsg); + } + log.info("[Stargate] Initialized stargate: " + portal.getName()); + portal.drawSign(); + // Set event text so our new sign is instantly initialized + event.setLine(0, sign.getText(0)); + event.setLine(1, sign.getText(1)); + event.setLine(2, sign.getText(2)); + event.setLine(3, sign.getText(3)); + } + } + + @Override + public void onBlockBreak(BlockBreakEvent event) { + Block block = event.getBlock(); + Player player = event.getPlayer(); + if (block.getType() != Material.WALL_SIGN && block.getType() != Material.STONE_BUTTON && Gate.getGatesByControlBlock(block).length == 0) { + return; + } + + Portal portal = Portal.getByBlock(block); + if (portal == null) return; + + if (hasPerm(player, "stargate.destroy", player.isOp()) || hasPerm(player, "stargate.destroy.all", player.isOp()) || + ( portal.getOwner().equalsIgnoreCase(player.getName()) && hasPerm(player, "stargate.destroy.owner", false) )) { + // Can't afford + if (iConomyHandler.useiConomy()) { + if(iConomyHandler.getBalance(player.getName()) < portal.getGate().getDestroyCost()) { + if (!iConomyHandler.inFundMsg.isEmpty()) { + player.sendMessage(ChatColor.RED + iConomyHandler.inFundMsg); + event.setCancelled(true); + return; + } + } + iConomyHandler.chargePlayer(player.getName(), null, portal.getGate().getDestroyCost()); + if (portal.getGate().getDestroyCost() > 0) { + player.sendMessage(ChatColor.GREEN + "Deducted " + iConomy.getBank().format(portal.getGate().getDestroyCost())); + } else if (portal.getGate().getDestroyCost() < 0) { + player.sendMessage(ChatColor.GREEN + "Refunded " + iConomy.getBank().format(-portal.getGate().getDestroyCost())); + } + } + + portal.unregister(true); + if (!dmgMsg.isEmpty()) { + player.sendMessage(ChatColor.RED + dmgMsg); + } + return; + } + + event.setCancelled(true); + } + + @Override + public void onBlockPhysics(BlockPhysicsEvent event) { + Block block = event.getBlock(); + if (block.getType() == Material.PORTAL) { + event.setCancelled((Portal.getByEntrance(block) != null)); + } + } + + @Override + public void onBlockFromTo(BlockFromToEvent event) { + Portal portal = Portal.getByEntrance(event.getBlock()); + + if (portal != null) { + event.setCancelled((event.getBlock().getY() == event.getToBlock().getY())); + } + } + } + + private class wListener extends WorldListener { + @Override + public void onWorldLoad(WorldLoadEvent event) { + World w = event.getWorld(); + // We have to make sure the world is actually loaded. This gets called twice for some reason. + if (w.getBlockAt(w.getSpawnLocation()).getWorld() != null) { + Portal.loadAllGates(w); + } + } + } + + private class eListener extends EntityListener { + @Override + public void onEntityExplode(EntityExplodeEvent event) { + if (event.isCancelled()) return; + for (Block b : event.blockList()) { + if (b.getTypeId() != Material.WALL_SIGN.getId() && b.getTypeId() != Material.STONE_BUTTON.getId()) continue; + Portal portal = Portal.getByBlock(b); + if (portal == null) continue; + if (destroyExplosion) { + portal.unregister(true); + } else { + b.setType(b.getType()); + event.setCancelled(true); + } + } + } + } + + private class sListener extends ServerListener { + @Override + public void onPluginEnable(PluginEnableEvent event) { + if (iConomyHandler.iconomy == null) { + if (event.getPlugin().getDescription().getName().equalsIgnoreCase("iConomy")) { + iConomyHandler.iconomy = (iConomy)checkPlugin(event.getPlugin()); + } + } + if (permissions == null) { + if (event.getPlugin().getDescription().getName().equalsIgnoreCase("Permissions")) { + permissions = (Permissions)checkPlugin(event.getPlugin()); + } + } + } + + @Override + public void onPluginDisable(PluginDisableEvent event) { + if (event.getPlugin() == iConomyHandler.iconomy) { + log.info("[Stargate] iConomy plugin lost."); + iConomyHandler.iconomy = null; + } + if (event.getPlugin() == permissions) { + log.info("[Stargate] Permissions plugin lost."); + permissions = null; + } + } + } + + private class SGThread implements Runnable { + public void run() { + long time = System.currentTimeMillis() / 1000; + // Close open portals + for (Iterator iter = Stargate.openList.iterator(); iter.hasNext();) { + Portal p = iter.next(); + if (time > p.getOpenTime() + Stargate.openLimit) { + p.close(false); + iter.remove(); + } + } + // Deactivate active portals + for (Iterator iter = Stargate.activeList.iterator(); iter.hasNext();) { + Portal p = iter.next(); + if (time > p.getOpenTime() + Stargate.activeLimit) { + p.deactivate(); + iter.remove(); + } + } + } + } +} diff --git a/src/plugin.yml b/src/plugin.yml index 5533219..2124340 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -1,6 +1,6 @@ -name: Stargate -main: net.TheDgtl.Stargate.Stargate -version: 0.3.4 -description: Stargate mod for Bukkit -author: Drakia +name: Stargate +main: net.TheDgtl.Stargate.Stargate +version: 0.3.5 +description: Stargate mod for Bukkit +author: Drakia website: http://www.thedgtl.net \ No newline at end of file