commit eb407537f2ae52ff010cbd9673e5ae59451a726f Author: Drakia Date: Sun Feb 6 03:36:48 2011 -0800 Initial commit diff --git a/src/com/bukkit/TheDgtl/Stargate/Blox.java b/src/com/bukkit/TheDgtl/Stargate/Blox.java new file mode 100644 index 0000000..7c02877 --- /dev/null +++ b/src/com/bukkit/TheDgtl/Stargate/Blox.java @@ -0,0 +1,125 @@ +package com.bukkit.TheDgtl.Stargate; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.Block; + +public class Blox { + private int x; + private int y; + private int z; + private World world; + + public Blox (World world, int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + this.world = world; + } + + public Blox (Block block) { + this.x = block.getX(); + this.y = block.getY(); + this.z = block.getZ(); + this.world = block.getWorld(); + } + + public Blox (Location location) { + this.x = location.getBlockX(); + this.y = location.getBlockY(); + this.z = location.getBlockZ(); + this.world = location.getWorld(); + } + + public Blox (World world, String string) { + String[] split = string.split(","); + this.x = Integer.parseInt(split[0]); + this.y = Integer.parseInt(split[1]); + this.z = Integer.parseInt(split[2]); + this.world = world; + } + + public Blox makeRelative(int x, int y, int z) { + return new Blox(this.world, this.x + x, this.y + y, this.z + z); + } + + public Location makeRelativeLoc(double x, double y, double z, float rotX, float rotY) { + return new Location(this.world, (double)this.x + x, (double)this.y + y, (double)this.z + z, rotX, rotY); + } + + public Blox modRelative(int right, int depth, int distance, int modX, int modY, int modZ) { + return makeRelative(-right * modX + distance * modZ, -depth * modY, -right * modZ + -distance * modX); + } + + public Location modRelativeLoc(double right, double depth, double distance, float rotX, float rotY, int modX, int modY, int modZ) { + return makeRelativeLoc(0.5 + -right * modX + distance * modZ, depth, 0.5 + -right * modZ + -distance * modX, rotX, 0); + } + + public void setType(int type) { + world.getBlockAt(x, y, z).setTypeId(type); + } + + public int getType() { + return world.getBlockAt(x, y, z).getTypeId(); + } + + public void setData(int data) { + world.getBlockAt(x, y, z).setData((byte)data); + } + + public int getData() { + return world.getBlockAt(x, y, z).getData(); + } + + public Block getBlock() { + return world.getBlockAt(x, y, z); + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public int getZ() { + return z; + } + + public World getWorld() { + return world; + } + + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(x); + builder.append(','); + builder.append(y); + builder.append(','); + builder.append(z); + return builder.toString(); + } + + @Override + public int hashCode() { + int result = 0; + + result += x * 92821; + result += y * 92821; + result += z * 92821; + + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + + Blox blox = (Blox) obj; + + return (x == blox.x) && (y == blox.y) && (z == blox.z); + } +} \ No newline at end of file diff --git a/src/com/bukkit/TheDgtl/Stargate/Gate.java b/src/com/bukkit/TheDgtl/Stargate/Gate.java new file mode 100644 index 0000000..d0cf1aa --- /dev/null +++ b/src/com/bukkit/TheDgtl/Stargate/Gate.java @@ -0,0 +1,399 @@ +package com.bukkit.TheDgtl.Stargate; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.FilenameFilter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Scanner; +import java.util.logging.Level; + +import org.bukkit.Material; +import org.bukkit.block.Block; + +/** + * Gate.java - Plug-in for hey0's minecraft mod. + * @author Shaun (sturmeh) + * @author Dinnerbone + */ +public class Gate { + public static final int ANYTHING = -1; + public static final int ENTRANCE = -2; + public static final int CONTROL = -3; + private static HashMap gates = new HashMap(); + private static HashMap> controlBlocks = new HashMap>(); + + private String filename; + private Integer[][] layout; + private HashMap types; + private RelativeBlockVector[] entrances = new RelativeBlockVector[0]; + private RelativeBlockVector[] border = new RelativeBlockVector[0]; + private RelativeBlockVector[] controls = new RelativeBlockVector[0]; + private HashMap exits = new HashMap(); + private int portalBlockOpen = Material.PORTAL.getId(); + private int portalBlockClosed = Material.AIR.getId(); + + private Gate(String filename, Integer[][] layout, HashMap types) { + this.filename = filename; + this.layout = layout; + this.types = types; + + populateCoordinates(); + } + + private void populateCoordinates() { + ArrayList entranceList = new ArrayList(); + ArrayList borderList = new ArrayList(); + 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]; + + if (id == ENTRANCE) { + entranceList.add(new RelativeBlockVector(x, y, 0)); + exitDepths[x] = y; + //bottom = y; + } else if (id == CONTROL) { + controlList.add(new RelativeBlockVector(x, y, 0)); + } else if (id != ANYTHING) { + borderList.add(new RelativeBlockVector(x, y, 0)); + } + } + } + + for (int x = 0; x < exitDepths.length; x++) { + relativeExits[x] = new RelativeBlockVector(x, exitDepths[x], 0); + } + + for (int x = relativeExits.length - 1; x >= 0; x--) { + if (relativeExits[x] != null) { + lastExit = relativeExits[x]; + } else { + relativeExits[x] = lastExit; + } + + if (exitDepths[x] > 0) this.exits.put(relativeExits[x], x); + } + + this.entrances = entranceList.toArray(this.entrances); + this.border = borderList.toArray(this.border); + this.controls = controlList.toArray(this.controls); + } + + public void save() { + HashMap reverse = new HashMap(); + + try { + BufferedWriter bw = new BufferedWriter(new FileWriter("stargates/" + filename)); + + writeConfig(bw, "portal-open", portalBlockOpen); + writeConfig(bw, "portal-closed", portalBlockClosed); + + for (Character type : types.keySet()) { + Integer value = types.get(type); + + if (!type.equals('-')) { + reverse.put(value, type); + } + + bw.append(type); + bw.append('='); + bw.append(value.toString()); + bw.newLine(); + } + + bw.newLine(); + + 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 (reverse.containsKey(id)) { + symbol = reverse.get(id); + } else { + symbol = '?'; + } + + bw.append(symbol); + } + bw.newLine(); + } + + bw.close(); + } catch (IOException ex) { + Stargate.log.log(Level.SEVERE, "Could not load Gate " + filename + " - " + ex.getMessage()); + } + } + + private void writeConfig(BufferedWriter bw, String key, int value) throws IOException { + bw.append(String.format("%s=%d", key, value)); + bw.newLine(); + } + + public Integer[][] getLayout() { + return layout; + } + + public RelativeBlockVector[] getEntrances() { + return entrances; + } + + public RelativeBlockVector[] getBorder() { + return border; + } + + public RelativeBlockVector[] getControls() { + return controls; + } + + public HashMap getExits() { + return exits; + } + + public int getControlBlock() { + return types.get('-'); + } + + public String getFilename() { + return filename; + } + + public int getPortalBlockOpen() { + return portalBlockOpen; + } + + public int getPortalBlockClosed() { + return portalBlockClosed; + } + + public boolean matches(Block topleft, int modX, int modZ) { + return matches(new Blox(topleft), modX, modZ); + } + + 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]; + + if (id == ENTRANCE) { + if (topleft.modRelative(x, y, 0, modX, 1, modZ).getType() != 0) { + 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; + } + } + } + } + + return true; + } + + private static void registerGate(Gate gate) { + gates.put(gate.getFilename(), gate); + + int blockID = gate.getControlBlock(); + + if (!controlBlocks.containsKey(blockID)) { + controlBlocks.put(blockID, new ArrayList()); + } + + controlBlocks.get(blockID).add(gate); + } + + private static Gate loadGate(File file) { + Scanner scanner = null; + boolean designing = false; + ArrayList> design = new ArrayList>(); + HashMap types = new HashMap(); + HashMap config = new HashMap(); + int cols = 0; + + try { + scanner = new Scanner(file); + + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + + if (designing) { + 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 = ANYTHING; + } else if (symbol.equals('-')) { + id = CONTROL; + } else 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); + } + + design.add(row); + } else { + if ((line.isEmpty()) || (!line.contains("="))) { + designing = true; + } else { + String[] split = line.split("="); + String key = split[0].trim(); + String value = split[1].trim(); + + if (key.length() == 1) { + Character symbol = key.charAt(0); + Integer id = Integer.parseInt(value); + + types.put(symbol, id); + } else { + config.put(key, value); + } + } + } + } + } catch (Exception ex) { + Stargate.log.log(Level.SEVERE, "Could not load Gate " + file.getName() + " - Invalid block ID given"); + return null; + } finally { + if (scanner != null) scanner.close(); + } + + Integer[][] layout = new Integer[design.size()][cols]; + + for (int y = 0; y < design.size(); y++) { + ArrayList row = design.get(y); + Integer[] result = new Integer[cols]; + + for (int x = 0; x < cols; x++) { + if (x < row.size()) { + result[x] = row.get(x); + } else { + result[x] = ANYTHING; + } + } + + layout[y] = result; + } + + Gate gate = new Gate(file.getName(), layout, types); + + gate.portalBlockOpen = readConfig(config, gate, file, "portal-open", gate.portalBlockOpen); + gate.portalBlockClosed = readConfig(config, gate, file, "portal-closed", gate.portalBlockClosed); + + if (gate.getControls().length != 2) { + Stargate.log.log(Level.SEVERE, "Could not load Gate " + file.getName() + " - Gates must have exactly 2 control points."); + return null; + } else { + gate.save(); // Updates format for version changes + return gate; + } + } + + private static int readConfig(HashMap config, Gate gate, File file, String key, int def) { + if (config.containsKey(key)) { + try { + return Integer.parseInt(config.get(key)); + } catch (NumberFormatException ex) { + Stargate.log.log(Level.WARNING, String.format("%s reading %s: %s is not numeric", ex.getClass().getName(), file, key)); + } + } + + return def; + } + + public static void loadGates() { + File dir = new File("stargates"); + File[] files; + + if (dir.exists()) { + files = dir.listFiles(new StargateFilenameFilter()); + } else { + files = new File[0]; + } + + if (files.length == 0) { + dir.mkdir(); + populateDefaults(dir); + } else { + for (File file : files) { + Gate gate = loadGate(file); + if (gate != null) registerGate(gate); + } + } + } + + public static void populateDefaults(File dir) { + Integer[][] layout = new Integer[][] { + {ANYTHING, Portal.OBSIDIAN, Portal.OBSIDIAN, ANYTHING}, + {Portal.OBSIDIAN, ENTRANCE, ENTRANCE, Portal.OBSIDIAN}, + {CONTROL, ENTRANCE, ENTRANCE, CONTROL}, + {Portal.OBSIDIAN, ENTRANCE, ENTRANCE, Portal.OBSIDIAN}, + {ANYTHING, Portal.OBSIDIAN, Portal.OBSIDIAN, ANYTHING}, + }; + HashMap types = new HashMap(); + types.put('X', Portal.OBSIDIAN); + types.put('-', Portal.OBSIDIAN); + + Gate gate = new Gate("nethergate.gate", layout, types); + gate.save(); + registerGate(gate); + } + + public static Gate[] getGatesByControlBlock(Block block) { + return getGatesByControlBlock(block.getTypeId()); + } + + public static Gate[] getGatesByControlBlock(int type) { + Gate[] result = new Gate[0]; + ArrayList lookup = controlBlocks.get(type); + + if (lookup != null) result = lookup.toArray(result); + + return result; + } + + public static Gate getGateByName(String name) { + return gates.get(name); + } + + static class StargateFilenameFilter implements FilenameFilter { + public boolean accept(File dir, String name) { + return name.endsWith(".gate"); + } + } + + public enum CostFor { + Using, + Activating, + Creating + }; +} diff --git a/src/com/bukkit/TheDgtl/Stargate/Portal.java b/src/com/bukkit/TheDgtl/Stargate/Portal.java new file mode 100644 index 0000000..f0e2c5c --- /dev/null +++ b/src/com/bukkit/TheDgtl/Stargate/Portal.java @@ -0,0 +1,836 @@ +package com.bukkit.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.Scanner; +import java.util.Set; +import java.util.logging.Level; + +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.Player; +import org.bukkit.entity.Vehicle; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.material.Button; +import org.bukkit.material.MaterialData; + +/** + * Portal.java - Plug-in for hey0's minecraft mod. + * @author Shaun (sturmeh) + * @author Dinnerbone + */ +public class Portal { + public static final int OBSIDIAN = 49; + public static final int FIRE = 51; + public static final int SIGN = 68; + public static final int BUTTON = 77; + private static final HashMap lookupBlocks = new HashMap(); + private static final HashMap lookupNames = new HashMap(); + private static final HashMap lookupEntrances = new HashMap(); + private static final ArrayList allPortals = new ArrayList(); + private Blox topLeft; + private int modX; + private int modZ; + private float rotX; + private SignPost id; + private String name; + private String destination; + private Blox button; + private Player player; + private Blox[] frame; + private Blox[] entrances; + private boolean verified; + private boolean fixed; + private boolean gracePeriod; + private ArrayList destinations = new ArrayList(); + private String network; + private Gate gate; + private boolean isOpen = false; + private String owner = ""; + private HashMap exits; + private HashMap reverseExits; + private boolean hidden = false; + private Player activePlayer; + private boolean alwaysOn = false; + private World world; + + 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) { + 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.gracePeriod = false; + this.network = network; + this.name = name; + this.gate = gate; + this.owner = owner; + this.hidden = hidden; + this.alwaysOn = alwaysOn; + 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(true); + } + } + + public synchronized boolean manipGrace(boolean set, boolean var) { + if (!set) { + return gracePeriod; + } + gracePeriod = var; + return false; + } + + private boolean pastGrace() { + if (isAlwaysOn()) return false; // Ignore always open fixed gates. + if (manipGrace(false, false)) { + return manipGrace(true, false); + } + if (isActive() || isOpen()) { + return true; + } + return false; // else. + } + + public boolean isOpen() { + return isOpen || isAlwaysOn(); + } + + public boolean isAlwaysOn() { + return alwaysOn && isFixed(); + } + + public boolean isHidden() { + return hidden; + } + + 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; + // Open remote gate + if (!isFixed()) { + player = openFor; + manipGrace(true, true); + + Portal end = getDestination(); + if (end != null && !end.isOpen()) { + end.open(openFor, false); + end.setDestination(this); + if (end.isVerified()) end.drawSign(true); + } + } + + return true; + } + + public void close(boolean force) { + if (isAlwaysOn() && !force) return; // Never close an always open gate + if (!isFixed()) { + Portal end = getDestination(); + + if (end != null && end.isOpen()) { + end.deactivate(); // Clear it's destination first. + end.close(false); + } + } + + for (Blox inside : getEntrances()) { + inside.setType(gate.getPortalBlockClosed()); + } + + player = null; + isOpen = 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.teleportTo(exit); + event.setCancelled(true); + } + + public Location teleport(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 motX = vehicle.getVelocity().getX(); + double motY = vehicle.getVelocity().getY(); + double motZ = vehicle.getVelocity().getZ(); + + int xx = origin.modX * this.modX; + int xz = origin.modX * this.modZ; + int zx = origin.modZ * this.modX; + int zz = origin.modZ * this.modZ; + + vehicle.getVelocity().zero(); + vehicle.teleportTo(exit); + + return new Location(this.world, (motX * zz + motZ * xz) * 1, motY, (motX * zx + motZ * xx) * -1); + } + + public Location getExit(Location traveller, Portal origin) { + Block entrance = world.getBlockAt((int)Math.floor(traveller.getX()), (int)Math.floor(traveller.getY()), (int)Math.floor(traveller.getZ())); + HashMap originExits = origin.getExits(); + HashMap destExits = this.getExits(); + + if (originExits.containsKey(entrance)) { + int position = (int)(((float)originExits.get(entrance) / originExits.size()) * destExits.size()); + Block exit = getReverseExits().get(position); + + if (exit != null) { + Location loc = new Blox(exit).modRelativeLoc(0D, 0D, 1D, traveller.getYaw(), traveller.getPitch(), modX, 1, modZ); + Block block = world.getBlockAt((int)Math.floor(loc.getX()), (int)Math.floor(loc.getY()), (int)Math.floor(loc.getZ())); + + if (block.getType() == Material.STEP) { + loc.setY(loc.getY() + 0.5); + } + + loc.setPitch(traveller.getPitch()); + return loc; + } + } + + Stargate.log.log(Level.WARNING, "No position found calculting route from " + this + " to " + origin); + Stargate.log.info(originExits.get(entrance) + " / " + originExits.size() + " * " + destExits.size()); + return traveller; + } + + public float getRotation() { + return rotX; + } + + public void setName(String name) { + this.name = filterName(name); + + drawSign(true); + } + + 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); + } + + public String getDestinationName() { + return destination; + } + + public boolean isVerified() { + verified = verified || getBlockAt(1, 0).getType() == OBSIDIAN; + 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(true); + activePlayer = player; + for (String dest : allPortals) { + Portal portal = getByName(dest); + if ( (portal.getNetwork().equalsIgnoreCase(network)) && // In the network + (!dest.equalsIgnoreCase(getName())) && // Not this portal + (!portal.isHidden() || Stargate.Permissions.has(player, "stargate.hidden") || portal.getOwner().equals(player.getName())) // Is not hidden, player can view hidden, or player created + ) { + destinations.add(dest); + } + } + } + + public void deactivate() { + if (fixed) { + return; + } + destinations.clear(); + destination = ""; + activePlayer = null; + drawSign(true); + } + + public boolean isActive() { + return fixed || (destinations.size() > 0); + } + + public Player getActivePlayer() { + return activePlayer; + } + + public String getNetwork() { + return network; + } + + 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); + } + + drawSign(true); + } + + public final void drawSign(boolean update) { + 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); + } else { + manipGrace(true, true); + 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, ""); + } + + if (update) { + 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 HashMap getExits() { + if (exits == null) { + exits = new HashMap(); + reverseExits = new HashMap(); + HashMap relativeExits = gate.getExits(); + Set exitBlocks = relativeExits.keySet(); + + for (RelativeBlockVector vector : exitBlocks) { + Block block = getBlockAt(vector).getBlock(); + Integer position = relativeExits.get(vector); + exits.put(block, position); + reverseExits.put(position, block); + } + } + + return exits; + } + + public HashMap getReverseExits() { + if (reverseExits == null) { + getExits(); + } + + return reverseExits; + } + + @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.getName().equalsIgnoreCase(portal.getName()); + } + + public void unregister() { + lookupNames.remove(getName().toLowerCase()); + + for (Blox block : getFrame()) { + lookupBlocks.remove(block.getBlock()); + } + // Include the sign and button + lookupBlocks.remove(id.getBlock()); + if (button != null) { + lookupBlocks.remove(button.getBlock()); + } + + for (Blox entrance : getEntrances()) { + lookupEntrances.remove(entrance.getBlock()); + } + + allPortals.remove(getName()); + close(true); + + 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 : allPortals) { + Portal origin = Portal.getByName(originName); + if ((origin != null) && (origin.isAlwaysOn()) && (origin.getDestinationName().equalsIgnoreCase(getName())) && (origin.isVerified())) { + origin.close(true); + } + } + + saveAllGates(); + } + + private Blox getBlockAt(int right, int depth) { + return getBlockAt(right, depth, 0); + } + + private Blox getBlockAt(RelativeBlockVector vector) { + return topLeft.modRelative(vector.getRight(), vector.getDepth(), vector.getDistance(), modX, 1, modZ); + } + + private Blox getBlockAt(int right, int depth, int distance) { + return topLeft.modRelative(right, depth, distance, modX, 1, modZ); + } + + private void register() { + lookupNames.put(getName().toLowerCase(), this); + + for (Blox block : getFrame()) { + lookupBlocks.put(block.getBlock(), this); + } + // Include the sign and button + lookupBlocks.put(id.getBlock(), this); + if (button != null) { + lookupBlocks.put(button.getBlock(), this); + } + + for (Blox entrance : getEntrances()) { + lookupEntrances.put(entrance.getBlock(), this); + } + + allPortals.add(getName()); + } + + @Override + public String toString() { + return String.format("Portal [id=%s, name=%s, type=%s]", id, name, gate.getFilename()); + } + + public static Portal createPortal(SignPost id, Player player) { + Block idParent = id.getParent(); + if (idParent.getType() != Material.OBSIDIAN) 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); + + // Can not create a non-fixed always-on gate. + if (alwaysOn && destName.length() == 0) { + alwaysOn = false; + } + + if ((name.length() < 1) || (name.length() > 11) || (getByName(name) != null)) { + return null; + } + if ((network.length() < 1) || (network.length() > 11)) { + network = Stargate.getDefaultNetwork(); + } + if (destName.length() > 0) { + network = ""; + } + + int modX = 0; + int modZ = 0; + float rotX = 0f; + + if (idParent.getX() > id.getBlock().getX()) { + modZ -= 1; + rotX = 90f; + } else if (idParent.getX() < id.getBlock().getX()) { + modZ += 1; + rotX = 270f; + } else if (idParent.getZ() > id.getBlock().getZ()) { + modX += 1; + rotX = 180f; + } else if (idParent.getZ() < id.getBlock().getZ()) { + modX -= 1; + rotX = 0f; + } + + 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; + } + + 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(BUTTON); + } + portal = new Portal(topleft, modX, modZ, rotX, id, button, destName, name, true, network, gate, player.getName(), hidden, alwaysOn); + + // Open always on gate + if (portal.isAlwaysOn()) { + Portal dest = Portal.getByName(destName); + if (dest != null) + portal.open(true); + } + + // Open any always on gate pointing at this gate + for (String originName : allPortals) { + Portal origin = Portal.getByName(originName); + if (origin != null && origin.isAlwaysOn() && origin.getDestinationName().equalsIgnoreCase(portal.getName()) && origin.isVerified()) + origin.open(true); + } + + saveAllGates(); + + return portal; + } + + public static Portal getByName(String name) { + return lookupNames.get(name.toLowerCase()); + } + + public static Portal getByEntrance(Location location) { + return getByEntrance(new Blox(location).getBlock()); + } + + public static Portal getByEntrance(Block block) { + return lookupEntrances.get(block); + } + + public static Portal getByBlock(Block block) { + return lookupBlocks.get(block); + } + + public static void saveAllGates() { + String loc = Stargate.getSaveLocation(); + + try { + BufferedWriter bw = new BufferedWriter(new FileWriter(loc, false)); + + for (String name : allPortals) { + Portal portal = Portal.getByName(name); + 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()); + + 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 loadAllGates(World world) { + String location = Stargate.getSaveLocation(); + + lookupBlocks.clear(); + lookupNames.clear(); + lookupEntrances.clear(); + allPortals.clear(); + + if (new File(location).exists()) { + int l = 0; + try { + Scanner scanner = new Scanner(new File(location)); + while (scanner.hasNextLine()) { + l++; + String line = scanner.nextLine().trim(); + if (line.startsWith("#") || line.isEmpty()) { + continue; + } + String[] split = line.split(":"); + if (split.length < 8) { + 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); + 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]); + + String fixed = (split.length > 8) ? split[8] : ""; + String network = (split.length > 9) ? split[9] : 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; + + if (fixed.length() > 0) { + network = ""; + } + + Portal portal = new Portal(topLeft, modX, modZ, rotX, sign, button, fixed, name, false, network, gate, owner, hidden, alwaysOn); + portal.close(true); + // Verify portal integrity/register portal + if (!portal.isVerified() || !portal.checkIntegrity()) { + portal.close(true); + portal.unregister(); + Stargate.log.info("Destroying stargate at " + portal.toString()); + } else { + portal.drawSign(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 (String srcName : allPortals) { + Portal portal = Portal.getByName(srcName); + if (portal == null) continue; + if (!portal.isAlwaysOn()) continue; + if (!portal.isVerified()) continue; + + Portal dest = portal.getDestination(); + if (dest != null) { + portal.open(true); + OpenCount++; + } + } + Stargate.log.info("[Stargate] Loaded " + allPortals.size() + " stargates with " + OpenCount + " set as always-on"); + } catch (Exception e) { + Stargate.log.log(Level.SEVERE, "Exception while reading stargates from " + location + ": " + l); + e.printStackTrace(); + } + } + } + + public static void closeAllGates() { + Stargate.log.info("Closing all stargates."); + for (String name : allPortals) { + Portal p = Portal.getByName(name); + p.close(true); + } + } + + public static String filterName(String input) { + return input.replaceAll("[\\|:#]", "").trim(); + } + + public static Portal getNextOpen() { + for (String name : allPortals) { + Portal tmp = getByName(name); + if (tmp.pastGrace()) { + return tmp; + } + } + return null; + } +} diff --git a/src/com/bukkit/TheDgtl/Stargate/RelativeBlockVector.java b/src/com/bukkit/TheDgtl/Stargate/RelativeBlockVector.java new file mode 100644 index 0000000..0212837 --- /dev/null +++ b/src/com/bukkit/TheDgtl/Stargate/RelativeBlockVector.java @@ -0,0 +1,30 @@ +package com.bukkit.TheDgtl.Stargate; + +/** + * RelativeBlockVector.java - Plug-in for hey0's minecraft mod. + * @author Shaun (sturmeh) + * @author Dinnerbone + */ +public class RelativeBlockVector { + private int right = 0; + private int depth = 0; + private int distance = 0; + + public RelativeBlockVector(int right, int depth, int distance) { + this.right = right; + this.depth = depth; + this.distance = distance; + } + + public int getRight() { + return right; + } + + public int getDepth() { + return depth; + } + + public int getDistance() { + return distance; + } +} diff --git a/src/com/bukkit/TheDgtl/Stargate/SignPost.java b/src/com/bukkit/TheDgtl/Stargate/SignPost.java new file mode 100644 index 0000000..3003794 --- /dev/null +++ b/src/com/bukkit/TheDgtl/Stargate/SignPost.java @@ -0,0 +1,116 @@ +package com.bukkit.TheDgtl.Stargate; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.block.Sign; + +public class SignPost { + private Block parent; + private Sign sign; + private Block block; + private World world; + + public SignPost(World world, Sign sign) { + this.world = world; + this.sign = sign; + block = world.getBlockAt(sign.getX(), sign.getY(), sign.getZ()); + } + + public SignPost(Blox block) { + this.block = block.getBlock(); + this.world = block.getWorld(); + this.sign = (Sign)block.getBlock().getState(); + } + + public Block getParent() { + if (parent == null) findParent(); + return parent; + } + + public Block getBlock() { + return block; + } + + public String getText(int index) { + if (sign == null) findSign(); + if (sign == null) return ""; + return sign.getLine(index); + } + + public void setText(int index, String value) { + if (sign == null) findSign(); + if (sign == null) return; + sign.setLine(index, value); + } + + public String getIdText() { + if (sign == null) findSign(); + if (sign == null) return ""; + StringBuilder result = new StringBuilder(); + + result.append(getText(0)); + result.append("\n"); + result.append(getText(1)); + result.append("\n"); + result.append(getText(2)); + result.append("\n"); + result.append(getText(3)); + + return result.toString().toLowerCase(); + } + + public void update() { + if (sign == null) findSign(); + if (sign == null) return; + sign.update(); + } + + private void findParent() { + int offsetX = 0; + int offsetY = 0; + int offsetZ = 0; + + if (block.getType() == Material.WALL_SIGN) { + if (block.getData() == 0x2) { + offsetZ = 1; + } else if (block.getData() == 0x3) { + offsetZ = -1; + } else if (block.getData() == 0x4) { + offsetX = 1; + } else if (block.getData() == 0x5) { + offsetX = -1; + } + } else if (block.getType() == Material.SIGN_POST) { + offsetY = -1; + } + if (sign == null) { + Stargate.log.info("Sign is null"); + return; + } + if (world == null) { + Stargate.log.info("World is null"); + } + parent = world.getBlockAt(sign.getX() + offsetX, sign.getY() + offsetY, sign.getZ() + offsetZ); + } + + private void findSign() { + try { + sign = (Sign)this.world.getBlockAt(block.getX(), block.getY(), block.getZ()).getState(); + } finally { + + } + } + + public static SignPost getFromBlock(Block block) { + BlockState state = block.getState(); + if (!(state instanceof Sign)) return null; + return new SignPost(block.getWorld(), (Sign)state); + } + + public static SignPost getFromLocation(Location location) { + return getFromBlock(location.getWorld().getBlockAt((int)location.getX(), (int)location.getY(), (int)location.getZ())); + } +} \ No newline at end of file diff --git a/src/com/bukkit/TheDgtl/Stargate/Stargate.java b/src/com/bukkit/TheDgtl/Stargate/Stargate.java new file mode 100644 index 0000000..d593b26 --- /dev/null +++ b/src/com/bukkit/TheDgtl/Stargate/Stargate.java @@ -0,0 +1,358 @@ +package com.bukkit.TheDgtl.Stargate; + +import java.io.File; +import java.util.concurrent.SynchronousQueue; +import java.util.logging.Logger; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.Server; +import org.bukkit.block.Block; +import org.bukkit.block.BlockDamageLevel; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.Event.Priority; +import org.bukkit.event.block.BlockDamageEvent; +import org.bukkit.event.block.BlockFromToEvent; +import org.bukkit.event.block.BlockListener; +import org.bukkit.event.block.BlockPhysicsEvent; +import org.bukkit.event.block.BlockRightClickEvent; +import org.bukkit.event.player.PlayerListener; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginDescriptionFile; +import org.bukkit.plugin.PluginLoader; +import org.bukkit.plugin.PluginManager; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.util.config.Configuration; + +// Permissions +import com.nijikokun.bukkit.Permissions.Permissions; +import com.nijiko.permissions.PermissionHandler; + +/** + * Stargate.java - Plug-in for hey0's minecraft mod. + * @author Shaun (sturmeh) + * @author Dinnerbone + */ +public class Stargate extends JavaPlugin implements Runnable { + // Permissions + public static PermissionHandler Permissions = null; + + private final bListener blockListener = new bListener(); + private final pListener playerListener = new pListener(); + //private final vListener vehicleListener = new vListener(); + public static Logger log; + private Configuration config; + private static String gateSaveLocation = "stargates/locations.dat"; + private static String teleportMessage = "You feel weightless as the portal carries you to new land..."; + private static String registerMessage = "You feel a slight tremble in the ground around the portal..."; + private static String destroyzMessage = "You feel a great shift in energy, as it leaves the portal..."; + private static String noownersMessage = "You feel a great power, yet feel a lack of belonging here..."; + private static String unselectMessage = "You seem to want to go somewhere, but it's still a secret..."; + private static String collisionMessage = "You anticipate a great surge, but it appears it's blocked..."; + private static String defaultNetwork = "central"; + private static SynchronousQueue slip = new SynchronousQueue(); + //private HashMap vehicles = new HashMap(); + + // Threading stuff + private Thread clock; + private long interval = 0; + + public Stargate(PluginLoader pluginLoader, Server instance, PluginDescriptionFile desc, File folder, File plugin, ClassLoader cLoader) { + super(pluginLoader, instance, desc, folder, plugin, cLoader); + log = Logger.getLogger("Minecraft"); + + // Migrate old settings if applicable. + File oldFile = new File("stargates.txt"); + if (oldFile.exists()) + oldFile.renameTo(new File(gateSaveLocation)); + } + + public void onDisable() { + Portal.closeAllGates(); + } + + public void onEnable() { + PluginDescriptionFile pdfFile = this.getDescription(); + log.info(pdfFile.getName() + " v." + pdfFile.getVersion() + " is enabled."); + + PluginManager pm = getServer().getPluginManager(); + config = this.getConfiguration(); + if (clock == null) + clock = new Thread(this); + this.reloadConfig(); + this.setupPermissions(); + + 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_DAMAGED, blockListener, Priority.Normal, this); + pm.registerEvent(Event.Type.BLOCK_FLOW, blockListener, Priority.Normal, this); + pm.registerEvent(Event.Type.BLOCK_PHYSICS, blockListener, Priority.Normal, this); + + //pm.registerEvent(Event.Type.VEHICLE_MOVE, vehicleListener, Priority.Normal, this); + + setInterval(160); // 8 seconds. + + clock.start(); + } + + public void reloadConfig() { + config.load(); + gateSaveLocation = config.getString("portal-save-location", gateSaveLocation); + teleportMessage = config.getString("teleport-message", teleportMessage); + registerMessage = config.getString("portal-create-message", registerMessage); + destroyzMessage = config.getString("portal-destroy-message", destroyzMessage); + noownersMessage = config.getString("not-owner-message", noownersMessage); + unselectMessage = config.getString("not-selected-message", unselectMessage); + collisionMessage = config.getString("other-side-blocked-message", collisionMessage); + + defaultNetwork = config.getString("default-gate-network", defaultNetwork).trim(); + + Gate.loadGates(); + Portal.loadAllGates(this.getServer().getWorlds()[0]); + } + + public synchronized void doWork() { + Portal open = Portal.getNextOpen(); + + if (open != null) { + try { + slip.put(open); + } catch (InterruptedException e) { + } + } + } + + public void threadSafeOperation() { + Portal open = slip.poll(); + if (open != null) { + if (open.isOpen()) { + open.close(false); + } else if (open.isActive()) { + open.deactivate(); + } + } + } + + public static String getSaveLocation() { + return gateSaveLocation; + } + + public static String getDefaultNetwork() { + return defaultNetwork; + } + + private void onButtonPressed(Player player, Portal gate) { + Portal destination = gate.getDestination(); + + if (!gate.isOpen()) { + if ((!gate.isFixed()) && (gate.getActivePlayer() != player)) { + gate.deactivate(); + if (!noownersMessage.isEmpty()) { + player.sendMessage(ChatColor.RED + noownersMessage); + } + } else if ((destination == null) || (destination == gate)) { + if (!unselectMessage.isEmpty()) { + player.sendMessage(ChatColor.RED + unselectMessage); + } + } else if ((destination.isOpen()) && (!destination.isFixed())) { + if (!collisionMessage.isEmpty()) { + player.sendMessage(ChatColor.RED + collisionMessage); + } + } else { + gate.open(player, false); + } + } else { + gate.close(false); + } + } + + public void setupPermissions() { + Plugin perm = this.getServer().getPluginManager().getPlugin("Permissions"); + + if(Stargate.Permissions == null) { + if(perm != null) { + Stargate.Permissions = ((Permissions)perm).getHandler(); + } else { + log.info("[" + this.getDescription().getName() + "] Permission system not enabled. Disabling plugin."); + this.getServer().getPluginManager().disablePlugin(this); + } + } + } + +/* private class vListener extends VehicleListener { + @Override + public void onVehicleMove(VehicleMoveEvent event) { + Player player = (Player)event.getVehicle().getPassenger(); + + Location lookup = vehicles.get(vehicle.getId()); + + if (lookup != null) { + vehicle.setMotion(lookup.x, lookup.y, lookup.z); + vehicles.remove(vehicle.getId()); + } + + if (player != null) { + Portal portal = Portal.getByEntrance(etc.getServer().getBlockAt(x, y, z)); + + if ((portal != null) && (portal.isOpen())) { + if (portal.isOpenFor(player)) { + Portal destination = portal.getDestination(); + + if (destination != null) { + if (!teleportMessage.isEmpty()) { + player.sendMessage(Colors.Blue + teleportMessage); + } + + vehicles.put(vehicle.getId(), destination.teleport(vehicle, portal)); + + portal.close(false); + } + } else { + if (!noownersMessage.isEmpty()) { + player.sendMessage(Colors.Red + noownersMessage); + } + } + } + } + } + }*/ + + private class pListener extends PlayerListener { + @Override + public void onPlayerMove(PlayerMoveEvent event) { + threadSafeOperation(); + 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 (!teleportMessage.isEmpty()) { + player.sendMessage(ChatColor.BLUE + teleportMessage); + } + + destination.teleport(player, portal, event); + portal.close(false); + } + } else { + if (!noownersMessage.isEmpty()) { + player.sendMessage(ChatColor.RED + noownersMessage); + } + } + } + } + } + + private class bListener extends BlockListener { + + @Override + public void onBlockRightClick(BlockRightClickEvent event) { + Player player = event.getPlayer(); + Block block = event.getBlock(); + + if ((block.getType() == Material.SIGN_POST) || (block.getType() == Material.WALL_SIGN)) { + Portal portal = Portal.getByBlock(block); + + // Cycle through a stargates locations + if (portal != null) { + if (Stargate.Permissions.has(player, "stargate.use")) { + if ((!portal.isOpen()) && (!portal.isFixed())) { + portal.cycleDestination(player); + } + } + } + + // Check if the player is initializing a stargate + if (portal == null && Stargate.Permissions.has(player, "stargate.create")) { + SignPost sign = new SignPost(new Blox(block)); + portal = Portal.getByBlock(sign.getParent()); + if (portal == null) { + log.info("Initializing stargate"); + portal = Portal.createPortal(sign, player); + + if (portal != null && !registerMessage.isEmpty()) { + player.sendMessage(ChatColor.GREEN + registerMessage); + } + + if (portal == null) return; + log.info("Initialized stargate: " + portal.getName()); + portal.drawSign(true); + } + } + } + + // Implement right-click to toggle a stargate, gets around spawn protection problem. + if ((block.getType() == Material.STONE_BUTTON)) { + if (Stargate.Permissions.has(player, "stargate.use")) { + Portal portal = Portal.getByBlock(block); + if (portal != null) { + onButtonPressed(player, portal); + } + } + } + } + + @Override + public void onBlockDamage(BlockDamageEvent event) { + Player player = event.getPlayer(); + Block block = event.getBlock(); + if (block.getType() != Material.WALL_SIGN && block.getType() != Material.OBSIDIAN && block.getType() != Material.STONE_BUTTON) { + return; + } + + Portal portal = Portal.getByBlock(block); + if (portal == null) portal = Portal.getByEntrance(block); + if (portal == null) return; + if (!Stargate.Permissions.has(player, "stargate.destroy")) { + event.setCancelled(true); + return; + } + + if (event.getDamageLevel() == BlockDamageLevel.BROKEN) { + portal.unregister(); + if (!destroyzMessage.isEmpty()) { + player.sendMessage(ChatColor.RED + destroyzMessage); + } + } + } + + @Override + public void onBlockPhysics(BlockPhysicsEvent event) { + Block block = event.getBlock(); + + if (block.getType() == Material.PORTAL) { + event.setCancelled((Portal.getByEntrance(block) != null)); + } + } + + @Override + public void onBlockFlow(BlockFromToEvent event) { + Portal portal = Portal.getByEntrance(event.getBlock()); + + if (portal != null) { + event.setCancelled((event.getBlock().getY() == event.getToBlock().getY())); + } + } + } + + public void run() { + while (isEnabled()) { + try { + while (interval <= 0) + Thread.sleep(50); // Thread is dormant + for (long i = 0; i < interval && isEnabled(); i++) + Thread.sleep(50); // Sleep for an in-game second? + if (isEnabled()) doWork(); + } catch (InterruptedException e) {} + } + } + + public void setInterval(long interval) { + this.interval = interval; + } +} diff --git a/src/plugin.yml b/src/plugin.yml new file mode 100644 index 0000000..6761172 --- /dev/null +++ b/src/plugin.yml @@ -0,0 +1,6 @@ +name: Stargate +main: com.bukkit.TheDgtl.Stargate.Stargate +version: 0.01 +description: Stargate mod for Bukkit +author: Drakia +website: http://www.thedgtl.net \ No newline at end of file