diff --git a/README b/README index bd2f189..95e92b9 100644 --- a/README +++ b/README @@ -30,6 +30,7 @@ Hmm.. None? - stargate.option.alwayson - Allow this user/group to create always-on gates. - stargate.option.private - Allow this user/group to create private gates. - stargate.option.free - Allow this user/group to create free gates. + - stargate.option.backwards - Allow this user/group to create backwards gates. ============= Instructions @@ -45,7 +46,12 @@ 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) + - 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 + 'B' is for a backwards facing gate (You will exit the back) Options: The options are the single letter, not the word. So to make a private hidden gate, your 4th line would be 'PH'. @@ -100,6 +106,9 @@ portal-open/closed are used to define the material in the gate when it is open o "X" and "-" are used to define block "types" for the layout (Any single-character can be used, such as "#"). In the gate format, you can see we use "X" to show where obsidian must be, "-" where the controls (Button/sign) are. You will also notice a "*" in the gate layout, this is the "exit point" of the gate, the block at which the player will teleport in front of. +As of version 0.5.5 you can supply block data in the format +X=35:15 +Which would only allow black wool. If no data is supplied any version of a block will work (Any color of wool for example) ============== Configuration @@ -130,6 +139,10 @@ maxgates - If non-zero, will define the maximum amount of gates allowed on a net ============= Changes ============= +[Version 0.5.5] + - Added 'B'ackwards option + - Fixed opening of gates with a fixed gate as a destination + - Added block metadata support to gates [Version 0.5.1] - Take into account world/network restrictions for Vehicles - Properly teleport empty vehicles between worlds diff --git a/src/net/TheDgtl/Stargate/Gate.java b/src/net/TheDgtl/Stargate/Gate.java index b925d95..14bd3ab 100644 --- a/src/net/TheDgtl/Stargate/Gate.java +++ b/src/net/TheDgtl/Stargate/Gate.java @@ -31,8 +31,9 @@ public class Gate { private static HashSet frameBlocks = new HashSet(); private String filename; - private Integer[][] layout; + private Character[][] layout; private HashMap types; + private HashMap metadata; private RelativeBlockVector[] entrances = new RelativeBlockVector[0]; private RelativeBlockVector[] border = new RelativeBlockVector[0]; private RelativeBlockVector[] controls = new RelativeBlockVector[0]; @@ -47,9 +48,10 @@ public class Gate { private int destroyCost = 0; private boolean toOwner = false; - private Gate(String filename, Integer[][] layout, HashMap types) { + private Gate(String filename, Character[][] layout, HashMap types, HashMap metadata) { this.filename = filename; this.layout = layout; + this.metadata = metadata; this.types = types; populateCoordinates(); @@ -61,21 +63,20 @@ public class Gate { ArrayList controlList = new ArrayList(); RelativeBlockVector[] relativeExits = new RelativeBlockVector[layout[0].length]; int[] exitDepths = new int[layout[0].length]; - //int bottom = 0; RelativeBlockVector lastExit = null; for (int y = 0; y < layout.length; y++) { for (int x = 0; x < layout[y].length; x++) { - Integer id = layout[y][x]; + Integer id = types.get(layout[y][x]); + if (layout[y][x] == '-') { + controlList.add(new RelativeBlockVector(x, y, 0)); + } if (id == ENTRANCE || id == EXIT) { entranceList.add(new RelativeBlockVector(x, y, 0)); exitDepths[x] = y; if (id == EXIT) this.exitBlock = new RelativeBlockVector(x, y, 0); - //bottom = y; - } else if (id == CONTROL) { - controlList.add(new RelativeBlockVector(x, y, 0)); } else if (id != ANYTHING) { borderList.add(new RelativeBlockVector(x, y, 0)); } @@ -102,8 +103,6 @@ public class Gate { } public void save(String gateFolder) { - HashMap reverse = new HashMap(); - try { BufferedWriter bw = new BufferedWriter(new FileWriter(gateFolder + filename)); @@ -119,14 +118,18 @@ public class Gate { for (Character type : types.keySet()) { Integer value = types.get(type); - - if (!type.equals('-')) { - reverse.put(value, type); - } + // Skip control values + if (value < 0) continue; bw.append(type); bw.append('='); bw.append(value.toString()); + Integer mData = metadata.get(type); + // Append metadata + if (mData != null) { + bw.append(':'); + bw.append(mData.toString()); + } bw.newLine(); } @@ -134,23 +137,7 @@ public class Gate { for (int y = 0; y < layout.length; y++) { for (int x = 0; x < layout[y].length; x++) { - Integer id = layout[y][x]; - Character symbol; - - if (id == ENTRANCE) { - symbol = '.'; - } else if (id == ANYTHING) { - symbol = ' '; - } else if (id == CONTROL) { - symbol = '-'; - } else if (id == EXIT) { - symbol = '*'; - } else if (reverse.containsKey(id)) { - symbol = reverse.get(id); - } else { - symbol = '?'; - } - + Character symbol = layout[y][x]; bw.append(symbol); } bw.newLine(); @@ -158,7 +145,7 @@ public class Gate { bw.close(); } catch (IOException ex) { - Stargate.log.log(Level.SEVERE, "Could not load Gate " + filename + " - " + ex.getMessage()); + Stargate.log.log(Level.SEVERE, "Could not save Gate " + filename + " - " + ex.getMessage()); } } @@ -172,7 +159,7 @@ public class Gate { bw.newLine(); } - public Integer[][] getLayout() { + public Character[][] getLayout() { return layout; } @@ -234,20 +221,20 @@ public class Gate { public boolean matches(Blox topleft, int modX, int modZ) { for (int y = 0; y < layout.length; y++) { for (int x = 0; x < layout[y].length; x++) { - int id = layout[y][x]; + int id = types.get(layout[y][x]); if (id == ENTRANCE || id == EXIT) { if (topleft.modRelative(x, y, 0, modX, 1, modZ).getType() != portalBlockClosed) { return false; } - } else if (id == CONTROL) { - if (topleft.modRelative(x, y, 0, modX, 1, modZ).getType() != getControlBlock()) { - return false; - } } else if (id != ANYTHING) { if (topleft.modRelative(x, y, 0, modX, 1, modZ).getType() != id) { return false; } + Integer mData = metadata.get(layout[y][x]); + if (mData != null && topleft.modRelative(x, y, 0, modX, 1, modZ).getData() != mData) { + return false; + } } } } @@ -270,10 +257,16 @@ public class Gate { private static Gate loadGate(File file) { Scanner scanner = null; boolean designing = false; - ArrayList> design = new ArrayList>(); + ArrayList> design = new ArrayList>(); HashMap types = new HashMap(); + HashMap metadata = new HashMap(); HashMap config = new HashMap(); int cols = 0; + + // Init types map + types.put('.', ENTRANCE); + types.put('*', EXIT); + types.put(' ', ANYTHING); try { scanner = new Scanner(file); @@ -282,31 +275,18 @@ public class Gate { String line = scanner.nextLine(); if (designing) { - ArrayList row = new ArrayList(); + ArrayList row = new ArrayList(); if (line.length() > cols) { cols = line.length(); } for (Character symbol : line.toCharArray()) { - Integer id = ANYTHING; - - if (symbol.equals('.')) { - id = ENTRANCE; - } else if (symbol.equals('*')) { - id = EXIT; - } else if (symbol.equals(' ')) { - id = ANYTHING; - } else if (symbol.equals('-')) { - id = CONTROL; - } else if ((symbol.equals('?')) || (!types.containsKey(symbol))) { + if ((symbol.equals('?')) || (!types.containsKey(symbol))) { Stargate.log.log(Level.SEVERE, "Could not load Gate " + file.getName() + " - Unknown symbol '" + symbol + "' in diagram"); return null; - } else { - id = types.get(symbol); } - - row.add(id); + row.add(symbol); } design.add(row); @@ -320,6 +300,13 @@ public class Gate { if (key.length() == 1) { Character symbol = key.charAt(0); + // Check for metadata + if (value.contains(":")) { + split = value.split(":"); + value = split[0].trim(); + String mData = split[1].trim(); + metadata.put(symbol, Integer.parseInt(mData)); + } Integer id = Integer.parseInt(value); types.put(symbol, id); @@ -337,24 +324,24 @@ public class Gate { if (scanner != null) scanner.close(); } - Integer[][] layout = new Integer[design.size()][cols]; + Character[][] layout = new Character[design.size()][cols]; for (int y = 0; y < design.size(); y++) { - ArrayList row = design.get(y); - Integer[] result = new Integer[cols]; + ArrayList row = design.get(y); + Character[] result = new Character[cols]; for (int x = 0; x < cols; x++) { if (x < row.size()) { result[x] = row.get(x); } else { - result[x] = ANYTHING; + result[x] = ' '; } } layout[y] = result; } - Gate gate = new Gate(file.getName(), layout, types); + Gate gate = new Gate(file.getName(), layout, types, metadata); gate.portalBlockOpen = readConfig(config, gate, file, "portal-open", gate.portalBlockOpen); gate.portalBlockClosed = readConfig(config, gate, file, "portal-closed", gate.portalBlockClosed); @@ -407,18 +394,22 @@ public class Gate { public static void populateDefaults(String gateFolder) { int Obsidian = Material.OBSIDIAN.getId(); - Integer[][] layout = new Integer[][] { - {ANYTHING, Obsidian,Obsidian, ANYTHING}, - {Obsidian, ENTRANCE, ENTRANCE, Obsidian}, - {CONTROL, ENTRANCE, ENTRANCE, CONTROL}, - {Obsidian, EXIT, ENTRANCE, Obsidian}, - {ANYTHING, Obsidian, Obsidian, ANYTHING}, + Character[][] layout = new Character[][] { + {' ', 'X','X', ' '}, + {'X', '.', '.', 'X'}, + {'-', '.', '.', '-'}, + {'X', '*', '.', 'X'}, + {' ', 'X', 'X', ' '}, }; HashMap types = new HashMap(); + types.put('.', ENTRANCE); + types.put('*', EXIT); + types.put(' ', ANYTHING); types.put('X', Obsidian); types.put('-', Obsidian); + HashMap metadata = new HashMap(); - Gate gate = new Gate("nethergate.gate", layout, types); + Gate gate = new Gate("nethergate.gate", layout, types, metadata); gate.save(gateFolder); registerGate(gate); } diff --git a/src/net/TheDgtl/Stargate/Portal.java b/src/net/TheDgtl/Stargate/Portal.java index c1d3d44..0765bd7 100644 --- a/src/net/TheDgtl/Stargate/Portal.java +++ b/src/net/TheDgtl/Stargate/Portal.java @@ -16,7 +16,6 @@ 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.StorageMinecart; import org.bukkit.entity.Vehicle; @@ -56,10 +55,13 @@ public class Portal { private String network; private Gate gate; private String owner = ""; + // Options private boolean hidden = false; private boolean alwaysOn = false; private boolean priv = false; private boolean free = false; + private boolean backwards = false; + private World world; // Gate options private boolean verified; @@ -74,8 +76,8 @@ public class Portal { 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) { + boolean verified, String network, Gate gate, String owner, + boolean hidden, boolean alwaysOn, boolean priv, boolean free, boolean backwards) { this.topLeft = topLeft; this.modX = modX; this.modZ = modZ; @@ -93,6 +95,7 @@ public class Portal { this.alwaysOn = alwaysOn; this.priv = priv; this.free = free; + this.backwards = backwards; this.world = topLeft.getWorld(); if (this.alwaysOn && !this.fixed) { @@ -126,6 +129,10 @@ public class Portal { return free; } + public boolean isBackwards() { + return backwards; + } + public boolean isFree(Player player, Portal dest) { // This gate is free, the player gets all gates free, or we don't charge for free dest and dest is free boolean isFree = isFree() || Stargate.hasPerm(player, "stargate.free.use", player.isOp()) || @@ -155,7 +162,7 @@ public class Portal { player = openFor; Portal end = getDestination(); - if (end != null && !end.isFixed() && !end.isOpen()) { + if (end != null && !end.isAlwaysOn() && !end.isOpen()) { end.open(openFor, false); end.setDestination(this); if (end.isVerified()) end.drawSign(); @@ -218,7 +225,9 @@ public class Portal { Location traveller = player.getLocation(); Location exit = getExit(traveller); - exit.setYaw(origin.getRotation() - traveller.getYaw() + this.getRotation() + 180); + // Handle backwards gates + int adjust = isBackwards() ? 0 :180; + exit.setYaw(origin.getRotation() - traveller.getYaw() + this.getRotation() + adjust); // The new method to teleport in a move event is set the "to" field. event.setTo(exit); @@ -278,14 +287,14 @@ public class Portal { // 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); + int back = (isBackwards()) ? -1 : 1; + loc = exit.modRelativeLoc(0D, 0D, 1D, traveller.getYaw(), traveller.getPitch(), modX * back, 1, modZ * back); } else { Stargate.log.log(Level.WARNING, "[Stargate] Missing destination point in .gate file " + gate.getFilename()); } if (loc != null) { - Block block = getWorld().getBlockAt(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); - if (block.getType() == Material.STEP) { + if (getWorld().getBlockTypeIdAt(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()) == Material.STEP.getId()) { loc.setY(loc.getY() + 0.5); } @@ -517,17 +526,12 @@ public class Portal { public Blox[] getFrame() { if (frame == null) { RelativeBlockVector[] border = gate.getBorder(); - RelativeBlockVector[] controls = gate.getControls(); - frame = new Blox[border.length + controls.length]; + frame = new Blox[border.length]; int i = 0; for (RelativeBlockVector vector : border) { frame[i++] = getBlockAt(vector); } - - for (RelativeBlockVector vector : controls) { - frame[i++] = getBlockAt(vector); - } } return frame; @@ -631,12 +635,14 @@ public class Portal { 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); + boolean backwards = (options.indexOf('b') != -1 || options.indexOf('B') != -1); // Check permissions for options. if (!Stargate.hasPerm(player, "stargate.option.hidden", player.isOp())) hidden = false; if (!Stargate.hasPerm(player, "stargate.option.alwayson", player.isOp())) alwaysOn = false; if (!Stargate.hasPerm(player, "stargate.option.private", player.isOp())) priv = false; if (!Stargate.hasPerm(player, "stargate.option.free", player.isOp())) free = false; + if (!Stargate.hasPerm(player, "stargate.option.backwards", player.isOp())) backwards = false; // Can not create a non-fixed always-on gate. if (alwaysOn && destName.length() == 0) { @@ -644,7 +650,7 @@ public class Portal { } // Debug - Stargate.debug("createPortal", "h = " + hidden + " a = " + alwaysOn + " p = " + priv + " f = " + free); + Stargate.debug("createPortal", "h = " + hidden + " a = " + alwaysOn + " p = " + priv + " f = " + free + " b = " + backwards); if ((network.length() < 1) || (network.length() > 11)) { network = Stargate.getDefaultNetwork(); @@ -773,7 +779,7 @@ public class Portal { 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); + portal = new Portal(topleft, modX, modZ, rotX, id, button, destName, name, true, network, gate, player.getName(), hidden, alwaysOn, priv, free, backwards); // Open always on gate if (portal.isAlwaysOn()) { @@ -861,6 +867,8 @@ public class Portal { builder.append(portal.world.getName()); builder.append(':'); builder.append(portal.isFree()); + builder.append(':'); + builder.append(portal.isBackwards()); bw.append(builder.toString()); bw.newLine(); @@ -927,8 +935,9 @@ public class Portal { 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; + boolean backwards = (split.length > 16) ? split[16].equalsIgnoreCase("true") : false; - Portal portal = new Portal(topLeft, modX, modZ, rotX, sign, button, dest, name, false, network, gate, owner, hidden, alwaysOn, priv, free); + Portal portal = new Portal(topLeft, modX, modZ, rotX, sign, button, dest, name, false, network, gate, owner, hidden, alwaysOn, priv, free, backwards); portal.close(true); } scanner.close(); diff --git a/src/plugin.yml b/src/plugin.yml index 125880f..cb75502 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -1,6 +1,6 @@ name: Stargate main: net.TheDgtl.Stargate.Stargate -version: 0.5.1 +version: 0.5.5 description: Stargate mod for Bukkit author: Drakia website: http://www.thedgtl.net