Added 'B'ackwards option

Fixed opening of gates with a fixed destination
Added block metadata support
This commit is contained in:
Drakia 2011-07-12 21:07:53 -07:00
parent 4968927528
commit e1e3cd5e39
4 changed files with 98 additions and 85 deletions

15
README
View File

@ -30,6 +30,7 @@ Hmm.. None?
- stargate.option.alwayson - Allow this user/group to create always-on gates.
- stargate.option.private - Allow this user/group to create private gates.
- stargate.option.free - Allow this user/group to create free gates.
- stargate.option.backwards - Allow this user/group to create backwards gates.
=============
Instructions
@ -45,7 +46,12 @@ Sign Layout:
- Line 1: Gate Name (Max 12 characters)
- Line 2: Destination Name [Optional] (Max 12 characters, used for fixed-gates only)
- Line 3: Network name [Optional] (Max 12 characters)
- Line 4: Options [Optional] ('A' for always-on fixed gate, 'H' for hidden networked gate, 'P' for a private gate, 'F' for a free gate)
- Line 4: Options [Optional] :
'A' for always-on fixed gate
'H' for hidden networked gate
'P' for a private gate
'F' for a free gate
'B' is for a backwards facing gate (You will exit the back)
Options:
The options are the single letter, not the word. So to make a private hidden gate, your 4th line would be 'PH'.
@ -100,6 +106,9 @@ portal-open/closed are used to define the material in the gate when it is open o
"X" and "-" are used to define block "types" for the layout (Any single-character can be used, such as "#").
In the gate format, you can see we use "X" to show where obsidian must be, "-" where the controls (Button/sign) are.
You will also notice a "*" in the gate layout, this is the "exit point" of the gate, the block at which the player will teleport in front of.
As of version 0.5.5 you can supply block data in the format
X=35:15
Which would only allow black wool. If no data is supplied any version of a block will work (Any color of wool for example)
==============
Configuration
@ -130,6 +139,10 @@ maxgates - If non-zero, will define the maximum amount of gates allowed on a net
=============
Changes
=============
[Version 0.5.5]
- Added 'B'ackwards option
- Fixed opening of gates with a fixed gate as a destination
- Added block metadata support to gates
[Version 0.5.1]
- Take into account world/network restrictions for Vehicles
- Properly teleport empty vehicles between worlds

View File

@ -31,8 +31,9 @@ public class Gate {
private static HashSet<Integer> frameBlocks = new HashSet<Integer>();
private String filename;
private Integer[][] layout;
private Character[][] layout;
private HashMap<Character, Integer> types;
private HashMap<Character, Integer> metadata;
private RelativeBlockVector[] entrances = new RelativeBlockVector[0];
private RelativeBlockVector[] border = new RelativeBlockVector[0];
private RelativeBlockVector[] controls = new RelativeBlockVector[0];
@ -47,9 +48,10 @@ public class Gate {
private int destroyCost = 0;
private boolean toOwner = false;
private Gate(String filename, Integer[][] layout, HashMap<Character, Integer> types) {
private Gate(String filename, Character[][] layout, HashMap<Character, Integer> types, HashMap<Character, Integer> metadata) {
this.filename = filename;
this.layout = layout;
this.metadata = metadata;
this.types = types;
populateCoordinates();
@ -61,21 +63,20 @@ public class Gate {
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];
Integer id = types.get(layout[y][x]);
if (layout[y][x] == '-') {
controlList.add(new RelativeBlockVector(x, y, 0));
}
if (id == ENTRANCE || id == EXIT) {
entranceList.add(new RelativeBlockVector(x, y, 0));
exitDepths[x] = y;
if (id == EXIT)
this.exitBlock = new RelativeBlockVector(x, y, 0);
//bottom = y;
} else if (id == CONTROL) {
controlList.add(new RelativeBlockVector(x, y, 0));
} else if (id != ANYTHING) {
borderList.add(new RelativeBlockVector(x, y, 0));
}
@ -102,8 +103,6 @@ public class Gate {
}
public void save(String gateFolder) {
HashMap<Integer, Character> reverse = new HashMap<Integer, Character>();
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(gateFolder + filename));
@ -119,14 +118,18 @@ public class Gate {
for (Character type : types.keySet()) {
Integer value = types.get(type);
if (!type.equals('-')) {
reverse.put(value, type);
}
// Skip control values
if (value < 0) continue;
bw.append(type);
bw.append('=');
bw.append(value.toString());
Integer mData = metadata.get(type);
// Append metadata
if (mData != null) {
bw.append(':');
bw.append(mData.toString());
}
bw.newLine();
}
@ -134,23 +137,7 @@ public class Gate {
for (int y = 0; y < layout.length; y++) {
for (int x = 0; x < layout[y].length; x++) {
Integer id = layout[y][x];
Character symbol;
if (id == ENTRANCE) {
symbol = '.';
} else if (id == ANYTHING) {
symbol = ' ';
} else if (id == CONTROL) {
symbol = '-';
} else if (id == EXIT) {
symbol = '*';
} else if (reverse.containsKey(id)) {
symbol = reverse.get(id);
} else {
symbol = '?';
}
Character symbol = layout[y][x];
bw.append(symbol);
}
bw.newLine();
@ -158,7 +145,7 @@ public class Gate {
bw.close();
} catch (IOException ex) {
Stargate.log.log(Level.SEVERE, "Could not load Gate " + filename + " - " + ex.getMessage());
Stargate.log.log(Level.SEVERE, "Could not save Gate " + filename + " - " + ex.getMessage());
}
}
@ -172,7 +159,7 @@ public class Gate {
bw.newLine();
}
public Integer[][] getLayout() {
public Character[][] getLayout() {
return layout;
}
@ -234,20 +221,20 @@ public class Gate {
public boolean matches(Blox topleft, int modX, int modZ) {
for (int y = 0; y < layout.length; y++) {
for (int x = 0; x < layout[y].length; x++) {
int id = layout[y][x];
int id = types.get(layout[y][x]);
if (id == ENTRANCE || id == EXIT) {
if (topleft.modRelative(x, y, 0, modX, 1, modZ).getType() != portalBlockClosed) {
return false;
}
} else if (id == CONTROL) {
if (topleft.modRelative(x, y, 0, modX, 1, modZ).getType() != getControlBlock()) {
return false;
}
} else if (id != ANYTHING) {
if (topleft.modRelative(x, y, 0, modX, 1, modZ).getType() != id) {
return false;
}
Integer mData = metadata.get(layout[y][x]);
if (mData != null && topleft.modRelative(x, y, 0, modX, 1, modZ).getData() != mData) {
return false;
}
}
}
}
@ -270,10 +257,16 @@ public class Gate {
private static Gate loadGate(File file) {
Scanner scanner = null;
boolean designing = false;
ArrayList<ArrayList<Integer>> design = new ArrayList<ArrayList<Integer>>();
ArrayList<ArrayList<Character>> design = new ArrayList<ArrayList<Character>>();
HashMap<Character, Integer> types = new HashMap<Character, Integer>();
HashMap<Character, Integer> metadata = new HashMap<Character, Integer>();
HashMap<String, String> config = new HashMap<String, String>();
int cols = 0;
// Init types map
types.put('.', ENTRANCE);
types.put('*', EXIT);
types.put(' ', ANYTHING);
try {
scanner = new Scanner(file);
@ -282,31 +275,18 @@ public class Gate {
String line = scanner.nextLine();
if (designing) {
ArrayList<Integer> row = new ArrayList<Integer>();
ArrayList<Character> row = new ArrayList<Character>();
if (line.length() > cols) {
cols = line.length();
}
for (Character symbol : line.toCharArray()) {
Integer id = ANYTHING;
if (symbol.equals('.')) {
id = ENTRANCE;
} else if (symbol.equals('*')) {
id = EXIT;
} else if (symbol.equals(' ')) {
id = ANYTHING;
} else if (symbol.equals('-')) {
id = CONTROL;
} else if ((symbol.equals('?')) || (!types.containsKey(symbol))) {
if ((symbol.equals('?')) || (!types.containsKey(symbol))) {
Stargate.log.log(Level.SEVERE, "Could not load Gate " + file.getName() + " - Unknown symbol '" + symbol + "' in diagram");
return null;
} else {
id = types.get(symbol);
}
row.add(id);
row.add(symbol);
}
design.add(row);
@ -320,6 +300,13 @@ public class Gate {
if (key.length() == 1) {
Character symbol = key.charAt(0);
// Check for metadata
if (value.contains(":")) {
split = value.split(":");
value = split[0].trim();
String mData = split[1].trim();
metadata.put(symbol, Integer.parseInt(mData));
}
Integer id = Integer.parseInt(value);
types.put(symbol, id);
@ -337,24 +324,24 @@ public class Gate {
if (scanner != null) scanner.close();
}
Integer[][] layout = new Integer[design.size()][cols];
Character[][] layout = new Character[design.size()][cols];
for (int y = 0; y < design.size(); y++) {
ArrayList<Integer> row = design.get(y);
Integer[] result = new Integer[cols];
ArrayList<Character> row = design.get(y);
Character[] result = new Character[cols];
for (int x = 0; x < cols; x++) {
if (x < row.size()) {
result[x] = row.get(x);
} else {
result[x] = ANYTHING;
result[x] = ' ';
}
}
layout[y] = result;
}
Gate gate = new Gate(file.getName(), layout, types);
Gate gate = new Gate(file.getName(), layout, types, metadata);
gate.portalBlockOpen = readConfig(config, gate, file, "portal-open", gate.portalBlockOpen);
gate.portalBlockClosed = readConfig(config, gate, file, "portal-closed", gate.portalBlockClosed);
@ -407,18 +394,22 @@ public class Gate {
public static void populateDefaults(String gateFolder) {
int Obsidian = Material.OBSIDIAN.getId();
Integer[][] layout = new Integer[][] {
{ANYTHING, Obsidian,Obsidian, ANYTHING},
{Obsidian, ENTRANCE, ENTRANCE, Obsidian},
{CONTROL, ENTRANCE, ENTRANCE, CONTROL},
{Obsidian, EXIT, ENTRANCE, Obsidian},
{ANYTHING, Obsidian, Obsidian, ANYTHING},
Character[][] layout = new Character[][] {
{' ', 'X','X', ' '},
{'X', '.', '.', 'X'},
{'-', '.', '.', '-'},
{'X', '*', '.', 'X'},
{' ', 'X', 'X', ' '},
};
HashMap<Character, Integer> types = new HashMap<Character, Integer>();
types.put('.', ENTRANCE);
types.put('*', EXIT);
types.put(' ', ANYTHING);
types.put('X', Obsidian);
types.put('-', Obsidian);
HashMap<Character, Integer> metadata = new HashMap<Character, Integer>();
Gate gate = new Gate("nethergate.gate", layout, types);
Gate gate = new Gate("nethergate.gate", layout, types, metadata);
gate.save(gateFolder);
registerGate(gate);
}

View File

@ -16,7 +16,6 @@ import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.Sign;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Minecart;
import org.bukkit.entity.Player;
import org.bukkit.entity.StorageMinecart;
import org.bukkit.entity.Vehicle;
@ -56,10 +55,13 @@ public class Portal {
private String network;
private Gate gate;
private String owner = "";
// Options
private boolean hidden = false;
private boolean alwaysOn = false;
private boolean priv = false;
private boolean free = false;
private boolean backwards = false;
private World world;
// Gate options
private boolean verified;
@ -74,8 +76,8 @@ public class Portal {
private Portal(Blox topLeft, int modX, int modZ,
float rotX, SignPost id, Blox button,
String dest, String name,
boolean verified, String network, Gate gate,
String owner, boolean hidden, boolean alwaysOn, boolean priv, boolean free) {
boolean verified, String network, Gate gate, String owner,
boolean hidden, boolean alwaysOn, boolean priv, boolean free, boolean backwards) {
this.topLeft = topLeft;
this.modX = modX;
this.modZ = modZ;
@ -93,6 +95,7 @@ public class Portal {
this.alwaysOn = alwaysOn;
this.priv = priv;
this.free = free;
this.backwards = backwards;
this.world = topLeft.getWorld();
if (this.alwaysOn && !this.fixed) {
@ -126,6 +129,10 @@ public class Portal {
return free;
}
public boolean isBackwards() {
return backwards;
}
public boolean isFree(Player player, Portal dest) {
// This gate is free, the player gets all gates free, or we don't charge for free dest and dest is free
boolean isFree = isFree() || Stargate.hasPerm(player, "stargate.free.use", player.isOp()) ||
@ -155,7 +162,7 @@ public class Portal {
player = openFor;
Portal end = getDestination();
if (end != null && !end.isFixed() && !end.isOpen()) {
if (end != null && !end.isAlwaysOn() && !end.isOpen()) {
end.open(openFor, false);
end.setDestination(this);
if (end.isVerified()) end.drawSign();
@ -218,7 +225,9 @@ public class Portal {
Location traveller = player.getLocation();
Location exit = getExit(traveller);
exit.setYaw(origin.getRotation() - traveller.getYaw() + this.getRotation() + 180);
// Handle backwards gates
int adjust = isBackwards() ? 0 :180;
exit.setYaw(origin.getRotation() - traveller.getYaw() + this.getRotation() + adjust);
// The new method to teleport in a move event is set the "to" field.
event.setTo(exit);
@ -278,14 +287,14 @@ public class Portal {
// Check if the gate has an exit block
if (gate.getExit() != null) {
Blox exit = getBlockAt(gate.getExit());
loc = exit.modRelativeLoc(0D, 0D, 1D, traveller.getYaw(), traveller.getPitch(), modX, 1, modZ);
int back = (isBackwards()) ? -1 : 1;
loc = exit.modRelativeLoc(0D, 0D, 1D, traveller.getYaw(), traveller.getPitch(), modX * back, 1, modZ * back);
} else {
Stargate.log.log(Level.WARNING, "[Stargate] Missing destination point in .gate file " + gate.getFilename());
}
if (loc != null) {
Block block = getWorld().getBlockAt(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
if (block.getType() == Material.STEP) {
if (getWorld().getBlockTypeIdAt(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()) == Material.STEP.getId()) {
loc.setY(loc.getY() + 0.5);
}
@ -517,17 +526,12 @@ public class Portal {
public Blox[] getFrame() {
if (frame == null) {
RelativeBlockVector[] border = gate.getBorder();
RelativeBlockVector[] controls = gate.getControls();
frame = new Blox[border.length + controls.length];
frame = new Blox[border.length];
int i = 0;
for (RelativeBlockVector vector : border) {
frame[i++] = getBlockAt(vector);
}
for (RelativeBlockVector vector : controls) {
frame[i++] = getBlockAt(vector);
}
}
return frame;
@ -631,12 +635,14 @@ public class Portal {
boolean alwaysOn = (options.indexOf('a') != -1 || options.indexOf('A') != -1);
boolean priv = (options.indexOf('p') != -1 || options.indexOf('P') != -1);
boolean free = (options.indexOf('f') != - 1|| options.indexOf('F') != -1);
boolean backwards = (options.indexOf('b') != -1 || options.indexOf('B') != -1);
// Check permissions for options.
if (!Stargate.hasPerm(player, "stargate.option.hidden", player.isOp())) hidden = false;
if (!Stargate.hasPerm(player, "stargate.option.alwayson", player.isOp())) alwaysOn = false;
if (!Stargate.hasPerm(player, "stargate.option.private", player.isOp())) priv = false;
if (!Stargate.hasPerm(player, "stargate.option.free", player.isOp())) free = false;
if (!Stargate.hasPerm(player, "stargate.option.backwards", player.isOp())) backwards = false;
// Can not create a non-fixed always-on gate.
if (alwaysOn && destName.length() == 0) {
@ -644,7 +650,7 @@ public class Portal {
}
// Debug
Stargate.debug("createPortal", "h = " + hidden + " a = " + alwaysOn + " p = " + priv + " f = " + free);
Stargate.debug("createPortal", "h = " + hidden + " a = " + alwaysOn + " p = " + priv + " f = " + free + " b = " + backwards);
if ((network.length() < 1) || (network.length() > 11)) {
network = Stargate.getDefaultNetwork();
@ -773,7 +779,7 @@ public class Portal {
button.setType(Material.STONE_BUTTON.getId());
button.setData(facing);
}
portal = new Portal(topleft, modX, modZ, rotX, id, button, destName, name, true, network, gate, player.getName(), hidden, alwaysOn, priv, free);
portal = new Portal(topleft, modX, modZ, rotX, id, button, destName, name, true, network, gate, player.getName(), hidden, alwaysOn, priv, free, backwards);
// Open always on gate
if (portal.isAlwaysOn()) {
@ -861,6 +867,8 @@ public class Portal {
builder.append(portal.world.getName());
builder.append(':');
builder.append(portal.isFree());
builder.append(':');
builder.append(portal.isBackwards());
bw.append(builder.toString());
bw.newLine();
@ -927,8 +935,9 @@ public class Portal {
boolean alwaysOn = (split.length > 12) ? split[12].equalsIgnoreCase("true") : false;
boolean priv = (split.length > 13) ? split[13].equalsIgnoreCase("true") : false;
boolean free = (split.length > 15) ? split[15].equalsIgnoreCase("true") : false;
boolean backwards = (split.length > 16) ? split[16].equalsIgnoreCase("true") : false;
Portal portal = new Portal(topLeft, modX, modZ, rotX, sign, button, dest, name, false, network, gate, owner, hidden, alwaysOn, priv, free);
Portal portal = new Portal(topLeft, modX, modZ, rotX, sign, button, dest, name, false, network, gate, owner, hidden, alwaysOn, priv, free, backwards);
portal.close(true);
}
scanner.close();

View File

@ -1,6 +1,6 @@
name: Stargate
main: net.TheDgtl.Stargate.Stargate
version: 0.5.1
version: 0.5.5
description: Stargate mod for Bukkit
author: Drakia
website: http://www.thedgtl.net