Initial commit

This commit is contained in:
Drakia 2011-02-06 03:36:48 -08:00
commit eb407537f2
7 changed files with 1870 additions and 0 deletions

View File

@ -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);
}
}

View File

@ -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<String, Gate> gates = new HashMap<String, Gate>();
private static HashMap<Integer, ArrayList<Gate>> controlBlocks = new HashMap<Integer, ArrayList<Gate>>();
private String filename;
private Integer[][] layout;
private HashMap<Character, Integer> types;
private RelativeBlockVector[] entrances = new RelativeBlockVector[0];
private RelativeBlockVector[] border = new RelativeBlockVector[0];
private RelativeBlockVector[] controls = new RelativeBlockVector[0];
private HashMap<RelativeBlockVector, Integer> exits = new HashMap<RelativeBlockVector, Integer>();
private int portalBlockOpen = Material.PORTAL.getId();
private int portalBlockClosed = Material.AIR.getId();
private Gate(String filename, Integer[][] layout, HashMap<Character, Integer> types) {
this.filename = filename;
this.layout = layout;
this.types = types;
populateCoordinates();
}
private void populateCoordinates() {
ArrayList<RelativeBlockVector> entranceList = new ArrayList<RelativeBlockVector>();
ArrayList<RelativeBlockVector> borderList = new ArrayList<RelativeBlockVector>();
ArrayList<RelativeBlockVector> controlList = new ArrayList<RelativeBlockVector>();
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<Integer, Character> reverse = new HashMap<Integer, Character>();
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<RelativeBlockVector, Integer> 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<Gate>());
}
controlBlocks.get(blockID).add(gate);
}
private static Gate loadGate(File file) {
Scanner scanner = null;
boolean designing = false;
ArrayList<ArrayList<Integer>> design = new ArrayList<ArrayList<Integer>>();
HashMap<Character, Integer> types = new HashMap<Character, Integer>();
HashMap<String, String> config = new HashMap<String, String>();
int cols = 0;
try {
scanner = new Scanner(file);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (designing) {
ArrayList<Integer> row = new ArrayList<Integer>();
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<Integer> 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<String, String> 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<Character, Integer> types = new HashMap<Character, Integer>();
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<Gate> 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
};
}

View File

@ -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<Block, Portal> lookupBlocks = new HashMap<Block, Portal>();
private static final HashMap<String, Portal> lookupNames = new HashMap<String, Portal>();
private static final HashMap<Block, Portal> lookupEntrances = new HashMap<Block, Portal>();
private static final ArrayList<String> allPortals = new ArrayList<String>();
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<String> destinations = new ArrayList<String>();
private String network;
private Gate gate;
private boolean isOpen = false;
private String owner = "";
private HashMap<Block, Integer> exits;
private HashMap<Integer, Block> 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<Block, Integer> originExits = origin.getExits();
HashMap<Block, Integer> 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<Block, Integer> getExits() {
if (exits == null) {
exits = new HashMap<Block, Integer>();
reverseExits = new HashMap<Integer, Block>();
HashMap<RelativeBlockVector, Integer> relativeExits = gate.getExits();
Set<RelativeBlockVector> 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<Integer, Block> 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;
}
}

View File

@ -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;
}
}

View File

@ -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()));
}
}

View File

@ -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<Portal> slip = new SynchronousQueue<Portal>();
//private HashMap<Integer, Location> vehicles = new HashMap<Integer, Location>();
// 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;
}
}

6
src/plugin.yml Normal file
View File

@ -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