[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:
parent
fc73e1fbda
commit
ac520665e6
4
README
4
README
@ -212,6 +212,10 @@ Client randomly crashes on teleport.
|
||||
=============
|
||||
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]
|
||||
- Resolve issue of language file being overwritten as ANSI instead of UTF8
|
||||
[Version 0.7.8.0]
|
||||
|
357
src/net/TheDgtl/Stargate/MetricsLite.java
Normal file
357
src/net/TheDgtl/Stargate/MetricsLite.java
Normal 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");
|
||||
}
|
||||
|
||||
}
|
@ -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, 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
|
||||
private Blox topLeft;
|
||||
private int modX;
|
||||
@ -95,6 +98,7 @@ public class Portal {
|
||||
private boolean show = false;
|
||||
private boolean noNetwork = false;
|
||||
private boolean random = false;
|
||||
private boolean bungee = false;
|
||||
|
||||
// In-use information
|
||||
private Player player;
|
||||
@ -107,7 +111,7 @@ public class Portal {
|
||||
float rotX, Blox id, Blox button,
|
||||
String dest, String name,
|
||||
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.modX = modX;
|
||||
this.modZ = modZ;
|
||||
@ -128,8 +132,9 @@ public class Portal {
|
||||
this.show = show;
|
||||
this.noNetwork = noNetwork;
|
||||
this.random = random;
|
||||
this.bungee = bungee;
|
||||
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()) {
|
||||
this.alwaysOn = false;
|
||||
@ -185,6 +190,10 @@ public class Portal {
|
||||
return random;
|
||||
}
|
||||
|
||||
public boolean isBungee() {
|
||||
return bungee;
|
||||
}
|
||||
|
||||
public void setAlwaysOn(boolean alwaysOn) {
|
||||
this.alwaysOn = alwaysOn;
|
||||
}
|
||||
@ -466,8 +475,14 @@ public class Portal {
|
||||
exit = pEvent.getExit();
|
||||
}
|
||||
|
||||
// The new method to teleport in a move event is set the "to" field.
|
||||
event.setTo(exit);
|
||||
// If no event is passed in, assume it's a teleport, and act as such
|
||||
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) {
|
||||
@ -530,8 +545,8 @@ public class Portal {
|
||||
} else {
|
||||
Stargate.log.log(Level.WARNING, "[Stargate] Missing destination point in .gate file " + gate.getFilename());
|
||||
}
|
||||
|
||||
if (loc != null) {
|
||||
|
||||
if (getWorld().getBlockTypeIdAt(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()) == Material.STEP.getId()) {
|
||||
loc.setY(loc.getY() + 0.5);
|
||||
}
|
||||
@ -691,7 +706,12 @@ public class Portal {
|
||||
Stargate.setLine(sign, ++done, "(" + network + ")");
|
||||
}
|
||||
} 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()) {
|
||||
Stargate.setLine(sign, ++done, "> " + Stargate.getString("signRandom") + " <");
|
||||
} else {
|
||||
@ -768,7 +788,6 @@ public class Portal {
|
||||
public void unregister(boolean removeAll) {
|
||||
Stargate.debug("Unregister", "Unregistering gate " + getName());
|
||||
close(true);
|
||||
lookupNamesNet.get(getNetwork().toLowerCase()).remove(getName().toLowerCase());
|
||||
|
||||
for (Blox block : getFrame()) {
|
||||
lookupBlocks.remove(block);
|
||||
@ -790,7 +809,21 @@ public class Portal {
|
||||
if (removeAll)
|
||||
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) {
|
||||
Sign sign = (Sign)id.getBlock().getState();
|
||||
@ -801,15 +834,6 @@ public class Portal {
|
||||
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());
|
||||
}
|
||||
|
||||
@ -818,12 +842,26 @@ public class Portal {
|
||||
}
|
||||
|
||||
private void register() {
|
||||
fixed = destination.length() > 0 || random;
|
||||
if (!lookupNamesNet.containsKey(getNetwork().toLowerCase())) {
|
||||
Stargate.debug("register", "Network not in lookupNamesNet, adding");
|
||||
lookupNamesNet.put(getNetwork().toLowerCase(), new HashMap<String, Portal>());
|
||||
fixed = destination.length() > 0 || random || bungee;
|
||||
|
||||
// Bungee gates are stored in their own list
|
||||
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()) {
|
||||
lookupBlocks.put(block, this);
|
||||
@ -843,12 +881,6 @@ public class Portal {
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -879,6 +911,7 @@ public class Portal {
|
||||
boolean show = (options.indexOf('s') != -1);
|
||||
boolean noNetwork = (options.indexOf('n') != -1);
|
||||
boolean random = (options.indexOf('r') != -1);
|
||||
boolean bungee = (options.indexOf('u') != -1);
|
||||
|
||||
// Check permissions for options.
|
||||
if (hidden && !Stargate.canOption(player, "hidden")) hidden = false;
|
||||
@ -890,6 +923,20 @@ public class Portal {
|
||||
if (noNetwork && !Stargate.canOption(player, "nonetwork")) noNetwork = 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.
|
||||
if (alwaysOn && destName.length() == 0) {
|
||||
alwaysOn = false;
|
||||
@ -906,6 +953,12 @@ public class Portal {
|
||||
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
|
||||
int modX = 0;
|
||||
int modZ = 0;
|
||||
@ -966,9 +1019,9 @@ public class Portal {
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
@ -976,7 +1029,7 @@ public class Portal {
|
||||
String denyMsg = "";
|
||||
|
||||
// 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");
|
||||
if (Stargate.canCreatePersonal(player)) {
|
||||
network = player.getName();
|
||||
@ -1001,7 +1054,7 @@ public class Portal {
|
||||
}
|
||||
|
||||
// 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);
|
||||
if (p != null) {
|
||||
String world = p.getWorld().getName();
|
||||
@ -1025,7 +1078,7 @@ public class Portal {
|
||||
|
||||
Blox button = 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);
|
||||
|
||||
@ -1049,17 +1102,26 @@ public class Portal {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (getByName(portal.getName(), portal.getNetwork()) != null) {
|
||||
Stargate.debug("createPortal", "Name Error");
|
||||
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;
|
||||
// Don't do network checks for bungee gates
|
||||
if (portal.isBungee()) {
|
||||
if (bungeePortals.get(portal.getName().toLowerCase()) != null) {
|
||||
Stargate.debug("createPortal::Bungee", "Gate Exists");
|
||||
Stargate.sendMessage(player, Stargate.getString("createExists"));
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
if (getByName(portal.getName(), portal.getNetwork()) != null) {
|
||||
Stargate.debug("createPortal", "Name Error");
|
||||
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) {
|
||||
@ -1086,7 +1148,7 @@ public class Portal {
|
||||
portal.register();
|
||||
portal.drawSign();
|
||||
// Open always on gate
|
||||
if (portal.isRandom()) {
|
||||
if (portal.isRandom() || portal.isBungee()) {
|
||||
portal.open(true);
|
||||
} else if (portal.isAlwaysOn()) {
|
||||
Portal dest = Portal.getByName(destName, portal.getNetwork());
|
||||
@ -1101,14 +1163,17 @@ public class Portal {
|
||||
}
|
||||
}
|
||||
|
||||
// Open any always on gate pointing at this gate
|
||||
for (String originName : allPortalsNet.get(portal.getNetwork().toLowerCase())) {
|
||||
Portal origin = Portal.getByName(originName, portal.getNetwork());
|
||||
if (origin == null) continue;
|
||||
if (!origin.getDestinationName().equalsIgnoreCase(portal.getName())) continue;
|
||||
if (!origin.isVerified()) continue;
|
||||
if (origin.isFixed()) origin.drawSign();
|
||||
if (origin.isAlwaysOn()) origin.open(true);
|
||||
// Don't do network stuff for bungee gates
|
||||
if (!portal.isBungee()) {
|
||||
// Open any always on gate pointing at this gate
|
||||
for (String originName : allPortalsNet.get(portal.getNetwork().toLowerCase())) {
|
||||
Portal origin = Portal.getByName(originName, portal.getNetwork());
|
||||
if (origin == null) continue;
|
||||
if (!origin.getDestinationName().equalsIgnoreCase(portal.getName())) continue;
|
||||
if (!origin.isVerified()) continue;
|
||||
if (origin.isFixed()) origin.drawSign();
|
||||
if (origin.isAlwaysOn()) origin.open(true);
|
||||
}
|
||||
}
|
||||
|
||||
saveAllGates(portal.getWorld());
|
||||
@ -1137,6 +1202,10 @@ public class Portal {
|
||||
public static Portal getByBlock(Block block) {
|
||||
return lookupBlocks.get(new Blox(block));
|
||||
}
|
||||
|
||||
public static Portal getBungeeGate(String name) {
|
||||
return bungeePortals.get(name);
|
||||
}
|
||||
|
||||
public static void saveAllGates(World world) {
|
||||
String loc = Stargate.getSaveLocation() + "/" + world.getName() + ".db";
|
||||
@ -1190,6 +1259,8 @@ public class Portal {
|
||||
builder.append(portal.isNoNetwork());
|
||||
builder.append(':');
|
||||
builder.append(portal.isRandom());
|
||||
builder.append(':');
|
||||
builder.append(portal.isBungee());
|
||||
|
||||
bw.append(builder.toString());
|
||||
bw.newLine();
|
||||
@ -1260,8 +1331,9 @@ public class Portal {
|
||||
boolean show = (split.length > 17) ? split[17].equalsIgnoreCase("true") : false;
|
||||
boolean noNetwork = (split.length > 18) ? split[18].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.close(true);
|
||||
}
|
||||
@ -1293,6 +1365,14 @@ public class Portal {
|
||||
}
|
||||
|
||||
if (!portal.isFixed()) continue;
|
||||
|
||||
if (portal.isBungee()) {
|
||||
OpenCount++;
|
||||
portal.open(true);
|
||||
portal.drawSign();
|
||||
continue;
|
||||
}
|
||||
|
||||
Portal dest = portal.getDestination();
|
||||
if (dest != null) {
|
||||
if (portal.isAlwaysOn()) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.TheDgtl.Stargate;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
@ -11,6 +12,7 @@ import java.util.logging.Logger;
|
||||
import net.TheDgtl.Stargate.event.StargateAccessEvent;
|
||||
import net.TheDgtl.Stargate.event.StargateDestroyEvent;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
@ -98,6 +100,7 @@ public class Stargate extends JavaPlugin {
|
||||
public static boolean handleVehicles = true;
|
||||
public static boolean sortLists = false;
|
||||
public static boolean protectEntrance = false;
|
||||
public static boolean enableBungee = true;
|
||||
public static ChatColor signColor;
|
||||
|
||||
// Temp workaround for snowmen, don't check gate entrance
|
||||
@ -145,6 +148,12 @@ public class Stargate extends JavaPlugin {
|
||||
|
||||
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()
|
||||
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 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() {
|
||||
@ -186,6 +208,7 @@ public class Stargate extends JavaPlugin {
|
||||
handleVehicles = newConfig.getBoolean("handleVehicles");
|
||||
sortLists = newConfig.getBoolean("sortLists");
|
||||
protectEntrance = newConfig.getBoolean("protectEntrance");
|
||||
enableBungee = newConfig.getBoolean("enableBungee");
|
||||
// Sign color
|
||||
String sc = newConfig.getString("signColor");
|
||||
try {
|
||||
@ -567,7 +590,7 @@ public class Stargate extends JavaPlugin {
|
||||
// Portal is free
|
||||
if (src.isFree()) return 0;
|
||||
// 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
|
||||
if (src.getGate().getToOwner() && src.getOwner().equalsIgnoreCase(player.getName())) return 0;
|
||||
// Player gets free gate use
|
||||
@ -637,6 +660,9 @@ public class Stargate extends JavaPlugin {
|
||||
Portal portal = Portal.getByEntrance(event.getTo());
|
||||
if (portal == null || !portal.isOpen()) return;
|
||||
|
||||
// We don't support vehicles in Bungee portals
|
||||
if (portal.isBungee()) return;
|
||||
|
||||
if (passenger instanceof Player) {
|
||||
Player player = (Player)passenger;
|
||||
if (!portal.isOpenFor(player)) {
|
||||
@ -743,16 +769,17 @@ public class Stargate extends JavaPlugin {
|
||||
}
|
||||
|
||||
Portal destination = portal.getDestination(player);
|
||||
if (destination == null) return;
|
||||
if (!portal.isBungee() && destination == null) return;
|
||||
|
||||
boolean deny = false;
|
||||
// Check if player has access to this network
|
||||
// For Bungee gates this will be the target server name
|
||||
if (!canAccessNetwork(player, portal.getNetwork())) {
|
||||
deny = true;
|
||||
}
|
||||
|
||||
// Check if player has access to destination world
|
||||
if (!canAccessWorld(player, destination.getWorld().getName())) {
|
||||
if (!portal.isBungee() && !canAccessWorld(player, destination.getWorld().getName())) {
|
||||
deny = true;
|
||||
}
|
||||
|
||||
@ -786,6 +813,18 @@ public class Stargate extends JavaPlugin {
|
||||
}
|
||||
|
||||
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);
|
||||
portal.close(false);
|
||||
}
|
||||
|
25
src/net/TheDgtl/Stargate/pmListener.java
Normal file
25
src/net/TheDgtl/Stargate/pmListener.java
Normal 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());
|
||||
}
|
||||
|
||||
}
|
@ -24,4 +24,9 @@ createConflict=Gate conflicts with existing gate
|
||||
signRightClick=Right click
|
||||
signToUse=to use gate
|
||||
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
|
||||
|
@ -1,8 +1,8 @@
|
||||
author=Manuestaire
|
||||
prefix=[Stargate]
|
||||
teleportMsg=Teletransportado
|
||||
destroyMsg=Portal Destruido
|
||||
invalidMsg=Destino Inválido
|
||||
destroyMsg=Portal Destruído
|
||||
invalidMsg=Elige Destino
|
||||
blockMsg=Destino Bloqueado
|
||||
destEmpty=La lista de destinos está vacía
|
||||
denyMsg=Acceso denegado
|
||||
@ -22,7 +22,7 @@ createFull=Esta red est
|
||||
createWorldDeny=No tienes permisos para acceder a ese mundo
|
||||
createConflict=El portal entra en conflicto con un portal ya existente
|
||||
|
||||
signRightClick=Right click
|
||||
signToUse=to use gate
|
||||
signRandom=Random
|
||||
signDisconnected=Disconnected
|
||||
signRightClick=Click derecho
|
||||
signToUse=para usar
|
||||
signRandom=Aleatorio
|
||||
signDisconnected=Desconectado
|
@ -1,6 +1,6 @@
|
||||
name: Stargate
|
||||
main: net.TheDgtl.Stargate.Stargate
|
||||
version: 0.7.8.1
|
||||
version: 0.7.9.0
|
||||
description: Stargate mod for Bukkit
|
||||
author: Drakia
|
||||
website: http://www.thedgtl.net
|
||||
|
Loading…
Reference in New Issue
Block a user