[Version 0.7.9.0]

- Added BungeeCord multi-server support (Requires Stargate-Bungee for BungeeCord)
 - Updated Spanish language file
 - Added basic plugin metrics via http://mcstats.org/
This commit is contained in:
Steven Scott 2012-11-24 15:42:57 -08:00
parent fc73e1fbda
commit ac520665e6
8 changed files with 575 additions and 65 deletions

4
README
View File

@ -212,6 +212,10 @@ Client randomly crashes on teleport.
============= =============
Changes Changes
============= =============
[Version 0.7.9.0]
- Added BungeeCord multi-server support (Requires Stargate-Bungee for BungeeCord)
- Updated Spanish language file
- Added basic plugin metrics via http://mcstats.org/
[Version 0.7.8.1] [Version 0.7.8.1]
- Resolve issue of language file being overwritten as ANSI instead of UTF8 - Resolve issue of language file being overwritten as ANSI instead of UTF8
[Version 0.7.8.0] [Version 0.7.8.0]

View File

@ -0,0 +1,357 @@
/*
* Copyright 2011 Tyler Blair. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and contributors and should not be interpreted as representing official policies,
* either expressed or implied, of anybody else.
*/
package net.TheDgtl.Stargate;
import org.bukkit.Bukkit;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.Proxy;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.UUID;
import java.util.logging.Level;
public class MetricsLite {
/**
* The current revision number
*/
private final static int REVISION = 5;
/**
* The base url of the metrics domain
*/
private static final String BASE_URL = "http://mcstats.org";
/**
* The url used to report a server's status
*/
private static final String REPORT_URL = "/report/%s";
/**
* Interval of time to ping (in minutes)
*/
private final static int PING_INTERVAL = 10;
/**
* The plugin this metrics submits for
*/
private final Plugin plugin;
/**
* The plugin configuration file
*/
private final YamlConfiguration configuration;
/**
* The plugin configuration file
*/
private final File configurationFile;
/**
* Unique server id
*/
private final String guid;
/**
* Lock for synchronization
*/
private final Object optOutLock = new Object();
/**
* Id of the scheduled task
*/
private volatile int taskId = -1;
public MetricsLite(Plugin plugin) throws IOException {
if (plugin == null) {
throw new IllegalArgumentException("Plugin cannot be null");
}
this.plugin = plugin;
// load the config
configurationFile = getConfigFile();
configuration = YamlConfiguration.loadConfiguration(configurationFile);
// add some defaults
configuration.addDefault("opt-out", false);
configuration.addDefault("guid", UUID.randomUUID().toString());
// Do we need to create the file?
if (configuration.get("guid", null) == null) {
configuration.options().header("http://mcstats.org").copyDefaults(true);
configuration.save(configurationFile);
}
// Load the guid then
guid = configuration.getString("guid");
}
/**
* Start measuring statistics. This will immediately create an async repeating task as the plugin and send
* the initial data to the metrics backend, and then after that it will post in increments of
* PING_INTERVAL * 1200 ticks.
*
* @return True if statistics measuring is running, otherwise false.
*/
public boolean start() {
synchronized (optOutLock) {
// Did we opt out?
if (isOptOut()) {
return false;
}
// Is metrics already running?
if (taskId >= 0) {
return true;
}
// Begin hitting the server with glorious data
taskId = plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin, new Runnable() {
private boolean firstPost = true;
public void run() {
try {
// This has to be synchronized or it can collide with the disable method.
synchronized (optOutLock) {
// Disable Task, if it is running and the server owner decided to opt-out
if (isOptOut() && taskId > 0) {
plugin.getServer().getScheduler().cancelTask(taskId);
taskId = -1;
}
}
// We use the inverse of firstPost because if it is the first time we are posting,
// it is not a interval ping, so it evaluates to FALSE
// Each time thereafter it will evaluate to TRUE, i.e PING!
postPlugin(!firstPost);
// After the first post we set firstPost to false
// Each post thereafter will be a ping
firstPost = false;
} catch (IOException e) {
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage());
}
}
}, 0, PING_INTERVAL * 1200);
return true;
}
}
/**
* Has the server owner denied plugin metrics?
*
* @return true if metrics should be opted out of it
*/
public boolean isOptOut() {
synchronized(optOutLock) {
try {
// Reload the metrics file
configuration.load(getConfigFile());
} catch (IOException ex) {
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
return true;
} catch (InvalidConfigurationException ex) {
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
return true;
}
return configuration.getBoolean("opt-out", false);
}
}
/**
* Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task.
*
* @throws IOException
*/
public void enable() throws IOException {
// This has to be synchronized or it can collide with the check in the task.
synchronized (optOutLock) {
// Check if the server owner has already set opt-out, if not, set it.
if (isOptOut()) {
configuration.set("opt-out", false);
configuration.save(configurationFile);
}
// Enable Task, if it is not running
if (taskId < 0) {
start();
}
}
}
/**
* Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task.
*
* @throws IOException
*/
public void disable() throws IOException {
// This has to be synchronized or it can collide with the check in the task.
synchronized (optOutLock) {
// Check if the server owner has already set opt-out, if not, set it.
if (!isOptOut()) {
configuration.set("opt-out", true);
configuration.save(configurationFile);
}
// Disable Task, if it is running
if (taskId > 0) {
this.plugin.getServer().getScheduler().cancelTask(taskId);
taskId = -1;
}
}
}
/**
* Gets the File object of the config file that should be used to store data such as the GUID and opt-out status
*
* @return the File object for the config file
*/
public File getConfigFile() {
// I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use
// is to abuse the plugin object we already have
// plugin.getDataFolder() => base/plugins/PluginA/
// pluginsFolder => base/plugins/
// The base is not necessarily relative to the startup directory.
File pluginsFolder = plugin.getDataFolder().getParentFile();
// return => base/plugins/PluginMetrics/config.yml
return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml");
}
/**
* Generic method that posts a plugin to the metrics website
*/
private void postPlugin(boolean isPing) throws IOException {
// The plugin's description file containg all of the plugin data such as name, version, author, etc
final PluginDescriptionFile description = plugin.getDescription();
// Construct the post data
final StringBuilder data = new StringBuilder();
data.append(encode("guid")).append('=').append(encode(guid));
encodeDataPair(data, "version", description.getVersion());
encodeDataPair(data, "server", Bukkit.getVersion());
encodeDataPair(data, "players", Integer.toString(Bukkit.getServer().getOnlinePlayers().length));
encodeDataPair(data, "revision", String.valueOf(REVISION));
// If we're pinging, append it
if (isPing) {
encodeDataPair(data, "ping", "true");
}
// Create the url
URL url = new URL(BASE_URL + String.format(REPORT_URL, encode(plugin.getDescription().getName())));
// Connect to the website
URLConnection connection;
// Mineshafter creates a socks proxy, so we can safely bypass it
// It does not reroute POST requests so we need to go around it
if (isMineshafterPresent()) {
connection = url.openConnection(Proxy.NO_PROXY);
} else {
connection = url.openConnection();
}
connection.setDoOutput(true);
// Write the data
final OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
writer.write(data.toString());
writer.flush();
// Now read the response
final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
final String response = reader.readLine();
// close resources
writer.close();
reader.close();
if (response == null || response.startsWith("ERR")) {
throw new IOException(response); //Throw the exception
}
//if (response.startsWith("OK")) - We should get "OK" followed by an optional description if everything goes right
}
/**
* Check if mineshafter is present. If it is, we need to bypass it to send POST requests
*
* @return true if mineshafter is installed on the server
*/
private boolean isMineshafterPresent() {
try {
Class.forName("mineshafter.MineServer");
return true;
} catch (Exception e) {
return false;
}
}
/**
* <p>Encode a key/value data pair to be used in a HTTP post request. This INCLUDES a & so the first
* key/value pair MUST be included manually, e.g:</p>
* <code>
* StringBuffer data = new StringBuffer();
* data.append(encode("guid")).append('=').append(encode(guid));
* encodeDataPair(data, "version", description.getVersion());
* </code>
*
* @param buffer the stringbuilder to append the data pair onto
* @param key the key value
* @param value the value
*/
private static void encodeDataPair(final StringBuilder buffer, final String key, final String value) throws UnsupportedEncodingException {
buffer.append('&').append(encode(key)).append('=').append(encode(value));
}
/**
* Encode text as UTF-8
*
* @param text the text to encode
* @return the encoded text, as UTF-8
*/
private static String encode(final String text) throws UnsupportedEncodingException {
return URLEncoder.encode(text, "UTF-8");
}
}

View File

@ -63,6 +63,9 @@ public class Portal {
private static final HashMap<String, ArrayList<String>> allPortalsNet = new HashMap<String, ArrayList<String>>(); private static final HashMap<String, ArrayList<String>> allPortalsNet = new HashMap<String, ArrayList<String>>();
private static final HashMap<String, HashMap<String, Portal>> lookupNamesNet = new HashMap<String, HashMap<String, Portal>>(); private static final HashMap<String, HashMap<String, Portal>> lookupNamesNet = new HashMap<String, HashMap<String, Portal>>();
// A list of Bungee gates
private static final HashMap<String, Portal> bungeePortals = new HashMap<String, Portal>();
// Gate location block info // Gate location block info
private Blox topLeft; private Blox topLeft;
private int modX; private int modX;
@ -95,6 +98,7 @@ public class Portal {
private boolean show = false; private boolean show = false;
private boolean noNetwork = false; private boolean noNetwork = false;
private boolean random = false; private boolean random = false;
private boolean bungee = false;
// In-use information // In-use information
private Player player; private Player player;
@ -107,7 +111,7 @@ public class Portal {
float rotX, Blox id, Blox button, float rotX, Blox id, Blox button,
String dest, String name, String dest, String name,
boolean verified, String network, Gate gate, String owner, boolean verified, String network, Gate gate, String owner,
boolean hidden, boolean alwaysOn, boolean priv, boolean free, boolean backwards, boolean show, boolean noNetwork, boolean random) { boolean hidden, boolean alwaysOn, boolean priv, boolean free, boolean backwards, boolean show, boolean noNetwork, boolean random, boolean bungee) {
this.topLeft = topLeft; this.topLeft = topLeft;
this.modX = modX; this.modX = modX;
this.modZ = modZ; this.modZ = modZ;
@ -128,8 +132,9 @@ public class Portal {
this.show = show; this.show = show;
this.noNetwork = noNetwork; this.noNetwork = noNetwork;
this.random = random; this.random = random;
this.bungee = bungee;
this.world = topLeft.getWorld(); this.world = topLeft.getWorld();
this.fixed = dest.length() > 0 || this.random; this.fixed = dest.length() > 0 || this.random || this.bungee;
if (this.isAlwaysOn() && !this.isFixed()) { if (this.isAlwaysOn() && !this.isFixed()) {
this.alwaysOn = false; this.alwaysOn = false;
@ -185,6 +190,10 @@ public class Portal {
return random; return random;
} }
public boolean isBungee() {
return bungee;
}
public void setAlwaysOn(boolean alwaysOn) { public void setAlwaysOn(boolean alwaysOn) {
this.alwaysOn = alwaysOn; this.alwaysOn = alwaysOn;
} }
@ -466,8 +475,14 @@ public class Portal {
exit = pEvent.getExit(); exit = pEvent.getExit();
} }
// The new method to teleport in a move event is set the "to" field. // If no event is passed in, assume it's a teleport, and act as such
event.setTo(exit); if (event == null) {
exit.setYaw(this.getRotation());
player.teleport(exit);
} else {
// The new method to teleport in a move event is set the "to" field.
event.setTo(exit);
}
} }
public void teleport(final Vehicle vehicle) { public void teleport(final Vehicle vehicle) {
@ -530,8 +545,8 @@ public class Portal {
} else { } else {
Stargate.log.log(Level.WARNING, "[Stargate] Missing destination point in .gate file " + gate.getFilename()); Stargate.log.log(Level.WARNING, "[Stargate] Missing destination point in .gate file " + gate.getFilename());
} }
if (loc != null) { if (loc != null) {
if (getWorld().getBlockTypeIdAt(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()) == Material.STEP.getId()) { if (getWorld().getBlockTypeIdAt(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()) == Material.STEP.getId()) {
loc.setY(loc.getY() + 0.5); loc.setY(loc.getY() + 0.5);
} }
@ -691,7 +706,12 @@ public class Portal {
Stargate.setLine(sign, ++done, "(" + network + ")"); Stargate.setLine(sign, ++done, "(" + network + ")");
} }
} else { } else {
if (isFixed()) { // Awesome new logic for Bungee gates
if (isBungee()) {
Stargate.setLine(sign, ++done, Stargate.getString("bungeeSign"));
Stargate.setLine(sign, ++done, ">" + destination + "<");
Stargate.setLine(sign, ++done, "[" + network + "]");
} else if (isFixed()) {
if (isRandom()) { if (isRandom()) {
Stargate.setLine(sign, ++done, "> " + Stargate.getString("signRandom") + " <"); Stargate.setLine(sign, ++done, "> " + Stargate.getString("signRandom") + " <");
} else { } else {
@ -768,7 +788,6 @@ public class Portal {
public void unregister(boolean removeAll) { public void unregister(boolean removeAll) {
Stargate.debug("Unregister", "Unregistering gate " + getName()); Stargate.debug("Unregister", "Unregistering gate " + getName());
close(true); close(true);
lookupNamesNet.get(getNetwork().toLowerCase()).remove(getName().toLowerCase());
for (Blox block : getFrame()) { for (Blox block : getFrame()) {
lookupBlocks.remove(block); lookupBlocks.remove(block);
@ -790,7 +809,21 @@ public class Portal {
if (removeAll) if (removeAll)
allPortals.remove(this); allPortals.remove(this);
allPortalsNet.get(getNetwork().toLowerCase()).remove(getName().toLowerCase()); if (bungee) {
bungeePortals.remove(getName().toLowerCase());
} else {
lookupNamesNet.get(getNetwork().toLowerCase()).remove(getName().toLowerCase());
allPortalsNet.get(getNetwork().toLowerCase()).remove(getName().toLowerCase());
for (String originName : allPortalsNet.get(getNetwork().toLowerCase())) {
Portal origin = Portal.getByName(originName, getNetwork());
if (origin == null) continue;
if (!origin.getDestinationName().equalsIgnoreCase(getName())) continue;
if (!origin.isVerified()) continue;
if (origin.isFixed()) origin.drawSign();
if (origin.isAlwaysOn()) origin.close(true);
}
}
if (id.getBlock().getType() == Material.WALL_SIGN && id.getBlock().getState() instanceof Sign) { if (id.getBlock().getType() == Material.WALL_SIGN && id.getBlock().getState() instanceof Sign) {
Sign sign = (Sign)id.getBlock().getState(); Sign sign = (Sign)id.getBlock().getState();
@ -801,15 +834,6 @@ public class Portal {
sign.update(); sign.update();
} }
for (String originName : allPortalsNet.get(getNetwork().toLowerCase())) {
Portal origin = Portal.getByName(originName, getNetwork());
if (origin == null) continue;
if (!origin.getDestinationName().equalsIgnoreCase(getName())) continue;
if (!origin.isVerified()) continue;
if (origin.isFixed()) origin.drawSign();
if (origin.isAlwaysOn()) origin.close(true);
}
saveAllGates(getWorld()); saveAllGates(getWorld());
} }
@ -818,12 +842,26 @@ public class Portal {
} }
private void register() { private void register() {
fixed = destination.length() > 0 || random; fixed = destination.length() > 0 || random || bungee;
if (!lookupNamesNet.containsKey(getNetwork().toLowerCase())) {
Stargate.debug("register", "Network not in lookupNamesNet, adding"); // Bungee gates are stored in their own list
lookupNamesNet.put(getNetwork().toLowerCase(), new HashMap<String, Portal>()); if (isBungee()) {
bungeePortals.put(getName().toLowerCase(), this);
} else {
// Check if network exists in our network list
if (!lookupNamesNet.containsKey(getNetwork().toLowerCase())) {
Stargate.debug("register", "Network not in lookupNamesNet, adding");
lookupNamesNet.put(getNetwork().toLowerCase(), new HashMap<String, Portal>());
}
lookupNamesNet.get(getNetwork().toLowerCase()).put(getName().toLowerCase(), this);
// Check if this network exists
if (!allPortalsNet.containsKey(getNetwork().toLowerCase())) {
Stargate.debug("register", "Network not in allPortalsNet, adding");
allPortalsNet.put(getNetwork().toLowerCase(), new ArrayList<String>());
}
allPortalsNet.get(getNetwork().toLowerCase()).add(getName().toLowerCase());
} }
lookupNamesNet.get(getNetwork().toLowerCase()).put(getName().toLowerCase(), this);
for (Blox block : getFrame()) { for (Blox block : getFrame()) {
lookupBlocks.put(block, this); lookupBlocks.put(block, this);
@ -843,12 +881,6 @@ public class Portal {
} }
allPortals.add(this); allPortals.add(this);
// Check if this network exists
if (!allPortalsNet.containsKey(getNetwork().toLowerCase())) {
Stargate.debug("register", "Network not in allPortalsNet, adding");
allPortalsNet.put(getNetwork().toLowerCase(), new ArrayList<String>());
}
allPortalsNet.get(getNetwork().toLowerCase()).add(getName().toLowerCase());
} }
public static Portal createPortal(SignChangeEvent event, Player player) { public static Portal createPortal(SignChangeEvent event, Player player) {
@ -879,6 +911,7 @@ public class Portal {
boolean show = (options.indexOf('s') != -1); boolean show = (options.indexOf('s') != -1);
boolean noNetwork = (options.indexOf('n') != -1); boolean noNetwork = (options.indexOf('n') != -1);
boolean random = (options.indexOf('r') != -1); boolean random = (options.indexOf('r') != -1);
boolean bungee = (options.indexOf('u') != -1);
// Check permissions for options. // Check permissions for options.
if (hidden && !Stargate.canOption(player, "hidden")) hidden = false; if (hidden && !Stargate.canOption(player, "hidden")) hidden = false;
@ -890,6 +923,20 @@ public class Portal {
if (noNetwork && !Stargate.canOption(player, "nonetwork")) noNetwork = false; if (noNetwork && !Stargate.canOption(player, "nonetwork")) noNetwork = false;
if (random && !Stargate.canOption(player, "random")) random = false; if (random && !Stargate.canOption(player, "random")) random = false;
// If the player is trying to create a Bungee gate without permissions, drop out here
if (bungee) {
if (!Stargate.enableBungee) {
Stargate.sendMessage(player, Stargate.getString("bungeeDisabled"));
return null;
} else if (!Stargate.hasPerm(player, "stargate.admin.bungee")) {
Stargate.sendMessage(player, Stargate.getString("bungeeDeny"));
return null;
} else if (destName.isEmpty() || network.isEmpty()) {
Stargate.sendMessage(player, Stargate.getString("bungeeEmpty"));
return null;
}
}
// Can not create a non-fixed always-on gate. // Can not create a non-fixed always-on gate.
if (alwaysOn && destName.length() == 0) { if (alwaysOn && destName.length() == 0) {
alwaysOn = false; alwaysOn = false;
@ -906,6 +953,12 @@ public class Portal {
show = false; show = false;
} }
// Bungee gates are always on and don't support Random
if (bungee) {
alwaysOn = true;
random = false;
}
// Moved the layout check so as to avoid invalid messages when not making a gate // Moved the layout check so as to avoid invalid messages when not making a gate
int modX = 0; int modX = 0;
int modZ = 0; int modZ = 0;
@ -966,9 +1019,9 @@ public class Portal {
} }
// Debug // Debug
Stargate.debug("createPortal", "h = " + hidden + " a = " + alwaysOn + " p = " + priv + " f = " + free + " b = " + backwards + " s = " + show + " n = " + noNetwork + " r = " + random); Stargate.debug("createPortal", "h = " + hidden + " a = " + alwaysOn + " p = " + priv + " f = " + free + " b = " + backwards + " s = " + show + " n = " + noNetwork + " r = " + random + " u = " + bungee);
if ((network.length() < 1) || (network.length() > 11)) { if (!bungee && (network.length() < 1 || network.length() > 11)) {
network = Stargate.getDefaultNetwork(); network = Stargate.getDefaultNetwork();
} }
@ -976,7 +1029,7 @@ public class Portal {
String denyMsg = ""; String denyMsg = "";
// Check if the player can create gates on this network // Check if the player can create gates on this network
if (!Stargate.canCreate(player, network)) { if (!bungee && !Stargate.canCreate(player, network)) {
Stargate.debug("createPortal", "Player doesn't have create permissions on network. Trying personal"); Stargate.debug("createPortal", "Player doesn't have create permissions on network. Trying personal");
if (Stargate.canCreatePersonal(player)) { if (Stargate.canCreatePersonal(player)) {
network = player.getName(); network = player.getName();
@ -1001,7 +1054,7 @@ public class Portal {
} }
// Check if the user can create gates to this world. // Check if the user can create gates to this world.
if (!deny && destName.length() > 0) { if (!bungee && !deny && destName.length() > 0) {
Portal p = Portal.getByName(destName, network); Portal p = Portal.getByName(destName, network);
if (p != null) { if (p != null) {
String world = p.getWorld().getName(); String world = p.getWorld().getName();
@ -1025,7 +1078,7 @@ public class Portal {
Blox button = null; Blox button = null;
Portal portal = null; Portal portal = null;
portal = new Portal(topleft, modX, modZ, rotX, id, button, destName, name, false, network, gate, player.getName(), hidden, alwaysOn, priv, free, backwards, show, noNetwork, random); portal = new Portal(topleft, modX, modZ, rotX, id, button, destName, name, false, network, gate, player.getName(), hidden, alwaysOn, priv, free, backwards, show, noNetwork, random, bungee);
int cost = Stargate.getCreateCost(player, gate); int cost = Stargate.getCreateCost(player, gate);
@ -1049,17 +1102,26 @@ public class Portal {
return null; return null;
} }
if (getByName(portal.getName(), portal.getNetwork()) != null) { // Don't do network checks for bungee gates
Stargate.debug("createPortal", "Name Error"); if (portal.isBungee()) {
Stargate.sendMessage(player, Stargate.getString("createExists")); if (bungeePortals.get(portal.getName().toLowerCase()) != null) {
return null; Stargate.debug("createPortal::Bungee", "Gate Exists");
} Stargate.sendMessage(player, Stargate.getString("createExists"));
return null;
// Check if there are too many gates in this network }
ArrayList<String> netList = allPortalsNet.get(portal.getNetwork().toLowerCase()); } else {
if (Stargate.maxGates > 0 && netList != null && netList.size() >= Stargate.maxGates) { if (getByName(portal.getName(), portal.getNetwork()) != null) {
Stargate.sendMessage(player, Stargate.getString("createFull")); Stargate.debug("createPortal", "Name Error");
return null; Stargate.sendMessage(player, Stargate.getString("createExists"));
return null;
}
// Check if there are too many gates in this network
ArrayList<String> netList = allPortalsNet.get(portal.getNetwork().toLowerCase());
if (Stargate.maxGates > 0 && netList != null && netList.size() >= Stargate.maxGates) {
Stargate.sendMessage(player, Stargate.getString("createFull"));
return null;
}
} }
if (cost > 0) { if (cost > 0) {
@ -1086,7 +1148,7 @@ public class Portal {
portal.register(); portal.register();
portal.drawSign(); portal.drawSign();
// Open always on gate // Open always on gate
if (portal.isRandom()) { if (portal.isRandom() || portal.isBungee()) {
portal.open(true); portal.open(true);
} else if (portal.isAlwaysOn()) { } else if (portal.isAlwaysOn()) {
Portal dest = Portal.getByName(destName, portal.getNetwork()); Portal dest = Portal.getByName(destName, portal.getNetwork());
@ -1101,14 +1163,17 @@ public class Portal {
} }
} }
// Open any always on gate pointing at this gate // Don't do network stuff for bungee gates
for (String originName : allPortalsNet.get(portal.getNetwork().toLowerCase())) { if (!portal.isBungee()) {
Portal origin = Portal.getByName(originName, portal.getNetwork()); // Open any always on gate pointing at this gate
if (origin == null) continue; for (String originName : allPortalsNet.get(portal.getNetwork().toLowerCase())) {
if (!origin.getDestinationName().equalsIgnoreCase(portal.getName())) continue; Portal origin = Portal.getByName(originName, portal.getNetwork());
if (!origin.isVerified()) continue; if (origin == null) continue;
if (origin.isFixed()) origin.drawSign(); if (!origin.getDestinationName().equalsIgnoreCase(portal.getName())) continue;
if (origin.isAlwaysOn()) origin.open(true); if (!origin.isVerified()) continue;
if (origin.isFixed()) origin.drawSign();
if (origin.isAlwaysOn()) origin.open(true);
}
} }
saveAllGates(portal.getWorld()); saveAllGates(portal.getWorld());
@ -1137,6 +1202,10 @@ public class Portal {
public static Portal getByBlock(Block block) { public static Portal getByBlock(Block block) {
return lookupBlocks.get(new Blox(block)); return lookupBlocks.get(new Blox(block));
} }
public static Portal getBungeeGate(String name) {
return bungeePortals.get(name);
}
public static void saveAllGates(World world) { public static void saveAllGates(World world) {
String loc = Stargate.getSaveLocation() + "/" + world.getName() + ".db"; String loc = Stargate.getSaveLocation() + "/" + world.getName() + ".db";
@ -1190,6 +1259,8 @@ public class Portal {
builder.append(portal.isNoNetwork()); builder.append(portal.isNoNetwork());
builder.append(':'); builder.append(':');
builder.append(portal.isRandom()); builder.append(portal.isRandom());
builder.append(':');
builder.append(portal.isBungee());
bw.append(builder.toString()); bw.append(builder.toString());
bw.newLine(); bw.newLine();
@ -1260,8 +1331,9 @@ public class Portal {
boolean show = (split.length > 17) ? split[17].equalsIgnoreCase("true") : false; boolean show = (split.length > 17) ? split[17].equalsIgnoreCase("true") : false;
boolean noNetwork = (split.length > 18) ? split[18].equalsIgnoreCase("true") : false; boolean noNetwork = (split.length > 18) ? split[18].equalsIgnoreCase("true") : false;
boolean random = (split.length > 19) ? split[19].equalsIgnoreCase("true") : false; boolean random = (split.length > 19) ? split[19].equalsIgnoreCase("true") : false;
boolean bungee = (split.length > 20) ? split[20].equalsIgnoreCase("true") : false;
Portal portal = new Portal(topLeft, modX, modZ, rotX, sign, button, dest, name, false, network, gate, owner, hidden, alwaysOn, priv, free, backwards, show, noNetwork, random); Portal portal = new Portal(topLeft, modX, modZ, rotX, sign, button, dest, name, false, network, gate, owner, hidden, alwaysOn, priv, free, backwards, show, noNetwork, random, bungee);
portal.register(); portal.register();
portal.close(true); portal.close(true);
} }
@ -1293,6 +1365,14 @@ public class Portal {
} }
if (!portal.isFixed()) continue; if (!portal.isFixed()) continue;
if (portal.isBungee()) {
OpenCount++;
portal.open(true);
portal.drawSign();
continue;
}
Portal dest = portal.getDestination(); Portal dest = portal.getDestination();
if (dest != null) { if (dest != null) {
if (portal.isAlwaysOn()) { if (portal.isAlwaysOn()) {

View File

@ -1,6 +1,7 @@
package net.TheDgtl.Stargate; package net.TheDgtl.Stargate;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Queue; import java.util.Queue;
@ -11,6 +12,7 @@ import java.util.logging.Logger;
import net.TheDgtl.Stargate.event.StargateAccessEvent; import net.TheDgtl.Stargate.event.StargateAccessEvent;
import net.TheDgtl.Stargate.event.StargateDestroyEvent; import net.TheDgtl.Stargate.event.StargateDestroyEvent;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Location; import org.bukkit.Location;
@ -98,6 +100,7 @@ public class Stargate extends JavaPlugin {
public static boolean handleVehicles = true; public static boolean handleVehicles = true;
public static boolean sortLists = false; public static boolean sortLists = false;
public static boolean protectEntrance = false; public static boolean protectEntrance = false;
public static boolean enableBungee = true;
public static ChatColor signColor; public static ChatColor signColor;
// Temp workaround for snowmen, don't check gate entrance // Temp workaround for snowmen, don't check gate entrance
@ -145,6 +148,12 @@ public class Stargate extends JavaPlugin {
this.loadConfig(); this.loadConfig();
// Enable the required channels for Bungee support
if (enableBungee) {
Bukkit.getMessenger().registerOutgoingPluginChannel(this, "SGBungee");
Bukkit.getMessenger().registerIncomingPluginChannel(this, "SGBungee", new pmListener());
}
// It is important to load languages here, as they are used during reloadGates() // It is important to load languages here, as they are used during reloadGates()
lang = new LangLoader(langFolder, Stargate.langName); lang = new LangLoader(langFolder, Stargate.langName);
@ -166,6 +175,19 @@ public class Stargate extends JavaPlugin {
getServer().getScheduler().scheduleSyncRepeatingTask(this, new SGThread(), 0L, 100L); getServer().getScheduler().scheduleSyncRepeatingTask(this, new SGThread(), 0L, 100L);
getServer().getScheduler().scheduleSyncRepeatingTask(this, new BlockPopulatorThread(), 0L, 1L); getServer().getScheduler().scheduleSyncRepeatingTask(this, new BlockPopulatorThread(), 0L, 1L);
// Enable Plugin Metrics
try {
MetricsLite ml = new MetricsLite(this);
if (!ml.isOptOut()) {
ml.start();
log.info("[Stargate] Plugin metrics enabled.");
} else {
log.info("[Stargate] Plugin metrics not enabled.");
}
} catch (IOException ex) {
log.warning("[Stargate] Error enabling plugin metrics: " + ex);
}
} }
public void loadConfig() { public void loadConfig() {
@ -186,6 +208,7 @@ public class Stargate extends JavaPlugin {
handleVehicles = newConfig.getBoolean("handleVehicles"); handleVehicles = newConfig.getBoolean("handleVehicles");
sortLists = newConfig.getBoolean("sortLists"); sortLists = newConfig.getBoolean("sortLists");
protectEntrance = newConfig.getBoolean("protectEntrance"); protectEntrance = newConfig.getBoolean("protectEntrance");
enableBungee = newConfig.getBoolean("enableBungee");
// Sign color // Sign color
String sc = newConfig.getString("signColor"); String sc = newConfig.getString("signColor");
try { try {
@ -567,7 +590,7 @@ public class Stargate extends JavaPlugin {
// Portal is free // Portal is free
if (src.isFree()) return 0; if (src.isFree()) return 0;
// Not charging for free destinations // Not charging for free destinations
if (!iConomyHandler.chargeFreeDestination && dest.isFree()) return 0; if (dest != null && !iConomyHandler.chargeFreeDestination && dest.isFree()) return 0;
// Cost is 0 if the player owns this gate and funds go to the owner // Cost is 0 if the player owns this gate and funds go to the owner
if (src.getGate().getToOwner() && src.getOwner().equalsIgnoreCase(player.getName())) return 0; if (src.getGate().getToOwner() && src.getOwner().equalsIgnoreCase(player.getName())) return 0;
// Player gets free gate use // Player gets free gate use
@ -637,6 +660,9 @@ public class Stargate extends JavaPlugin {
Portal portal = Portal.getByEntrance(event.getTo()); Portal portal = Portal.getByEntrance(event.getTo());
if (portal == null || !portal.isOpen()) return; if (portal == null || !portal.isOpen()) return;
// We don't support vehicles in Bungee portals
if (portal.isBungee()) return;
if (passenger instanceof Player) { if (passenger instanceof Player) {
Player player = (Player)passenger; Player player = (Player)passenger;
if (!portal.isOpenFor(player)) { if (!portal.isOpenFor(player)) {
@ -743,16 +769,17 @@ public class Stargate extends JavaPlugin {
} }
Portal destination = portal.getDestination(player); Portal destination = portal.getDestination(player);
if (destination == null) return; if (!portal.isBungee() && destination == null) return;
boolean deny = false; boolean deny = false;
// Check if player has access to this network // Check if player has access to this network
// For Bungee gates this will be the target server name
if (!canAccessNetwork(player, portal.getNetwork())) { if (!canAccessNetwork(player, portal.getNetwork())) {
deny = true; deny = true;
} }
// Check if player has access to destination world // Check if player has access to destination world
if (!canAccessWorld(player, destination.getWorld().getName())) { if (!portal.isBungee() && !canAccessWorld(player, destination.getWorld().getName())) {
deny = true; deny = true;
} }
@ -786,6 +813,18 @@ public class Stargate extends JavaPlugin {
} }
Stargate.sendMessage(player, Stargate.getString("teleportMsg"), false); Stargate.sendMessage(player, Stargate.getString("teleportMsg"), false);
if (portal.isBungee()) {
portal.teleport(player, portal, event);
// Teleport player via BungeeCord
String pMsg = portal.getNetwork() + "@#@" + portal.getDestinationName();
player.sendPluginMessage(stargate, "SGBungee", pMsg.getBytes());
// Close portal if required (Should never be)
portal.close(false);
return;
}
destination.teleport(player, portal, event); destination.teleport(player, portal, event);
portal.close(false); portal.close(false);
} }

View File

@ -0,0 +1,25 @@
package net.TheDgtl.Stargate;
import org.bukkit.entity.Player;
import org.bukkit.plugin.messaging.PluginMessageListener;
public class pmListener implements PluginMessageListener {
@Override
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
if (!channel.equals("SGBungee")) return;
// Message should be destination gate name.
Portal dest = Portal.getBungeeGate(new String(message));
// Specified an invalid gate. For now we'll just let them connect at their current location
if (dest == null) {
return;
}
// Teleport the player to their destination portal
dest.teleport(player, dest, null);
Stargate.debug("PML", "Recieved message: " + new String(message) + " Player: " + player.getName());
}
}

View File

@ -24,4 +24,9 @@ createConflict=Gate conflicts with existing gate
signRightClick=Right click signRightClick=Right click
signToUse=to use gate signToUse=to use gate
signRandom=Random signRandom=Random
signDisconnected=Disconnected signDisconnected=Disconnected
bungeeDisabled=BungeeCord support is disabled.
bungeeDeny=You do not have permission to create BungeeCord gates.
bungeeEmpty=BungeeCord gates require both a destination and network.
bungeeSign=Teleport to

View File

@ -1,8 +1,8 @@
author=Manuestaire author=Manuestaire
prefix=[Stargate] prefix=[Stargate]
teleportMsg=Teletransportado teleportMsg=Teletransportado
destroyMsg=Portal Destruido destroyMsg=Portal Destruído
invalidMsg=Destino Inválido invalidMsg=Elige Destino
blockMsg=Destino Bloqueado blockMsg=Destino Bloqueado
destEmpty=La lista de destinos está vacía destEmpty=La lista de destinos está vacía
denyMsg=Acceso denegado denyMsg=Acceso denegado
@ -22,7 +22,7 @@ createFull=Esta red est
createWorldDeny=No tienes permisos para acceder a ese mundo createWorldDeny=No tienes permisos para acceder a ese mundo
createConflict=El portal entra en conflicto con un portal ya existente createConflict=El portal entra en conflicto con un portal ya existente
signRightClick=Right click signRightClick=Click derecho
signToUse=to use gate signToUse=para usar
signRandom=Random signRandom=Aleatorio
signDisconnected=Disconnected signDisconnected=Desconectado

View File

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