+ * This allows you to call {@link #getConnection()}. + *
+ * + * @return The instance of this database. + */ + public static BaseDatabase getInstance() { + if (instance == null) { + instance = new BaseDatabase(); + } + + return instance; + } + + public static boolean runCustomQuery(String query) { + try (Connection connection = getInstance().getConnection()) { + try (PreparedStatement statement = connection.prepareStatement(query)) { + statement.execute(); + } + } catch (SQLException e) { + e.printStackTrace(); + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/database/DatabaseHandler.java b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/database/DatabaseHandler.java new file mode 100644 index 0000000..8575df3 --- /dev/null +++ b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/database/DatabaseHandler.java @@ -0,0 +1,193 @@ +package net.grandtheftmc.Bungee.database; + +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.SQLException; + +import com.zaxxer.hikari.HikariDataSource; + +import net.grandtheftmc.Bungee.database.component.Database; +import net.grandtheftmc.Bungee.database.component.DatabaseCredentials; + +/** + * A generic database handler that holds a HikariCP data source so we can have + * multiple database connection. + * + * Note: This should be init() with either the Plugin/Config path to load + * settings, or can be init() with just database credentials, which uses default + * HikariCP settings. + * + * @author sbahr + */ +public class DatabaseHandler implements Database { + + /** The default MySQL driver */ + private static final String DEFAULT_MYSQL_DRIVER = "com.mysql.jdbc.Driver"; + /** The database credentials */ + private DatabaseCredentials dbCreds; + /** Data source connection pool from HikariCP */ + private HikariDataSource hikariSource = new HikariDataSource(); + + // NOTE: HikariCP performs best at fixed pool size, minIdle=maxConns + // https://github.com/brettwooldridge/HikariCP + + /** How many minimum idle connections should we always have (2) */ + protected int minIdle = 2; + /** How many max connections should exist in pool (2) */ + protected int maxPoolSize = 2; + /** How long, in millis, we stop waiting for new connection (15 secs) */ + protected int connectionTimeoutMs = 15 * 1000; + /** How long, in millis, before connections timeout (45 secs) */ + protected int idleTimeoutMs = 45 * 1000; + /** How long, in millis, this connection can be alive for (30 mins) */ + protected int maxLifetimeMs = 30 * 60 * 1000; + /** How long, in millis, can a connection be gone from a pool (4 secs) */ + protected int leakDetectionThresholdMs = 4 * 1000; + /** The ping alive query */ + protected String connectionTestQuery = "SELECT 1"; + /** Should the connection cache prepared statements */ + protected boolean cachePreparedStatements = true; + /** Number of prepared statements to cache per connection */ + protected int preparedStatementCache = 250; + /** Max number of prepared statements to have */ + protected int maxPreparedStatementCache = 2048; + /** The log writer for Hikari */ + protected PrintWriter logWriter = new PrintWriter(System.out); + + /** + * Initialize the handler with the specified database credentials. + *+ * Sets up the configuration for the connection pool and default settings. + *
+ * + * @param dbCreds - the credentials for the database + * @param driver - the driver class + */ + public void init(DatabaseCredentials dbCreds, String driver) { + this.dbCreds = dbCreds; + + // set the driver name for the connection driver + hikariSource.setDriverClassName(driver); + + // assume host/port combo together, or could just be without port + String connURL = dbCreds.getHost(); + + // if a port is defined + if (dbCreds.getPort() > 0) { + connURL = dbCreds.getHost() + ":" + dbCreds.getPort(); + } + + // set the jdbc url, note the character encoding + // https://stackoverflow.com/questions/3040597/jdbc-character-encoding + hikariSource.setJdbcUrl("jdbc:mysql://" + connURL + "/" + dbCreds.getName() + "?characterEncoding=UTF-8"); + + // set user/pass + hikariSource.setUsername(dbCreds.getUser()); + hikariSource.setPassword(dbCreds.getPass()); + + /** General conf settings for hikari */ + // works best when minIdle=maxPoolSize + hikariSource.setMinimumIdle(minIdle); + hikariSource.setMaximumPoolSize(maxPoolSize); + + // how long to wait, for a new connection + hikariSource.setConnectionTimeout(connectionTimeoutMs); + // how long before idle connection is destroyed + hikariSource.setIdleTimeout(idleTimeoutMs); + // how long can a connection exist + hikariSource.setMaxLifetime(maxLifetimeMs); + // how long connection is away from a pool before saying uh oh + hikariSource.setLeakDetectionThreshold(leakDetectionThresholdMs); + // test query to confirm alive + hikariSource.setConnectionTestQuery(connectionTestQuery); + // should we cache prepared statements + hikariSource.addDataSourceProperty("cachePrepStmts", "" + cachePreparedStatements); + // the size of the prepared statement cache + hikariSource.addDataSourceProperty("prepStmtCacheSize", "" + preparedStatementCache); + // the maximum cache limit + hikariSource.addDataSourceProperty("prepStmtCacheSqlLimit", "" + maxPreparedStatementCache); + + // MUST set log writer + try { + hikariSource.setLogWriter(new PrintWriter(System.out)); + } + catch (SQLException e) { + e.printStackTrace(); + } + } + + /** + * Initialize the database handler given the credentials. + * + * @param credentials - the login details to this database + */ + protected void init(DatabaseCredentials credentials) { + this.init(credentials, DEFAULT_MYSQL_DRIVER); + } + + /** + * Load the settings for HikariCP from the yaml config and stores them + * locally in the object, then initializes the database handler. + */ + public void init(String host, int port, String dbName, String user, String pass) { +// +// String host = config.getString(path + ".host", "localhost"); +// int port = config.getInt(path + ".port", 3306); +// String dbName = config.getString(path + ".database", "hyphenical"); +// String username = config.getString(path + ".user", "user"); +// String password = config.getString(path + ".password", "pass123"); +// +// // connection stats +// int minIdle = config.getInt(path + ".min-idle", 2); +// int maxConns = config.getInt(path + ".max-conn", 2); +// +// // load local fields +// this.minIdle = minIdle < 0 ? 1 : minIdle; +// this.maxPoolSize = maxConns < 1 ? 1 : maxConns; +// +// // create database credentials + DatabaseCredentials creds = new DatabaseCredentials(host, port, dbName, user, pass); + +// // initialize hikari cp + init(creds); + } + + /** + * Close HikariCP connection pool, and all the connections. + *+ * Note: This should be called whenever the plugin turns off! + *
+ */ + public void close() { + if (hikariSource != null && !hikariSource.isClosed()) { + hikariSource.close(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public DatabaseCredentials getCredentials() { + return dbCreds; + } + + /** + * {@inheritDoc} + */ + @Override + public Connection getConnection() { + if (hikariSource != null) { + try { + Connection conn = hikariSource.getConnection(); + return conn; + } + catch (Exception e) { + System.out.println("[DatabaseHandler] Unable to grab a connection from the connection pool!"); + e.printStackTrace(); + } + } + + return null; + } +} diff --git a/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/database/component/Database.java b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/database/component/Database.java new file mode 100644 index 0000000..1c7e027 --- /dev/null +++ b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/database/component/Database.java @@ -0,0 +1,26 @@ +package net.grandtheftmc.Bungee.database.component; + +import java.sql.Connection; + +/** + * An interface that represents a database (and it's credentials). + * + * @author sbahr + */ +public interface Database { + + /** + * Get the credentials for the database. + * + * @return The credentials for the database. + */ + DatabaseCredentials getCredentials(); + + /** + * Get the connection for the database. + * + * @return The connection for the database. + */ + Connection getConnection(); + +} diff --git a/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/database/component/DatabaseCredentials.java b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/database/component/DatabaseCredentials.java new file mode 100644 index 0000000..52c737f --- /dev/null +++ b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/database/component/DatabaseCredentials.java @@ -0,0 +1,112 @@ +package net.grandtheftmc.Bungee.database.component; + +/** + * Represents an immutable data object containing information about a connection + * to the database. + * + * @author sbahr + */ +public class DatabaseCredentials { + + /** The host of the db, ex: example.com */ + private final String host; + /** The port associated, ex: 3306 */ + private final int port; + /** The name of the database to use, ex: test_db */ + private final String dbName; + /** The name of the user that has access to the db, ex: user123 */ + private final String dbUser; + /** The password for the user, ex: pass123 */ + private final String dbPass; + + /** + * Construct a new DatabaseCredentials object. + * + * @param host - the host of the db, ex: example.com + * @param port - the port for the db, ex: 3306 + * @param dbName - the name of the db to use, ex: test_db + * @param dbUser - the user of the db, ex: user123 + * @param dbPass - the pass for the user, ex: pass123 + */ + public DatabaseCredentials(String host, int port, String dbName, String dbUser, String dbPass) { + this.host = host; + this.port = port; + this.dbName = dbName; + this.dbUser = dbUser; + this.dbPass = dbPass; + } + + /** + * Construct a new DatabaseCredentials object. + *+ * The port for the host is not defined as an argument and either should be + * supplied in the host argument or use a different constructor. If no port + * is defined, we'll use the default port. + *
+ * + * @param host - the host of the db, ex: example.com + * @param dbName - the name of the db to use, ex: test_db + * @param dbUser - the user of the db, ex: user123 + * @param dbPass - the pass for the user, ex: pass123 + */ + public DatabaseCredentials(String host, String dbName, String dbUser, String dbPass) { + this(host, -1, dbName, dbUser, dbPass); + } + + /** + * Get the host associated with this database credentials. + *+ * The host URL, ex: www.example.com + *
+ * + * @return The host URL for the database. + */ + public final String getHost() { + return host; + } + + /** + * Get the port number for the database. + *+ * The port number could be irrelevant if defined in {@link #getHost()}. If + * the port number is -1, use the default port. + *
+ * + * @return The port number for the database. + */ + public final int getPort() { + return port; + } + + /** + * Get the name of the database that we are using. + *+ * This is the name of the database, as there can be multiple databases + * within one database. + *
+ * + * @return The name of the database we are using. + */ + public final String getName() { + return dbName; + } + + /** + * Get the username of the user that has access to the database. + * + * @return The name for the user that has access to this database. + */ + public final String getUser() { + return dbUser; + } + + /** + * Get the password of the user that has access to the database. + * + * @return The password, associated with the user, that has access to this + * database. + */ + public final String getPass() { + return dbPass; + } +} diff --git a/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/help/HelpCore.java b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/help/HelpCore.java new file mode 100644 index 0000000..d898e09 --- /dev/null +++ b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/help/HelpCore.java @@ -0,0 +1,203 @@ +package net.grandtheftmc.Bungee.help; + +import net.grandtheftmc.Bungee.Bungee; +import net.grandtheftmc.Bungee.Utils; +import net.grandtheftmc.Bungee.help.data.HelpCategory; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.config.Configuration; + +import java.util.*; + +/** + * Created by Adam on 05/06/2017. + */ +public class HelpCore { + + /* + Sample Data: (Tab to delimit keys for multiple checks) + ------------------------------------------------------ + + help: + topic: + matches: [] + help: [] + subtopic: + matches: [] + help: [] - Can be empty or not, doesn't matter + + Example: + -------- + + help: + Vehicles: + matches: vehicle,vehicles + help: [] + Jetpacks: + matches: + - 'jetpack' + - 'jetpacks' + help: + - 'Jetpacks are cool.' + - 'Go buy a Jetpack.' + Wingsuits: + matches: + - 'fly' + - 'wingsuit' + - 'wingsuits' + - 'wings' + help: + - 'Wingsuits are faster than JetPacks.' + - 'Or, are they' + + + */ + + /** + * A list of all the root categories. + */ + private List");
+ textComponent.setColor(ChatColor.GRAY);
+ player.sendMessage(textComponent);
+ }
+ }
+ });
+ }, 0, 10, TimeUnit.SECONDS);
+ }
+}
diff --git a/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/tasks/PlaytimePurgeTask.java b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/tasks/PlaytimePurgeTask.java
new file mode 100644
index 0000000..b97e912
--- /dev/null
+++ b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/tasks/PlaytimePurgeTask.java
@@ -0,0 +1,17 @@
+package net.grandtheftmc.Bungee.tasks;
+
+import net.grandtheftmc.Bungee.Bungee;
+import net.grandtheftmc.Bungee.Lang;
+import net.grandtheftmc.Bungee.users.User;
+import net.grandtheftmc.Bungee.utils.PlaytimeManager;
+
+import java.util.Optional;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+public class PlaytimePurgeTask {
+
+ public PlaytimePurgeTask() {
+ Bungee.getInstance().getProxy().getScheduler().schedule(Bungee.getInstance(), PlaytimeManager::purgeOldSessions, 0, 1, TimeUnit.DAYS);
+ }
+}
diff --git a/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/tasks/ServerStatusTask.java b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/tasks/ServerStatusTask.java
new file mode 100644
index 0000000..86b456b
--- /dev/null
+++ b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/tasks/ServerStatusTask.java
@@ -0,0 +1,20 @@
+package net.grandtheftmc.Bungee.tasks;
+
+import net.grandtheftmc.Bungee.Bungee;
+import net.grandtheftmc.Bungee.utils.ServerStatus;
+
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.TimeUnit;
+
+public class ServerStatusTask {
+
+ public ServerStatusTask() {
+ Bungee.getInstance().getProxy().getScheduler().schedule(Bungee.getInstance(), () -> Bungee.getInstance().getProxy().getServers().values().forEach(serverInfo -> {
+ try {
+ ServerStatus serverStatus = ServerStatus.getServerStatus(serverInfo);
+ serverStatus.updateStatus();
+ }
+ catch (RejectedExecutionException ignored) {}
+ }), 1, 15, TimeUnit.SECONDS);
+ }
+}
diff --git a/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/users/User.java b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/users/User.java
new file mode 100644
index 0000000..0236541
--- /dev/null
+++ b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/users/User.java
@@ -0,0 +1,212 @@
+package net.grandtheftmc.Bungee.users;
+
+import net.grandtheftmc.Bungee.Bungee;
+import net.grandtheftmc.Bungee.database.BaseDatabase;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+public class User {
+ private final UUID uuid;
+ private String username;
+ private UserRank ur;
+ private int authyId = 0;
+ private boolean authyVerified;
+ private String lastIPAddress = "0";
+
+ private boolean staffChat;
+ private boolean socialSpy;
+ private long lastJoin;
+ private long lastQuit;
+ private long playtime;
+
+ public User(UUID uuid) {
+ this.uuid = uuid;
+ this.dataCheck();
+ }
+
+ public void dataCheck() {
+ this.update();
+
+ try (Connection connection = BaseDatabase.getInstance().getConnection()) {
+ try (PreparedStatement statement = connection.prepareStatement("INSERT INTO Authy (uuid,authyId) VALUES (?, ?) ON DUPLICATE KEY UPDATE uuid=?;")) {
+ statement.setString(1, this.uuid.toString());
+ statement.setInt(2, this.authyId);
+ statement.setString(3, this.uuid.toString());
+
+ statement.execute();
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public UUID getUUID() {
+ return this.uuid;
+ }
+
+ public String getUsername() {
+ return this.username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public UserRank getUserRank() {
+ return this.ur;
+ }
+
+ public void setUserRank(UserRank ur) {
+ this.ur = ur;
+ }
+
+ public boolean isRank(UserRank userRank) {
+ return userRank == this.ur || this.ur.isHigherThan(userRank);
+ }
+
+ public boolean isSpecial() {
+ return this.ur != UserRank.DEFAULT;
+ }
+
+ public int getAuthyId() {
+ return this.authyId;
+ }
+
+ public void setAuthyId(int authyId) {
+ this.authyId = authyId;
+
+ Bungee.getInstance().getProxy().getScheduler().runAsync(Bungee.getInstance(), () -> {
+ try (Connection connection = BaseDatabase.getInstance().getConnection()) {
+ try (PreparedStatement statement = connection.prepareStatement("UPDATE Authy SET authyId=? WHERE uuid=?;")) {
+ statement.setInt(1, this.authyId);
+ statement.setString(2, this.uuid.toString());
+ statement.execute();
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+
+ public boolean isAuthyVerified() {
+ if (!this.isRank(UserRank.BUILDER)) return true;
+ return authyVerified;
+ }
+
+ public void setAuthyVerified(boolean authyVerified) {
+ this.authyVerified = authyVerified;
+ }
+
+ public String getLastIPAddress() {
+ return this.lastIPAddress;
+ }
+
+ public void setLastIPAddress(String lastIPAddress) {
+ this.lastIPAddress = lastIPAddress;
+
+ Bungee.getInstance().getProxy().getScheduler().runAsync(Bungee.getInstance(), () -> {
+ try (Connection connection = BaseDatabase.getInstance().getConnection()) {
+ try (PreparedStatement statement = connection.prepareStatement("UPDATE Authy SET lastIPAddress=? WHERE uuid=?;")) {
+ statement.setString(1, this.lastIPAddress);
+ statement.setString(2, this.uuid.toString());
+ statement.execute();
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+
+ public boolean getStaffChat() {
+ return this.staffChat;
+ }
+
+ public void setStaffChat(boolean b) {
+ this.staffChat = b;
+ }
+
+ public void toggleStaffChat() {
+ this.staffChat = !this.staffChat;
+ }
+
+ public boolean getSocialSpy() {
+ return this.socialSpy;
+ }
+
+ public void setSocialSpy(boolean b) {
+ this.socialSpy = b;
+ }
+
+ public Long getLastJoin() {
+ return this.lastJoin;
+ }
+
+ public void setLastJoin(Long lastJoin) {
+ this.lastJoin = lastJoin;
+ }
+
+ public long getLastQuit() {
+ return this.lastQuit;
+ }
+
+ public void setLastQuit(long lastQuit) {
+ this.lastQuit = lastQuit;
+ }
+
+ public Long getPlaytime() {
+ return this.playtime;
+ }
+
+ public void setPlaytime(Long playtime) {
+ this.playtime = playtime;
+ }
+
+ public String getColoredName(ProxiedPlayer player) {
+ return this.ur.getColor() + (this.ur == UserRank.DEFAULT ? "" : "&l") + player.getName();
+ }
+
+ public String getColoredName() {
+ return this.ur.getColor() + (this.ur == UserRank.DEFAULT ? "" : "&l") + this.username;
+ }
+
+ public void update() {
+ Bungee.getInstance().getProxy().getScheduler().runAsync(Bungee.getInstance(), () -> {
+ try (Connection connection = BaseDatabase.getInstance().getConnection()) {
+ try (PreparedStatement statement = connection.prepareStatement("SELECT UP.rank, U.name FROM user_profile UP, user U WHERE UP.uuid=UNHEX(?) AND UP.uuid=U.uuid;")) {
+ statement.setString(1, this.uuid.toString().replaceAll("-", ""));
+ try (ResultSet result = statement.executeQuery()) {
+ if (result.next()) {
+ UserRank ur = UserRank.getUserRank(result.getString("rank"));
+ if (!ur.isHigherThan(UserRank.YOUTUBER)) {
+ Bungee.getUserManager().getLoadedUsers().remove(this);
+ return;
+ }
+ this.ur = ur;
+ }
+ }
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ try (Connection connection = BaseDatabase.getInstance().getConnection()) {
+ try (PreparedStatement statement = connection.prepareStatement("SELECT authyId,lastIPAddress FROM Authy WHERE uuid=? LIMIT 1;")) {
+ statement.setString(1, this.uuid.toString());
+ try (ResultSet result = statement.executeQuery()) {
+ if (result.next()) {
+ this.authyId = result.getInt("authyId");
+ this.lastIPAddress = result.getString("lastIPAddress");
+ }
+ }
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+}
diff --git a/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/users/UserManager.java b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/users/UserManager.java
new file mode 100644
index 0000000..7fb37b7
--- /dev/null
+++ b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/users/UserManager.java
@@ -0,0 +1,327 @@
+package net.grandtheftmc.Bungee.users;
+
+import com.google.common.collect.Maps;
+import net.grandtheftmc.Bungee.Bungee;
+import net.grandtheftmc.Bungee.database.BaseDatabase;
+import net.grandtheftmc.Bungee.utils.Callback;
+import net.grandtheftmc.Bungee.utils.UUIDUtil;
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.config.Configuration;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class UserManager {
+
+ private final Map loadedUsers = new HashMap<>();
+
+ /**
+ * Default set of permissions, loaded from configuration
+ *
+ * @see #loadPerms()
+ */
+ private final Map> perms = new HashMap<>();
+
+ public UserManager() {
+ this.loadPerms();
+ this.loadUsers();
+ }
+
+ /**
+ * Load permissions ranks from configuration file.
+ */
+ public void loadPerms() {
+ Configuration c = Bungee.getSettings().getPermsConfig();
+ for (String s : c.getKeys()) {
+ UserRank rank = UserRank.getUserRankOrNull(s);
+ if (rank != null) this.perms.put(rank, c.getStringList(s));
+ }
+ this.setPerms();
+ }
+
+ /**
+ * Load a default set of users into redis memory from MySQL storage.
+ *
+ * The default set is of all staff members, additional users are loaded on demand.
+ */
+ public void loadUsers() {
+ Bungee.getInstance().getProxy().getScheduler().runAsync(Bungee.getInstance(), () -> {
+
+ try (Connection connection = BaseDatabase.getInstance().getConnection()) {
+ this.step1(connection, obj -> {
+ this.step2(connection, obj);
+ });
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+// try (Connection connection = BaseDatabase.getInstance().getConnection()) {
+// try (PreparedStatement statement = connection.prepareStatement("SELECT HEX(uuid) AS uid,rank FROM `user_profile` WHERE rank IN ('builder', 'helpop', 'mod', 'srmod', 'admin', 'dev', 'manager', 'owner');")) {
+// try (ResultSet result = statement.executeQuery()) {
+// HashMap map = Maps.newHashMap();
+// while (result.next()) {
+// UUID u = UUIDUtil.createUUID(result.getString("uid")).orElse(null);
+// if (u == null) continue;
+// map.put(u, UserRank.getUserRank(result.getString("rank")));
+// }
+//
+// UUID uuid = null;
+// for (UUID uid : map.keySet()) {
+// uuid = uid;
+// try (PreparedStatement statement2 = connection.prepareStatement("SELECT lastname,socialSpy FROM `users` WHERE `uuid`=?;")) {
+// statement2.setString(1, uid.toString());
+// try (ResultSet result2 = statement2.executeQuery()) {
+// if (result2.next()) {
+// String username = result2.getString("lastname");
+// boolean socialSpy = result2.getBoolean("socialSpy");
+//
+// //Add user key to hashmap.
+// User user = this.loadedUsers.computeIfAbsent(uid, k -> {
+// User u = new User(k);
+// Bungee.getInstance().getLogger().info("Successfully cached user " + u.getUUID());
+// return u;
+// });
+//
+// //Set ranks and other miscellaneous data.
+// user.setUserRank(map.get(uid));
+// user.setSocialSpy(socialSpy);
+// user.setUsername(username);
+// }
+// }
+// } catch (SQLException e) {
+// e.printStackTrace();
+// }
+// }
+//
+// ResultSet rs = Bungee.getSQL().query("SELECT authyId,lastIPAddress FROM Authy WHERE uuid='" + uuid.toString() + "' LIMIT 1;");
+// Optional user = getLoadedUser(uuid);
+// if (!user.isPresent()) {
+// rs.close();
+// return;
+// }
+//
+// int authyId = 0;
+// String ipAddress = "0";
+// if (rs.next()) {
+// authyId = rs.getInt("authyId");
+// ipAddress = rs.getString("lastIPAddress");
+// }
+// user.get().setAuthyId(authyId);
+// user.get().setLastIPAddress(ipAddress);
+// rs.close();
+// }
+// }
+// } catch (SQLException e) {
+// e.printStackTrace();
+// }
+
+// try {
+// ResultSet resultSet = Bungee.getSQL().query("SELECT HEX(uuid) AS uid,rank FROM `user_profile` WHERE rank IN ('builder', 'helpop', 'mod', 'srmod', 'admin', 'dev', 'manager', 'owner');");
+// HashMap map = Maps.newHashMap();
+// while (resultSet.next()) {
+// UUID u = UUIDUtil.createUUID(resultSet.getString("uid")).orElse(null);
+// if (u == null) continue;
+// map.put(u, UserRank.getUserRank(resultSet.getString("rank")));
+// }
+// resultSet.close();
+
+// UUID uuid = null;
+// for (UUID uid : map.keySet()) {
+// uuid = uid;
+// try (PreparedStatement statement = Bungee.getSQL().prepareStatement("SELECT lastname,socialSpy FROM `users` WHERE `uuid`=?;")) {
+// statement.setString(1, uid.toString());
+// try (ResultSet set = statement.executeQuery()) {
+// if (set.next()) {
+// String username = set.getString("lastname");
+// boolean socialSpy = set.getBoolean("socialSpy");
+//
+// //Add user key to hashmap.
+// User user = this.loadedUsers.computeIfAbsent(uid, k -> {
+// User u = new User(k);
+// Bungee.getInstance().getLogger().info("Successfully cached user " + u.getUUID());
+// return u;
+// });
+//
+// //Set ranks and other miscellaneous data.
+// user.setUserRank(map.get(uid));
+// user.setSocialSpy(socialSpy);
+// user.setUsername(username);
+// }
+// }
+// } catch (SQLException e) {
+// e.printStackTrace();
+// }
+// }
+
+// ResultSet rs = Bungee.getSQL().query("SELECT authyId,lastIPAddress FROM Authy WHERE uuid='" + uuid.toString() + "' LIMIT 1;");
+// Optional user = getLoadedUser(uuid);
+// if (!user.isPresent()) {
+// rs.close();
+// return;
+// }
+//
+// int authyId = 0;
+// String ipAddress = "0";
+// if (rs.next()) {
+// authyId = rs.getInt("authyId");
+// ipAddress = rs.getString("lastIPAddress");
+// }
+// user.get().setAuthyId(authyId);
+// user.get().setLastIPAddress(ipAddress);
+// rs.close();
+// } catch (SQLException exception) {
+// exception.printStackTrace();
+// }
+ });
+ }
+
+ private void step1(Connection connection, Callback> callback) {
+ try (PreparedStatement statement = connection.prepareStatement("SELECT HEX(uuid) AS uid,rank FROM `user_profile` WHERE rank IN ('builder', 'helpop', 'mod', 'srmod', 'admin', 'dev', 'manager', 'owner');")) {
+ try (ResultSet result = statement.executeQuery()) {
+ HashMap map = Maps.newHashMap();
+ while (result.next()) {
+ UUID u = UUIDUtil.createUUID(result.getString("uid")).orElse(null);
+ if (u == null) continue;
+ map.put(u, UserRank.getUserRank(result.getString("rank")));
+ }
+
+ callback.call(map);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void step2(Connection connection, HashMap map) {
+ UUID uuid;
+ for (UUID uid : map.keySet()) {
+ uuid = uid;
+ try (PreparedStatement statement2 = connection.prepareStatement("SELECT lastname,socialSpy FROM `users` WHERE `uuid`=?;")) {
+ statement2.setString(1, uid.toString());
+ try (ResultSet result2 = statement2.executeQuery()) {
+ if (result2.next()) {
+ String username = result2.getString("lastname");
+ boolean socialSpy = result2.getBoolean("socialSpy");
+
+ //Add user key to hashmap.
+ User user = this.loadedUsers.computeIfAbsent(uid, k -> {
+ User u = new User(k);
+ Bungee.getInstance().getLogger().info("Successfully cached user " + u.getUUID());
+ return u;
+ });
+
+ //Set ranks and other miscellaneous data.
+ user.setUserRank(map.get(uid));
+ user.setSocialSpy(socialSpy);
+ user.setUsername(username);
+ }
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ this.step3(connection, uuid);
+ }
+ }
+
+ private void step3(Connection connection, UUID uuid) {
+ try (PreparedStatement statement2 = connection.prepareStatement("SELECT authyId,lastIPAddress FROM Authy WHERE uuid='" + uuid.toString() + "' LIMIT 1;")) {
+ try (ResultSet result = statement2.executeQuery()) {
+ Optional user = getLoadedUser(uuid);
+ if (!user.isPresent()) {
+ result.close();
+ return;
+ }
+
+ int authyId = 0;
+ String ipAddress = "0";
+ if (result.next()) {
+ authyId = result.getInt("authyId");
+ ipAddress = result.getString("lastIPAddress");
+ }
+ user.get().setAuthyId(authyId);
+ user.get().setLastIPAddress(ipAddress);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void setPerms() {
+ for (ProxiedPlayer player : ProxyServer.getInstance().getPlayers()) {
+ this.getLoadedUser(player.getUniqueId()).ifPresent(user -> this.setPerms(player, user.getUserRank()));
+ }
+ }
+
+ public void setPerms(ProxiedPlayer player, UserRank rank) {
+ if (rank == null) return;
+ for (String perm : new ArrayList<>(player.getPermissions()))
+ player.setPermission(perm, false);
+
+ for (String perm : this.getPermsAndLower(rank))
+ player.setPermission(perm, true);
+ }
+
+ private List getPermsAndLower(UserRank rank) {
+ List perms = new ArrayList<>();
+ if (rank != null)
+ for (UserRank r : UserRank.values()) {
+ List l = this.perms.get(r);
+ if (l != null && !l.isEmpty())
+ perms.addAll(l);
+ if (r == rank) break;
+ }
+ return perms;
+ }
+
+ public Map getLoadedUsersMap() {
+ return loadedUsers;
+ }
+
+ public Collection getLoadedUsers() {
+ return this.loadedUsers.values();
+ }
+
+ public List getSortedUsers() {
+ Collection users = Bungee.getUserManager().getLoadedUsers();
+ List userList = new ArrayList<>();
+ for (UserRank userRank : UserRank.values()) {
+ userList.addAll(users.stream().filter(user -> user.getUserRank() == userRank).collect(Collectors.toList()));
+ }
+ return userList;
+ }
+
+ /**
+ * Get the User object of the player with the specified UUID.
+ *
+ * @param uuid
+ * @return
+ */
+ public Optional getLoadedUser(UUID uuid) {
+ if (uuid == null) return null;
+ return Optional.ofNullable(this.loadedUsers.get(uuid));
+ }
+
+ /**
+ * Get the User object of the player with the specified username.
+ *
+ * @param username
+ * @return
+ */
+ public Optional getLoadedUser(String username) {
+ if (username == null) return null;
+ List users = new ArrayList<>();
+ this.loadedUsers.forEach((uuid, user) -> {
+ if (user.getUsername().equalsIgnoreCase(username)) {
+ users.add(user);
+ return;
+ }
+ });
+ return users.isEmpty() ? Optional.empty() : Optional.of(users.get(0));
+ }
+}
diff --git a/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/users/UserRank.java b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/users/UserRank.java
new file mode 100644
index 0000000..2b19d65
--- /dev/null
+++ b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/users/UserRank.java
@@ -0,0 +1,99 @@
+package net.grandtheftmc.Bungee.users;
+
+import net.grandtheftmc.Bungee.Utils;
+import net.md_5.bungee.api.ChatColor;
+
+import java.util.Objects;
+
+public enum UserRank {
+
+ DEFAULT("&8"), VIP("&6"), PREMIUM("&a"), ELITE("&b"), SPONSOR("&5"), SUPREME("&c"),
+ YOUTUBER("&r"), HELPOP("&d"), MOD("&9"), SRMOD("&9"), BUILDER("&f"), ADMIN("&c"),
+ DEV("&9"), MANAGER("&4"), OWNER("&4");
+
+ private final String color;
+
+ UserRank(String color) {
+ this.color = color;
+ }
+
+ public static UserRank[] getUserRanks() {
+ return UserRank.class.getEnumConstants();
+ }
+
+ public static UserRank getUserRank(String name) {
+ if (name == null) return UserRank.DEFAULT;
+ for (UserRank ur : getUserRanks())
+ if (ur.getName().equalsIgnoreCase(name))
+ return ur;
+ return UserRank.DEFAULT;
+ }
+
+ public static UserRank getUserRankOrNull(String name) {
+ if (name == null)
+ return null;
+ for (UserRank ur : getUserRanks())
+ if (ur.getName().equalsIgnoreCase(name))
+ return ur;
+ return null;
+ }
+
+ public static UserRank getUserRankExact(String name) {
+ if (name == null)
+ return null;
+ for (UserRank ur : getUserRanks())
+ if (ur.getName().equalsIgnoreCase(name))
+ return ur;
+ return null;
+ }
+
+ public static UserRank[] getDonorRanks() {
+ return new UserRank[] { VIP, PREMIUM, ELITE, SPONSOR, SUPREME };
+ }
+
+ public String getName() {
+ return this.toString();
+ }
+
+ public String getColor() {
+ return Utils.f(this.isHigherThan(UserRank.YOUTUBER) ? this.color + ChatColor.BOLD : this.color);
+ }
+
+ public String getColoredName() {
+ return Utils.f(this == UserRank.YOUTUBER ? "&rYOU&4TUBER" : this.color + this.getName());
+ }
+
+ public String getColoredNameBold() {
+ return Utils.f(this == UserRank.YOUTUBER ? "&r&lYOU&4&lTUBER" : this.color + "&l" + this.getName());
+ }
+
+ public String getTabPrefix() {
+ return Utils.f(this == UserRank.YOUTUBER ? "&r&lY&4&lT" : this.color + "&l" + this.getName());
+ }
+
+ public String getPrefix() {
+ if (!Objects.equals(this.getName(), "DEFAULT"))
+ return Utils.f(' ' + this.getColoredNameBold() + "&8&l>");
+ return "";
+ }
+
+ public UserRank getNext() {
+ boolean picknext = false;
+ for (UserRank u : getUserRanks()) {
+ if (picknext)
+ return u;
+ if (Objects.equals(u.getName(), this.getName()))
+ picknext = true;
+ }
+ return UserRank.DEFAULT;
+ }
+
+ public boolean isHigherThan(UserRank rank) {
+ for (UserRank r : getUserRanks())
+ if (r == this)
+ return false;
+ else if (r == rank)
+ return true;
+ return false;
+ }
+}
diff --git a/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/Callback.java b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/Callback.java
new file mode 100644
index 0000000..0bb6932
--- /dev/null
+++ b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/Callback.java
@@ -0,0 +1,5 @@
+package net.grandtheftmc.Bungee.utils;
+
+public interface Callback {
+ void call(T obj);
+}
diff --git a/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/DefaultFontInfo.java b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/DefaultFontInfo.java
new file mode 100644
index 0000000..1e47c5a
--- /dev/null
+++ b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/DefaultFontInfo.java
@@ -0,0 +1,133 @@
+package net.grandtheftmc.Bungee.utils;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+/**
+ * Created by Adam on 05/06/2017.
+ */
+public enum DefaultFontInfo {
+
+ A_UPPER('A', 5),
+ A_LOWER('a', 5),
+ B_UPPER('B', 5),
+ B_LOWER('b', 5),
+ C_UPPER('C', 5),
+ C_LOWER('c', 5),
+ D_UPPER('D', 5),
+ D_LOWER('d', 5),
+ E_UPPER('E', 5),
+ E_LOWER('e', 5),
+ F_UPPER('F', 5),
+ F_LOWER('f', 4),
+ G_UPPER('G', 5),
+ G_LOWER('g', 5),
+ H_UPPER('H', 5),
+ H_LOWER('h', 5),
+ I_UPPER('I', 3),
+ I_LOWER('i', 1),
+ J_UPPER('J', 5),
+ J_LOWER('j', 5),
+ K_UPPER('K', 5),
+ K_LOWER('k', 4),
+ L_UPPER('L', 5),
+ L_LOWER('l', 1),
+ M_UPPER('M', 5),
+ M_LOWER('m', 5),
+ N_UPPER('N', 5),
+ N_LOWER('n', 5),
+ O_UPPER('O', 5),
+ O_LOWER('o', 5),
+ P_UPPER('P', 5),
+ P_LOWER('p', 5),
+ Q_UPPER('Q', 5),
+ Q_LOWER('q', 5),
+ R_UPPER('R', 5),
+ R_LOWER('r', 5),
+ S_UPPER('S', 5),
+ S_LOWER('s', 5),
+ T_UPPER('T', 5),
+ T_LOWER('t', 4),
+ U_UPPER('U', 5),
+ U_LOWER('u', 5),
+ V_UPPER('V', 5),
+ V_LOWER('v', 5),
+ W_UPPER('W', 5),
+ W_LOWER('w', 5),
+ X_UPPER('X', 5),
+ X_LOWER('x', 5),
+ Y_UPPER('Y', 5),
+ Y_LOWER('y', 5),
+ Z_UPPER('Z', 5),
+ Z_LOWER('z', 5),
+ NUM_1('1', 5),
+ NUM_2('2', 5),
+ NUM_3('3', 5),
+ NUM_4('4', 5),
+ NUM_5('5', 5),
+ NUM_6('6', 5),
+ NUM_7('7', 5),
+ NUM_8('8', 5),
+ NUM_9('9', 5),
+ NUM_0('0', 5),
+ EXCLAMATION_POINT('!', 1),
+ AT_SYMBOL('@', 6),
+ NUM_SIGN('#', 5),
+ DOLLAR_SIGN('$', 5),
+ PERCENT('%', 5),
+ UP_ARROW('^', 5),
+ AMPERSAND('&', 5),
+ ASTERISK('*', 5),
+ LEFT_PARENTHESIS('(', 4),
+ RIGHT_PERENTHESIS(')', 4),
+ MINUS('-', 5),
+ UNDERSCORE('_', 5),
+ PLUS_SIGN('+', 5),
+ EQUALS_SIGN('=', 5),
+ LEFT_CURL_BRACE('{', 4),
+ RIGHT_CURL_BRACE('}', 4),
+ LEFT_BRACKET('[', 3),
+ RIGHT_BRACKET(']', 3),
+ COLON(':', 1),
+ SEMI_COLON(';', 1),
+ DOUBLE_QUOTE('"', 3),
+ SINGLE_QUOTE('\'', 1),
+ LEFT_ARROW('<', 4),
+ RIGHT_ARROW('>', 4),
+ QUESTION_MARK('?', 5),
+ SLASH('/', 5),
+ BACK_SLASH('\\', 5),
+ LINE('|', 1),
+ TILDE('~', 5),
+ TICK('`', 2),
+ PERIOD('.', 1),
+ COMMA(',', 1),
+ SPACE(' ', 3),
+ DEFAULT('a', 4);
+
+ private final char character;
+ private final int length;
+
+ DefaultFontInfo(char character, int length) {
+ this.character = character;
+ this.length = length;
+ }
+
+ public char getCharacter() {
+ return this.character;
+ }
+
+ public int getLength() {
+ return this.length;
+ }
+
+ public int getBoldLength() {
+ if (this == SPACE) return this.length;
+ return this.length + 1;
+ }
+
+ public static DefaultFontInfo getDefaultFontInfo(char c) {
+ Optional defaultFontInfo = Arrays.stream(values()).filter(d -> d.character == c).findFirst();
+ return defaultFontInfo.orElse(DEFAULT);
+ }
+}
diff --git a/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/HelpLog.java b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/HelpLog.java
new file mode 100644
index 0000000..88f08d0
--- /dev/null
+++ b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/HelpLog.java
@@ -0,0 +1,57 @@
+package net.grandtheftmc.Bungee.utils;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Created by Adam on 03/06/2017.
+ */
+public class HelpLog {
+
+ //A list of users who have requested help.
+ private static Map helpReqs = new HashMap<>();
+
+ //1 Minutes timeout for receiving tokens.
+ private static final int HELP_TOKENS_TIMEOUT = 1000 * 60 * 1;
+
+ /**
+ * Invoked from RedisListener when a player requests help and this gets forwarded to the staff chat.
+ *
+ * @param name
+ */
+ public static void requestHelp(String name) {
+ helpReqs.put(name.toLowerCase(), System.currentTimeMillis());
+ }
+
+ /**
+ * Invoked whenever a staff member messages a player who requested help.
+ *
+ * @param name The name of the player the staff member has gmsg'ed.
+ * @return True if they should receive tokens. Let's set a 15 minute timeout on help requests in order to receive tokens.
+ */
+ public static boolean closeHelpTicket(String name) {
+ name = name.toLowerCase();
+ if (helpReqs.containsKey(name)) {
+ long t = helpReqs.remove(name);
+ long msElapsed = System.currentTimeMillis() - t;
+ return msElapsed <= HELP_TOKENS_TIMEOUT;
+ }
+
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * Check whether the target of gmsg has an open help ticket.
+ *
+ * @param name
+ * @return
+ */
+ public static boolean helpTicketExists(String name) {
+ return name != null && helpReqs.containsKey(name.toLowerCase());
+ }
+
+}
diff --git a/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/PlaytimeManager.java b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/PlaytimeManager.java
new file mode 100644
index 0000000..40ee3ae
--- /dev/null
+++ b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/PlaytimeManager.java
@@ -0,0 +1,116 @@
+package net.grandtheftmc.Bungee.utils;
+
+import net.grandtheftmc.Bungee.Bungee;
+import net.grandtheftmc.Bungee.Utils;
+import net.grandtheftmc.Bungee.database.BaseDatabase;
+import net.grandtheftmc.Bungee.users.User;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+
+public class PlaytimeManager {
+
+ //How many days to store session history for.
+ private static final int sessionHistoryDays = 7;
+ private static final String tableName = "playtime";
+ //Map UUID -> Millis() At connect time to track session time.
+ private static Map sessions = new HashMap<>();
+
+ /**
+ * Mark the beginning of a playtime session for the connecting player.
+ *
+ * @param uuid The player whose playtime we wish to track.
+ */
+ public static void beginSession(String uuid) {
+ sessions.put(UUID.fromString(uuid), System.currentTimeMillis());
+ }
+
+ /**
+ * End the playtime session, and store the result in the database.
+ *
+ * @param proxiedPlayer The player whose playtime we wish to track.
+ */
+ public static void endSession(ProxiedPlayer proxiedPlayer) {
+ if (sessions.containsKey(proxiedPlayer.getUniqueId())) {
+ long now = System.currentTimeMillis();
+ long elapsed = now - sessions.remove(proxiedPlayer.getUniqueId());
+
+ Bungee.getInstance().getProxy().getScheduler().runAsync(Bungee.getInstance(), () -> {
+
+ try (Connection connection = BaseDatabase.getInstance().getConnection()) {
+ String query = "INSERT INTO " + tableName + " (lastname,uuid,sessiontime,sessiondate) VALUES (?, ?, ?, ?);";
+ try (PreparedStatement statement = connection.prepareStatement(query)) {
+ statement.setString(1, proxiedPlayer.getName());
+ statement.setString(2, proxiedPlayer.getUniqueId().toString());
+ statement.setLong(3, elapsed);
+ statement.setLong(4, now);
+ statement.executeUpdate();
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+ }
+
+ /**
+ * This function will delete any rows in the DB with session dates older than a week.
+ * Call this every 24hr and on startup.
+ */
+ public static void purgeOldSessions() {
+ Bungee.getInstance().getProxy().getScheduler().runAsync(Bungee.getInstance(), () -> {
+ long threshold = System.currentTimeMillis() - (1000 * 60 * 60 * 24 * sessionHistoryDays);
+
+ try (Connection connection = BaseDatabase.getInstance().getConnection()) {
+ try (PreparedStatement statement = connection.prepareStatement("DELETE FROM " + tableName + " WHERE sessionDate<=" + threshold)) {
+ statement.executeUpdate();
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+
+ /**
+ * Query the playtime of another user.
+ *
+ * @param p The player issuing the command.
+ * @param target The name of the user to lookup.
+ */
+ public static void lookupPlaytime(ProxiedPlayer p, String target) {
+ Bungee.getInstance().getProxy().getScheduler().runAsync(Bungee.getInstance(), () -> {
+
+ long threshold = System.currentTimeMillis() - (1000 * 60 * 60 * 24 * sessionHistoryDays);
+ long totalTime = 0;
+
+ try (Connection connection = BaseDatabase.getInstance().getConnection()) {
+ try (PreparedStatement statement = connection.prepareStatement("SELECT lastname,sessiontime,sessiondate FROM " + tableName + " WHERE lastname='" + target + "' AND sessiondate>" + threshold + ";")) {
+ try (ResultSet result = statement.executeQuery()) {
+ if (result.isBeforeFirst()) {
+ while (result.next()) {
+ totalTime += result.getLong("sessiontime");
+ }
+
+ Optional userOptional = Bungee.getUserManager().getLoadedUser(target);
+ if (!userOptional.isPresent()) return;
+
+ String s = Utils.formatPlaytime(totalTime);
+ p.sendMessage(Utils.f(userOptional.get().getColoredName() + " &7has played for &a" + s + " &7in the last week."));
+ } else {
+ p.sendMessage(Utils.f("&cThe player " + target + " either doesn't exist, or hasn't played in the last week."));
+ }
+ }
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+}
diff --git a/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/RequestRateLimiter.java b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/RequestRateLimiter.java
new file mode 100644
index 0000000..8a773ca
--- /dev/null
+++ b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/RequestRateLimiter.java
@@ -0,0 +1,48 @@
+package net.grandtheftmc.Bungee.utils;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * Created by Adam on 05/06/2017.
+ */
+public class RequestRateLimiter {
+
+ /*
+ This class serves to limit requests made by staff members to the database.
+
+ No more than 1 execution every second.
+
+ Still allows frequent use, but without spamming.
+
+ Only applies to the /seen, /alt commands
+ */
+
+ //Store the issuing player and the time of the last command
+ private static Map lastReq = new HashMap<>();
+
+ /**
+ * Attempt to make a request to execute a database related command.
+ * @param u The UUID of the player executing the command.
+ * @return A boolean representing whether they have been granted use of said command or not.
+ */
+ public static boolean requestCmd(UUID u) {
+ long t = System.currentTimeMillis();
+
+ if (!lastReq.containsKey(u)) {
+ lastReq.put(u, t);
+ return true;
+ }
+
+ long last = lastReq.get(u);
+ if (t - last >= 1000) {
+ //if at least 1 second has passed allow the command.
+ lastReq.put(u, t);
+ return true;
+ }
+
+ return false;
+ }
+
+}
diff --git a/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/ServerStatus.java b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/ServerStatus.java
new file mode 100644
index 0000000..2c34fd1
--- /dev/null
+++ b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/ServerStatus.java
@@ -0,0 +1,45 @@
+package net.grandtheftmc.Bungee.utils;
+
+import io.netty.util.internal.ConcurrentSet;
+import net.md_5.bungee.api.Callback;
+import net.md_5.bungee.api.ServerPing;
+import net.md_5.bungee.api.config.ServerInfo;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class ServerStatus implements Callback {
+ private static final ConcurrentSet serverStatuses = new ConcurrentSet<>();
+ private final ServerInfo serverInfo;
+ private boolean online;
+
+
+ public ServerStatus(ServerInfo serverInfo) {
+ this.serverInfo = serverInfo;
+ serverStatuses.add(this);
+ }
+
+ public static ServerStatus getServerStatus(ServerInfo serverInfo) {
+ Set tempStatuses = new HashSet<>(serverStatuses);
+ return tempStatuses.stream()
+ .filter(serverStatus -> serverStatus.getServerInfo() == serverInfo)
+ .findFirst().orElse(new ServerStatus(serverInfo));
+ }
+
+ @Override
+ public void done(ServerPing serverPing, Throwable throwable) {
+ this.online = throwable == null;
+ }
+
+ public void updateStatus() {
+ this.serverInfo.ping(this);
+ }
+
+ public boolean isOnline() {
+ return this.online;
+ }
+
+ public ServerInfo getServerInfo() {
+ return this.serverInfo;
+ }
+}
diff --git a/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/TabComplete.java b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/TabComplete.java
new file mode 100644
index 0000000..478e507
--- /dev/null
+++ b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/TabComplete.java
@@ -0,0 +1,40 @@
+package net.grandtheftmc.Bungee.utils;
+
+import com.google.common.collect.ImmutableSet;
+import net.grandtheftmc.Bungee.Bungee;
+import net.md_5.bungee.api.CommandSender;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Created by Adam on 02/06/2017.
+ */
+public class TabComplete {
+
+ /**
+ * Match a list of players to a search string accross the Redis network.
+ * @param sender Who executed the command.
+ * @param args Arguments of player to search
+ * @return A Set of potential matches.
+ */
+ public static Set onTabComplete(CommandSender sender, String[] args){
+ if (args.length > 2 || args.length == 0)
+ return ImmutableSet.of();
+
+ Set matches = new HashSet<>();
+
+ if (args.length == 1) {
+ String search = args[0].toLowerCase();
+
+ //We search all redis online players for the autocomplete
+ for (String name : Bungee.getRedisManager().getRedisAPI().getHumanPlayersOnline()) {
+ if (name.toLowerCase().startsWith(search)) {
+ matches.add(name);
+ }
+ }
+ }
+
+ return matches;
+ }
+}
diff --git a/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/TimeFormatter.java b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/TimeFormatter.java
new file mode 100644
index 0000000..5373564
--- /dev/null
+++ b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/TimeFormatter.java
@@ -0,0 +1,45 @@
+package net.grandtheftmc.Bungee.utils;
+
+import java.util.concurrent.TimeUnit;
+
+public class TimeFormatter {
+ private final TimeUnit timeUnit;
+ private Long time;
+
+ public TimeFormatter(TimeUnit timeUnit, Long time) {
+ this.timeUnit = timeUnit;
+ this.time = time;
+ }
+
+ public Long getTime() {
+ return new Long(this.time);
+ }
+
+ public void setTime(Long time) {
+ this.time = time;
+ }
+
+ public TimeUnit getTimeUnit() {
+ return this.timeUnit;
+ }
+
+ public Long getSeconds() {
+ return this.timeUnit.toSeconds(this.time) - (this.timeUnit.toMinutes(this.time) * 60);
+ }
+
+ public Long getMinutes() {
+ return this.timeUnit.toMinutes(this.time) - (this.timeUnit.toHours(this.time) * 60);
+ }
+
+ public Long getHours() {
+ return this.timeUnit.toHours(this.time) - (this.timeUnit.toDays(this.time) * 24);
+ }
+
+ public Long getDays() {
+ return this.timeUnit.toDays(this.time);
+ }
+
+ public Long getMillis() {
+ return this.timeUnit.toMillis(this.time);
+ }
+}
\ No newline at end of file
diff --git a/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/UUIDUtil.java b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/UUIDUtil.java
new file mode 100644
index 0000000..caccfc8
--- /dev/null
+++ b/bungee-master@696956eaecd/src/main/java/net/grandtheftmc/Bungee/utils/UUIDUtil.java
@@ -0,0 +1,69 @@
+package net.grandtheftmc.Bungee.utils;
+
+import java.util.Optional;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Created by Stephen
+ */
+public class UUIDUtil {
+
+ /**
+ * A {@link Pattern} used to identify and/or split full UUIDs
+ */
+ private static final Pattern PATTERN_UUID = Pattern.compile("^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$", Pattern.CASE_INSENSITIVE);
+ /**
+ * A {@link Pattern} used to identify and/or split trimmed UUIDs
+ */
+ private static final Pattern PATTERN_TRIMMED_UUID = Pattern.compile("^([a-z0-9]{8})([a-z0-9]{4})([a-z0-9]{4})([a-z0-9]{4})([a-z0-9]{12})$", Pattern.CASE_INSENSITIVE);
+
+
+ /**
+ * Create a UUID safely from a {@link String}.
+ *
+ * @param string The {@link String} to deserialize into an {@link UUID} object.
+ * @return {@link Optional#empty()} if the provided {@link String} is illegal, otherwise an {@link Optional}
+ * containing the deserialized {@link UUID} object.
+ */
+ public static Optional createUUID(String string) {
+ if (string == null) {
+ return Optional.empty();
+ }
+
+ UUID result = null;
+
+ try {
+ // Is it a valid UUID?
+ if (!PATTERN_UUID.matcher(string).matches()) {
+ // Un-trim UUID if it is trimmed
+ Matcher matcher = PATTERN_TRIMMED_UUID.matcher(string);
+ if (matcher.matches()) {
+ StringBuilder sb = new StringBuilder();
+
+ for (int i = 1; i <= matcher.groupCount(); i++) {
+ if (i != 1) {
+ sb.append("-");
+ }
+
+ sb.append(matcher.group(i));
+ }
+
+ string = sb.toString();
+ } else {
+ // Invalid UUID
+ string = null;
+ }
+ }
+
+ if (string != null) {
+ result = UUID.fromString(string);
+ }
+ } catch (IllegalArgumentException ignored) {
+ // Useless data passed
+ }
+
+ return Optional.ofNullable(result);
+ }
+}
diff --git a/bungee-master@696956eaecd/src/main/resources/plugin.yml b/bungee-master@696956eaecd/src/main/resources/plugin.yml
new file mode 100644
index 0000000..e25eb50
--- /dev/null
+++ b/bungee-master@696956eaecd/src/main/resources/plugin.yml
@@ -0,0 +1,4 @@
+name: Bungee
+main: net.grandtheftmc.Bungee.Bungee
+version: 1.3
+author: GTMDevs
diff --git a/cartels-master@e4f5c2ecec5/.gitignore b/cartels-master@e4f5c2ecec5/.gitignore
new file mode 100644
index 0000000..ad7f541
--- /dev/null
+++ b/cartels-master@e4f5c2ecec5/.gitignore
@@ -0,0 +1,8 @@
+
+\.idea/
+
+target/classes/
+
+target/
+
+*.iml
\ No newline at end of file
diff --git a/cartels-master@e4f5c2ecec5/README.md b/cartels-master@e4f5c2ecec5/README.md
new file mode 100644
index 0000000..fdaec0e
--- /dev/null
+++ b/cartels-master@e4f5c2ecec5/README.md
@@ -0,0 +1 @@
+First commit.
\ No newline at end of file
diff --git a/cartels-master@e4f5c2ecec5/licenses/LGPL.txt b/cartels-master@e4f5c2ecec5/licenses/LGPL.txt
new file mode 100644
index 0000000..65c5ca8
--- /dev/null
+++ b/cartels-master@e4f5c2ecec5/licenses/LGPL.txt
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/cartels-master@e4f5c2ecec5/licenses/LICENCE.txt b/cartels-master@e4f5c2ecec5/licenses/LICENCE.txt
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/cartels-master@e4f5c2ecec5/licenses/LICENCE.txt
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+ .
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/cartels-master@e4f5c2ecec5/licenses/gson-license.txt b/cartels-master@e4f5c2ecec5/licenses/gson-license.txt
new file mode 100644
index 0000000..634d1aa
--- /dev/null
+++ b/cartels-master@e4f5c2ecec5/licenses/gson-license.txt
@@ -0,0 +1,13 @@
+Copyright (c) 2008-2009 Google Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/cartels-master@e4f5c2ecec5/pom.xml b/cartels-master@e4f5c2ecec5/pom.xml
new file mode 100644
index 0000000..b48e75f
--- /dev/null
+++ b/cartels-master@e4f5c2ecec5/pom.xml
@@ -0,0 +1,384 @@
+
+ 4.0.0
+
+ com.massivecraft
+ Cartels
+ 1.7.1
+ jar
+ Cartels
+
+
+
+ vault-repo
+ http://nexus.hc.to/content/repositories/pub_releases
+
+
+ ess-repo
+ http://repo.ess3.net/content/groups/essentials
+
+
+ spigot-repo
+ https://hub.spigotmc.org/nexus/content/groups/public/
+
+
+ maven.sk89q.com
+ http://maven.sk89q.com/repo/
+
+
+ repo.mikeprimm.com
+ http://repo.mikeprimm.com/
+
+
+ playervaults
+ https://ci.drtshock.net/plugin/repository
+
+
+ dmulloy2-repo
+ http://repo.dmulloy2.net/nexus/repository/public/
+
+
+ nexus-release
+ https://nexus.grandtheftmc.net/content/repositories/releases/
+
+
+
+
+
+ nexus-release
+ Internal Releases
+ https://nexus.grandtheftmc.net/content/repositories/releases/
+
+
+ nexus-snapshot
+ Internal Snapshots
+ https://nexus.grandtheftmc.net/content/repositories/snapshots/
+
+
+
+
+ UTF-8
+
+
+
+
+ org.spigotmc
+ spigot-api
+ 1.12-R0.1-SNAPSHOT
+ provided
+
+
+ bungeecord-chat
+ net.md-5
+
+
+ persistence-api
+ javax.persistence
+
+
+ junit
+ junit
+
+
+ guava
+ com.google.guava
+
+
+ gson
+ com.google.code.gson
+
+
+
+
+ net.milkbowl.vault
+ VaultAPI
+ 1.6
+ provided
+
+
+ bukkit
+ org.bukkit
+
+
+
+
+ com.sk89q
+ worldguard
+ 6.1.1-SNAPSHOT
+ provided
+
+
+ bukkit
+ org.bukkit
+
+
+ bukkit-classloader-check
+ com.sk89q.spigot
+
+
+ commandbook
+ com.sk89q
+
+
+ jsr305
+ com.google.code.findbugs
+
+
+ js
+ rhino
+
+
+ truezip
+ de.schlichtherle
+
+
+ jchronic
+ com.sk89q
+
+
+ worldedit
+ com.sk89q
+
+
+
+
+ com.sk89q.worldedit
+ worldedit-bukkit
+ 6.1.1-SNAPSHOT
+ provided
+
+
+ bukkit
+ org.bukkit
+
+
+ jsr305
+ com.google.code.findbugs
+
+
+ bukkit-classloader-check
+ org.sk89q.bukkit
+
+
+ dummypermscompat
+ com.sk89q
+
+
+ jchronic
+ com.sk89q
+
+
+ js
+ rhino
+
+
+ truezip
+ de.schlichtherle
+
+
+ jlibnoise
+ com.sk89q.lib
+
+
+ paranamer
+ com.thoughtworks.paranamer
+
+
+ guava
+ com.google.guava
+
+
+ gson
+ com.google.code.gson
+
+
+ snakeyaml
+ org.yaml
+
+
+
+
+ com.google.guava
+ guava
+ 10.0.1
+ provided
+
+
+ jsr305
+ com.google.code.findbugs
+
+
+
+
+ net.ess3
+ Essentials
+ 2.13-SNAPSHOT
+ provided
+
+
+ net.ess3
+ EssentialsChat
+ 2.13-SNAPSHOT
+ provided
+
+
+ bukkit
+ org.bukkit
+
+
+ lombok
+ org.projectlombok
+
+
+ Essentials
+ net.ess3
+
+
+
+
+ mkremins
+ fanciful
+ 0.4.0
+ compile
+
+
+ gson
+ com.google.code.gson
+
+
+
+
+ org.dynmap
+ dynmap
+ 2.0
+ provided
+
+
+ bukkit
+ org.bukkit
+
+
+ Permissions
+ com.nijikokun.bukkit
+
+
+ bPermissions
+ de.bananaco
+
+
+ EssentialsGroupManager
+ org.anjocaido
+
+
+ spoutpluginapi
+ org.getspout
+
+
+ PermissionsBukkit
+ com.platymuus.bukkit.permissions
+
+
+ PermissionsEx
+ ru.tehkode
+
+
+
+
+ com.google.code.gson
+ gson
+ 2.6.2
+ compile
+
+
+
+ net.grandtheftmc
+ core
+ 1.0.5
+ provided
+
+
+ net.grandtheftmc
+ vice
+ 1.0.2
+ provided
+
+
+
+
+ clean package install
+ ${project.name}
+ src/main/java
+
+
+ true
+ src/main/resources/
+
+
+
+
+ maven-compiler-plugin
+ 3.5.1
+
+
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 2.4.3
+
+ false
+
+
+
+ mkremins.fanciful
+ com.massivecraft.factions.shade.mkremins.fanciful
+
+
+ com.google.gson
+ com.massivecraft.factions.shade.com.google.gson
+
+
+
+
+
+ package
+
+ shade
+
+
+
+
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.8
+ true
+
+
+ default-deploy
+ deploy
+
+ deploy
+
+
+
+
+ nexus
+ https://nexus.grandtheftmc.net/
+ true
+
+
+
+
+
diff --git a/cartels-master@e4f5c2ecec5/src/main/assembly/package.xml b/cartels-master@e4f5c2ecec5/src/main/assembly/package.xml
new file mode 100644
index 0000000..8f3491c
--- /dev/null
+++ b/cartels-master@e4f5c2ecec5/src/main/assembly/package.xml
@@ -0,0 +1,16 @@
+
+ bin
+ false
+
+ zip
+
+
+
+
+ /
+ ${artifactId}.jar
+
+
+
\ No newline at end of file
diff --git a/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/Board.java b/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/Board.java
new file mode 100644
index 0000000..98b25be
--- /dev/null
+++ b/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/Board.java
@@ -0,0 +1,86 @@
+package com.massivecraft.factions;
+
+import com.massivecraft.factions.zcore.persist.json.JSONBoard;
+
+import java.util.ArrayList;
+import java.util.Set;
+
+
+public abstract class Board {
+ protected static Board instance = getBoardImpl();
+
+ //----------------------------------------------//
+ // Get and Set
+ //----------------------------------------------//
+ public abstract String getIdAt(FLocation flocation);
+
+ private static Board getBoardImpl() {
+ switch (Conf.backEnd) {
+ case JSON:
+ return new JSONBoard();
+ }
+ return null;
+ }
+
+ public static Board getInstance() {
+ return instance;
+ }
+
+ public abstract Faction getFactionAt(FLocation flocation);
+
+ public abstract void setIdAt(String id, FLocation flocation);
+
+ public abstract void setFactionAt(Faction faction, FLocation flocation);
+
+ public abstract void removeAt(FLocation flocation);
+
+ public abstract Set getAllClaims(String factionId);
+
+ public abstract Set getAllClaims(Faction faction);
+
+ // anot to be confused with claims, ownership referring to further member-specific ownership of a claim
+ public abstract void clearOwnershipAt(FLocation flocation);
+
+ public abstract void unclaimAll(String factionId);
+
+ // Is this coord NOT completely surrounded by coords claimed by the same faction?
+ // Simpler: Is there any nearby coord with a faction other than the faction here?
+ public abstract boolean isBorderLocation(FLocation flocation);
+
+ // Is this coord connected to any coord claimed by the specified faction?
+ public abstract boolean isConnectedLocation(FLocation flocation, Faction faction);
+
+ public abstract boolean hasFactionWithin(FLocation flocation, Faction faction, int radius);
+
+ //----------------------------------------------//
+ // Cleaner. Remove orphaned foreign keys
+ //----------------------------------------------//
+
+ public abstract void clean();
+
+ //----------------------------------------------//
+ // Coord count
+ //----------------------------------------------//
+
+ public abstract int getFactionCoordCount(String factionId);
+
+ public abstract int getFactionCoordCount(Faction faction);
+
+ public abstract int getFactionCoordCountInWorld(Faction faction, String worldName);
+
+ //----------------------------------------------//
+ // Map generation
+ //----------------------------------------------//
+
+ /**
+ * The map is relative to a coord and a faction north is in the direction of decreasing x east is in the direction
+ * of decreasing z
+ */
+ public abstract ArrayList getMap(Faction faction, FLocation flocation, double inDegrees);
+
+ public abstract void forceSave();
+
+ public abstract void forceSave(boolean sync);
+
+ public abstract boolean load();
+}
diff --git a/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/Conf.java b/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/Conf.java
new file mode 100644
index 0000000..d166a1e
--- /dev/null
+++ b/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/Conf.java
@@ -0,0 +1,467 @@
+package com.massivecraft.factions;
+
+import com.google.common.collect.ImmutableMap;
+import com.massivecraft.factions.integration.dynmap.DynmapStyle;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.entity.EntityType;
+
+import java.util.*;
+
+public class Conf {
+
+ public static List baseCommandAliases = new ArrayList();
+ public static boolean allowNoSlashCommand = true;
+
+ // Colors
+ public static ChatColor colorMember = ChatColor.GREEN;
+ public static ChatColor colorAlly = ChatColor.LIGHT_PURPLE;
+ public static ChatColor colorTruce = ChatColor.DARK_PURPLE;
+ public static ChatColor colorNeutral = ChatColor.WHITE;
+ public static ChatColor colorEnemy = ChatColor.RED;
+
+ public static ChatColor colorPeaceful = ChatColor.GOLD;
+ public static ChatColor colorWar = ChatColor.DARK_RED;
+
+ // Power
+ public static double powerPlayerMax = 10.0;
+ public static double powerPlayerMin = -10.0;
+ public static double powerPlayerStarting = 0.0;
+ public static double powerPerMinute = 0.2; // Default health rate... it takes 5 min to heal one power
+ public static double powerPerDeath = 4.0; // A death makes you lose 4 power
+ public static boolean powerRegenOffline = false; // does player power regenerate even while they're offline?
+ public static double powerOfflineLossPerDay = 0.0; // players will lose this much power per day offline
+ public static double powerOfflineLossLimit = 0.0; // players will no longer lose power from being offline once their power drops to this amount or less
+ public static double powerFactionMax = 0.0; // if greater than 0, the cap on how much power a faction can have (additional power from players beyond that will act as a "buffer" of sorts)
+
+ public static String prefixAdmin = "[DrugLord] ";//**
+ public static String prefixMod = "[Lieutenant] ";//*
+
+ public static int factionTagLengthMin = 3;
+ public static int factionTagLengthMax = 10;
+ public static boolean factionTagForceUpperCase = false;
+
+ public static boolean newFactionsDefaultOpen = false;
+
+ // when faction membership hits this limit, players will no longer be able to join using /f join; default is 0, no limit
+ public static int factionMemberLimit = 0;
+
+ // what faction ID to start new players in when they first join the server; default is 0, "no faction"
+ public static String newPlayerStartingFactionID = "0";
+
+ public static boolean showMapFactionKey = true;
+ public static boolean showNeutralFactionsOnMap = true;
+ public static boolean showEnemyFactionsOnMap = true;
+
+ // Disallow joining/leaving/kicking while power is negative
+ public static boolean canLeaveWithNegativePower = true;
+
+ // Configuration for faction-only chat
+ public static boolean factionOnlyChat = true;
+ // Configuration on the Faction tag in chat messages.
+ public static boolean chatTagEnabled = true;
+ public static transient boolean chatTagHandledByAnotherPlugin = false;
+ public static boolean chatTagRelationColored = true;
+ public static String chatTagReplaceString = "[CARTEL]";
+ public static String chatTagInsertAfterString = "";
+ public static String chatTagInsertBeforeString = "";
+ public static int chatTagInsertIndex = 0;
+ public static boolean chatTagPadBefore = false;
+ public static boolean chatTagPadAfter = true;
+ public static String chatTagFormat = "%s" + ChatColor.WHITE;
+ public static String factionChatFormat = "%s:" + ChatColor.WHITE + " %s";
+ public static String allianceChatFormat = ChatColor.LIGHT_PURPLE + "%s:" + ChatColor.WHITE + " %s";
+ public static String truceChatFormat = ChatColor.DARK_PURPLE + "%s:" + ChatColor.WHITE + " %s";
+
+ public static boolean broadcastDescriptionChanges = false;
+ public static boolean broadcastTagChanges = false;
+
+ public static double saveToFileEveryXMinutes = 30.0;
+
+ public static double autoLeaveAfterDaysOfInactivity = 10.0;
+ public static double autoLeaveRoutineRunsEveryXMinutes = 5.0;
+ public static int autoLeaveRoutineMaxMillisecondsPerTick = 5; // 1 server tick is roughly 50ms, so default max 10% of a tick
+ public static boolean removePlayerDataWhenBanned = true;
+ public static boolean autoLeaveDeleteFPlayerData = true; // Let them just remove player from Faction.
+
+ public static boolean worldGuardChecking = false;
+ public static boolean worldGuardBuildPriority = false;
+
+ // server logging options
+ public static boolean logFactionCreate = true;
+ public static boolean logFactionDisband = true;
+ public static boolean logFactionJoin = true;
+ public static boolean logFactionKick = true;
+ public static boolean logFactionLeave = true;
+ public static boolean logLandClaims = true;
+ public static boolean logLandUnclaims = true;
+ public static boolean logMoneyTransactions = true;
+ public static boolean logPlayerCommands = true;
+
+ // prevent some potential exploits
+ public static boolean handleExploitObsidianGenerators = true;
+ public static boolean handleExploitEnderPearlClipping = true;
+ public static boolean handleExploitInteractionSpam = true;
+ public static boolean handleExploitTNTWaterlog = false;
+ public static boolean handleExploitLiquidFlow = false;
+
+ public static boolean homesEnabled = true;
+ public static boolean homesMustBeInClaimedTerritory = true;
+ public static boolean homesTeleportToOnDeath = true;
+ public static boolean homesRespawnFromNoPowerLossWorlds = true;
+ public static boolean homesTeleportCommandEnabled = true;
+ public static boolean homesTeleportCommandEssentialsIntegration = true;
+ public static boolean homesTeleportCommandSmokeEffectEnabled = true;
+ public static float homesTeleportCommandSmokeEffectThickness = 3f;
+ public static boolean homesTeleportAllowedFromEnemyTerritory = true;
+ public static boolean homesTeleportAllowedFromDifferentWorld = true;
+ public static double homesTeleportAllowedEnemyDistance = 32.0;
+ public static boolean homesTeleportIgnoreEnemiesIfInOwnTerritory = true;
+
+ public static boolean disablePVPBetweenNeutralFactions = false;
+ public static boolean disablePVPForFactionlessPlayers = false;
+ public static boolean enablePVPAgainstFactionlessInAttackersLand = false;
+
+ public static int noPVPDamageToOthersForXSecondsAfterLogin = 3;
+
+ public static boolean peacefulTerritoryDisablePVP = true;
+ public static boolean peacefulTerritoryDisableMonsters = false;
+ public static boolean peacefulTerritoryDisableBoom = false;
+ public static boolean peacefulMembersDisablePowerLoss = true;
+
+ public static boolean permanentFactionsDisableLeaderPromotion = false;
+
+ public static boolean claimsMustBeConnected = false;
+ public static boolean claimsCanBeUnconnectedIfOwnedByOtherFaction = true;
+ public static int claimsRequireMinFactionMembers = 1;
+ public static int claimedLandsMax = 0;
+ public static int lineClaimLimit = 5;
+
+ // if someone is doing a radius claim and the process fails to claim land this many times in a row, it will exit
+ public static int radiusClaimFailureLimit = 9;
+
+ public static double considerFactionsReallyOfflineAfterXMinutes = 0.0;
+
+ public static int actionDeniedPainAmount = 1;
+
+ // commands which will be prevented if the player is a member of a permanent faction
+ public static Set permanentFactionMemberDenyCommands = new LinkedHashSet();
+
+ // commands which will be prevented when in claimed territory of another faction
+ public static Set territoryNeutralDenyCommands = new LinkedHashSet();
+ public static Set territoryEnemyDenyCommands = new LinkedHashSet();
+ public static Set territoryAllyDenyCommands = new LinkedHashSet();
+ public static Set warzoneDenyCommands = new LinkedHashSet();
+ public static Set wildernessDenyCommands = new LinkedHashSet();
+
+ public static boolean territoryDenyBuild = true;
+ public static boolean territoryDenyBuildWhenOffline = true;
+ public static boolean territoryPainBuild = false;
+ public static boolean territoryPainBuildWhenOffline = false;
+ public static boolean territoryDenyUseage = true;
+ public static boolean territoryEnemyDenyBuild = true;
+ public static boolean territoryEnemyDenyBuildWhenOffline = true;
+ public static boolean territoryEnemyPainBuild = false;
+ public static boolean territoryEnemyPainBuildWhenOffline = false;
+ public static boolean territoryEnemyDenyUseage = true;
+ public static boolean territoryEnemyProtectMaterials = true;
+ public static boolean territoryAllyDenyBuild = true;
+ public static boolean territoryAllyDenyBuildWhenOffline = true;
+ public static boolean territoryAllyPainBuild = false;
+ public static boolean territoryAllyPainBuildWhenOffline = false;
+ public static boolean territoryAllyDenyUseage = true;
+ public static boolean territoryAllyProtectMaterials = true;
+ public static boolean territoryTruceDenyBuild = true;
+ public static boolean territoryTruceDenyBuildWhenOffline = true;
+ public static boolean territoryTrucePainBuild = false;
+ public static boolean territoryTrucePainBuildWhenOffline = false;
+ public static boolean territoryTruceDenyUseage = true;
+ public static boolean territoryTruceProtectMaterials = true;
+ public static boolean territoryBlockCreepers = false;
+ public static boolean territoryBlockCreepersWhenOffline = false;
+ public static boolean territoryBlockFireballs = false;
+ public static boolean territoryBlockFireballsWhenOffline = false;
+ public static boolean territoryBlockTNT = false;
+ public static boolean territoryBlockTNTWhenOffline = false;
+ public static boolean territoryDenyEndermanBlocks = true;
+ public static boolean territoryDenyEndermanBlocksWhenOffline = true;
+
+ public static boolean safeZoneDenyBuild = true;
+ public static boolean safeZoneDenyUseage = true;
+ public static boolean safeZoneBlockTNT = true;
+ public static boolean safeZonePreventAllDamageToPlayers = false;
+ public static boolean safeZoneDenyEndermanBlocks = true;
+
+ public static boolean warZoneDenyBuild = true;
+ public static boolean warZoneDenyUseage = true;
+ public static boolean warZoneBlockCreepers = false;
+ public static boolean warZoneBlockFireballs = false;
+ public static boolean warZoneBlockTNT = true;
+ public static boolean warZonePowerLoss = true;
+ public static boolean warZoneFriendlyFire = false;
+ public static boolean warZoneDenyEndermanBlocks = true;
+
+ public static boolean wildernessDenyBuild = false;
+ public static boolean wildernessDenyUseage = false;
+ public static boolean wildernessBlockCreepers = false;
+ public static boolean wildernessBlockFireballs = false;
+ public static boolean wildernessBlockTNT = false;
+ public static boolean wildernessPowerLoss = true;
+ public static boolean wildernessDenyEndermanBlocks = false;
+
+ // for claimed areas where further faction-member ownership can be defined
+ public static boolean ownedAreasEnabled = true;
+ public static int ownedAreasLimitPerFaction = 0;
+ public static boolean ownedAreasModeratorsCanSet = false;
+ public static boolean ownedAreaModeratorsBypass = true;
+ public static boolean ownedAreaDenyBuild = true;
+ public static boolean ownedAreaPainBuild = false;
+ public static boolean ownedAreaProtectMaterials = true;
+ public static boolean ownedAreaDenyUseage = true;
+
+ public static boolean ownedMessageOnBorder = true;
+ public static boolean ownedMessageInsideTerritory = true;
+ public static boolean ownedMessageByChunk = false;
+
+ public static boolean pistonProtectionThroughDenyBuild = true;
+
+ public static Set territoryProtectedMaterials = EnumSet.noneOf(Material.class);
+ public static Set territoryDenyUseageMaterials = EnumSet.noneOf(Material.class);
+ public static Set territoryProtectedMaterialsWhenOffline = EnumSet.noneOf(Material.class);
+ public static Set territoryDenyUseageMaterialsWhenOffline = EnumSet.noneOf(Material.class);
+
+ public static transient Set safeZoneNerfedCreatureTypes = EnumSet.noneOf(EntityType.class);
+ // Economy settings
+ public static boolean econEnabled = true;
+ public static String econUniverseAccount = "";
+ public static double econCostClaimWilderness = 50000.0;//30.0
+ public static double econCostClaimFromFactionBonus = 0.0;//30.0
+ public static double econOverclaimRewardMultiplier = 0.0;
+ public static double econClaimAdditionalMultiplier = 0.05;//0.5
+ public static double econClaimRefundMultiplier = 0.0;//0.7
+ public static double econClaimUnconnectedFee = 0.0;
+ public static double econCostCreate = 1000000.0;//100.0
+ public static double econCostOwner = 0.0;//15.0
+ public static double econCostSethome = 100000.0;//30.0
+ public static double econCostJoin = 0.0;
+ public static double econCostLeave = 0.0;
+ public static double econCostKick = 0.0;
+ public static double econCostInvite = 50000.0;
+ public static double econCostHome = 0.0;
+ public static double econCostTag = 100000.0;
+ public static double econCostDesc = 0.0;
+ public static double econCostTitle = 0.0;
+ public static double econCostList = 0.0;
+ public static double econCostMap = 0.0;
+ public static double econCostPower = 0.0;
+ public static double econCostShow = 0.0;
+ public static double econCostStuck = 0.0;
+ public static double econCostOpen = 0.0;
+ public static double econCostAlly = 0.0;
+ public static double econCostTruce = 0.0;
+ public static double econCostEnemy = 0.0;
+ public static double econCostNeutral = 0.0;
+ public static double econCostNoBoom = 0.0;
+
+
+ // -------------------------------------------- //
+ // INTEGRATION: DYNMAP
+ // -------------------------------------------- //
+
+ // Should the dynmap intagration be used?
+ public static boolean dynmapUse = false;
+
+ // Name of the Factions layer
+ public static String dynmapLayerName = "Factions";
+
+ // Should the layer be visible per default
+ public static boolean dynmapLayerVisible = true;
+
+ // Ordering priority in layer menu (low goes before high - default is 0)
+ public static int dynmapLayerPriority = 2;
+
+ // (optional) set minimum zoom level before layer is visible (0 = default, always visible)
+ public static int dynmapLayerMinimumZoom = 0;
+
+ // Format for popup - substitute values for macros
+ public static String dynmapDescription =
+ "\n"
+ + "%name%
\n"
+ + "%description%
"
+ + "
\n"
+ + "Leader: %players.leader%
\n"
+ + "Admins: %players.admins.count%
\n"
+ + "Moderators: %players.moderators.count%
\n"
+ + "Members: %players.normals.count%
\n"
+ + "TOTAL: %players.count%
\n"
+ + "\n"
+ + "Bank: %money%
\n"
+ + "
\n"
+ + "";
+
+ // Enable the %money% macro. Only do this if you know your economy manager is thread-safe.
+ public static boolean dynmapDescriptionMoney = false;
+
+ // Allow players in faction to see one another on Dynmap (only relevant if Dynmap has 'player-info-protected' enabled)
+ public static boolean dynmapVisibilityByFaction = true;
+
+ // Optional setting to limit which regions to show.
+ // If empty all regions are shown.
+ // Specify Faction either by name or UUID.
+ // To show all regions on a given world, add 'world:' to the list.
+ public static Set dynmapVisibleFactions = new HashSet();
+
+ // Optional setting to hide specific Factions.
+ // Specify Faction either by name or UUID.
+ // To hide all regions on a given world, add 'world:' to the list.
+ public static Set dynmapHiddenFactions = new HashSet();
+
+ // Region Style
+ public static final transient String DYNMAP_STYLE_LINE_COLOR = "#00FF00";
+ public static final transient double DYNMAP_STYLE_LINE_OPACITY = 0.8D;
+ public static final transient int DYNMAP_STYLE_LINE_WEIGHT = 3;
+ public static final transient String DYNMAP_STYLE_FILL_COLOR = "#00FF00";
+ public static final transient double DYNMAP_STYLE_FILL_OPACITY = 0.35D;
+ public static final transient String DYNMAP_STYLE_HOME_MARKER = "greenflag";
+ public static final transient boolean DYNMAP_STYLE_BOOST = false;
+
+ public static DynmapStyle dynmapDefaultStyle = new DynmapStyle()
+ .setStrokeColor(DYNMAP_STYLE_LINE_COLOR)
+ .setLineOpacity(DYNMAP_STYLE_LINE_OPACITY)
+ .setLineWeight(DYNMAP_STYLE_LINE_WEIGHT)
+ .setFillColor(DYNMAP_STYLE_FILL_COLOR)
+ .setFillOpacity(DYNMAP_STYLE_FILL_OPACITY)
+ .setHomeMarker(DYNMAP_STYLE_HOME_MARKER)
+ .setBoost(DYNMAP_STYLE_BOOST);
+
+ // Optional per Faction style overrides. Any defined replace those in dynmapDefaultStyle.
+ // Specify Faction either by name or UUID.
+ public static Map dynmapFactionStyles = ImmutableMap.of(
+ "SafeZone", new DynmapStyle().setStrokeColor("#FF00FF").setFillColor("#FF00FF").setBoost(false),
+ "WarZone", new DynmapStyle().setStrokeColor("#FF0000").setFillColor("#FF0000").setBoost(false)
+ );
+
+
+ //Faction banks, to pay for land claiming and other costs instead of individuals paying for them
+ public static boolean bankEnabled = true;
+ public static boolean bankMembersCanWithdraw = false; //Have to be at least moderator to withdraw or pay money to another faction
+ public static boolean bankFactionPaysCosts = true; //The faction pays for faction command costs, such as sethome
+ public static boolean bankFactionPaysLandCosts = true; //The faction pays for land claiming costs.
+
+ // mainly for other plugins/mods that use a fake player to take actions, which shouldn't be subject to our protections
+ public static Set playersWhoBypassAllProtection = new LinkedHashSet();
+
+ public static Set worldsNoClaiming = new LinkedHashSet();
+ public static Set worldsNoPowerLoss = new LinkedHashSet();
+ public static Set worldsIgnorePvP = new LinkedHashSet();
+ public static Set worldsNoWildernessProtection = new LinkedHashSet();
+
+ // faction-
+ public static String vaultPrefix = "faction-%s";
+ public static int defaultMaxVaults = 0;
+
+ public static Backend backEnd = Backend.JSON;
+
+ public static transient int mapHeight = 8;
+ public static transient int mapWidth = 19;
+ public static transient char[] mapKeyChrs = "\\/#$%=&^ABCDEFGHJKLMNOPQRSTUVWXYZ1234567890abcdeghjmnopqrsuvwxyz?".toCharArray();
+
+ static {
+ baseCommandAliases.add("f");
+
+ territoryEnemyDenyCommands.add("home");
+ territoryEnemyDenyCommands.add("sethome");
+ territoryEnemyDenyCommands.add("spawn");
+ territoryEnemyDenyCommands.add("tpahere");
+ territoryEnemyDenyCommands.add("tpaccept");
+ territoryEnemyDenyCommands.add("tpa");
+
+ territoryProtectedMaterials.add(Material.WOODEN_DOOR);
+ territoryProtectedMaterials.add(Material.TRAP_DOOR);
+ territoryProtectedMaterials.add(Material.FENCE_GATE);
+ territoryProtectedMaterials.add(Material.DISPENSER);
+ territoryProtectedMaterials.add(Material.CHEST);
+ territoryProtectedMaterials.add(Material.FURNACE);
+ territoryProtectedMaterials.add(Material.BURNING_FURNACE);
+ territoryProtectedMaterials.add(Material.DIODE_BLOCK_OFF);
+ territoryProtectedMaterials.add(Material.DIODE_BLOCK_ON);
+ territoryProtectedMaterials.add(Material.JUKEBOX);
+ territoryProtectedMaterials.add(Material.BREWING_STAND);
+ territoryProtectedMaterials.add(Material.ENCHANTMENT_TABLE);
+ territoryProtectedMaterials.add(Material.CAULDRON);
+ territoryProtectedMaterials.add(Material.SOIL);
+ territoryProtectedMaterials.add(Material.BEACON);
+ territoryProtectedMaterials.add(Material.ANVIL);
+ territoryProtectedMaterials.add(Material.TRAPPED_CHEST);
+ territoryProtectedMaterials.add(Material.DROPPER);
+ territoryProtectedMaterials.add(Material.HOPPER);
+
+ territoryDenyUseageMaterials.add(Material.FIREBALL);
+ territoryDenyUseageMaterials.add(Material.FLINT_AND_STEEL);
+ territoryDenyUseageMaterials.add(Material.BUCKET);
+ territoryDenyUseageMaterials.add(Material.WATER_BUCKET);
+ territoryDenyUseageMaterials.add(Material.LAVA_BUCKET);
+
+ territoryProtectedMaterialsWhenOffline.add(Material.WOODEN_DOOR);
+ territoryProtectedMaterialsWhenOffline.add(Material.TRAP_DOOR);
+ territoryProtectedMaterialsWhenOffline.add(Material.FENCE_GATE);
+ territoryProtectedMaterialsWhenOffline.add(Material.DISPENSER);
+ territoryProtectedMaterialsWhenOffline.add(Material.CHEST);
+ territoryProtectedMaterialsWhenOffline.add(Material.FURNACE);
+ territoryProtectedMaterialsWhenOffline.add(Material.BURNING_FURNACE);
+ territoryProtectedMaterialsWhenOffline.add(Material.DIODE_BLOCK_OFF);
+ territoryProtectedMaterialsWhenOffline.add(Material.DIODE_BLOCK_ON);
+ territoryProtectedMaterialsWhenOffline.add(Material.JUKEBOX);
+ territoryProtectedMaterialsWhenOffline.add(Material.BREWING_STAND);
+ territoryProtectedMaterialsWhenOffline.add(Material.ENCHANTMENT_TABLE);
+ territoryProtectedMaterialsWhenOffline.add(Material.CAULDRON);
+ territoryProtectedMaterialsWhenOffline.add(Material.SOIL);
+ territoryProtectedMaterialsWhenOffline.add(Material.BEACON);
+ territoryProtectedMaterialsWhenOffline.add(Material.ANVIL);
+ territoryProtectedMaterialsWhenOffline.add(Material.TRAPPED_CHEST);
+ territoryProtectedMaterialsWhenOffline.add(Material.DROPPER);
+ territoryProtectedMaterialsWhenOffline.add(Material.HOPPER);
+
+ territoryDenyUseageMaterialsWhenOffline.add(Material.FIREBALL);
+ territoryDenyUseageMaterialsWhenOffline.add(Material.FLINT_AND_STEEL);
+ territoryDenyUseageMaterialsWhenOffline.add(Material.BUCKET);
+ territoryDenyUseageMaterialsWhenOffline.add(Material.WATER_BUCKET);
+ territoryDenyUseageMaterialsWhenOffline.add(Material.LAVA_BUCKET);
+
+ safeZoneNerfedCreatureTypes.add(EntityType.BLAZE);
+ safeZoneNerfedCreatureTypes.add(EntityType.CAVE_SPIDER);
+ safeZoneNerfedCreatureTypes.add(EntityType.CREEPER);
+ safeZoneNerfedCreatureTypes.add(EntityType.ENDER_DRAGON);
+ safeZoneNerfedCreatureTypes.add(EntityType.ENDERMAN);
+ safeZoneNerfedCreatureTypes.add(EntityType.GHAST);
+ safeZoneNerfedCreatureTypes.add(EntityType.MAGMA_CUBE);
+ safeZoneNerfedCreatureTypes.add(EntityType.PIG_ZOMBIE);
+ safeZoneNerfedCreatureTypes.add(EntityType.SILVERFISH);
+ safeZoneNerfedCreatureTypes.add(EntityType.SKELETON);
+ safeZoneNerfedCreatureTypes.add(EntityType.SPIDER);
+ safeZoneNerfedCreatureTypes.add(EntityType.SLIME);
+ safeZoneNerfedCreatureTypes.add(EntityType.WITCH);
+ safeZoneNerfedCreatureTypes.add(EntityType.WITHER);
+ safeZoneNerfedCreatureTypes.add(EntityType.ZOMBIE);
+ }
+
+ // -------------------------------------------- //
+ // Persistance
+ // -------------------------------------------- //
+ private static transient Conf i = new Conf();
+
+ public static void load() {
+ P.p.persist.loadOrSaveDefault(i, Conf.class, "conf");
+ }
+
+ public static void save() {
+ P.p.persist.save(i);
+ }
+
+ public enum Backend {
+ JSON,
+ //MYSQL, TODO
+ ;
+ }
+}
+
diff --git a/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/FLocation.java b/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/FLocation.java
new file mode 100644
index 0000000..790ddac
--- /dev/null
+++ b/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/FLocation.java
@@ -0,0 +1,251 @@
+package com.massivecraft.factions;
+
+import com.massivecraft.factions.util.MiscUtil;
+import org.bukkit.*;
+import org.bukkit.block.Block;
+import org.bukkit.entity.Player;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public class FLocation implements Serializable {
+ private static final long serialVersionUID = -8292915234027387983L;
+ private static final boolean worldBorderSupport;
+ private String worldName = "world";
+ private int x = 0;
+ private int z = 0;
+
+ static {
+ boolean worldBorderClassPresent = false;
+ try {
+ Class.forName("org.bukkit.WorldBorder");
+ worldBorderClassPresent = true;
+ } catch (ClassNotFoundException ignored) {}
+
+ worldBorderSupport = worldBorderClassPresent;
+ }
+
+ //----------------------------------------------//
+ // Constructors
+ //----------------------------------------------//
+
+ public FLocation() {
+
+ }
+
+ public FLocation(String worldName, int x, int z) {
+ this.worldName = worldName;
+ this.x = x;
+ this.z = z;
+ }
+
+ public FLocation(Location location) {
+ this(location.getWorld().getName(), blockToChunk(location.getBlockX()), blockToChunk(location.getBlockZ()));
+ }
+
+ public FLocation(Player player) {
+ this(player.getLocation());
+ }
+
+ public FLocation(FPlayer fplayer) {
+ this(fplayer.getPlayer());
+ }
+
+ public FLocation(Block block) {
+ this(block.getLocation());
+ }
+
+ //----------------------------------------------//
+ // Getters and Setters
+ //----------------------------------------------//
+
+ public String getWorldName() {
+ return worldName;
+ }
+
+ public World getWorld() {
+ return Bukkit.getWorld(worldName);
+ }
+
+ public void setWorldName(String worldName) {
+ this.worldName = worldName;
+ }
+
+ public long getX() {
+ return x;
+ }
+
+ public void setX(int x) {
+ this.x = x;
+ }
+
+ public long getZ() {
+ return z;
+ }
+
+ public void setZ(int z) {
+ this.z = z;
+ }
+
+ public String getCoordString() {
+ return "" + x + "," + z;
+ }
+
+ @Override
+ public String toString() {
+ return "[" + this.getWorldName() + "," + this.getCoordString() + "]";
+ }
+
+ public static FLocation fromString(String string) {
+ int index = string.indexOf(",", 0);
+ int start = 1;
+ String worldName = string.substring(start, index);
+ start = index + 1;
+ index = string.indexOf(",", start);
+ int x = Integer.valueOf(string.substring(start, index));
+ int y = Integer.valueOf(string.substring(index + 1, string.length() - 1));
+ return new FLocation(worldName, x, y);
+ }
+
+ //----------------------------------------------//
+ // Block/Chunk/Region Value Transformation
+ //----------------------------------------------//
+
+ // bit-shifting is used because it's much faster than standard division and multiplication
+ public static int blockToChunk(int blockVal) { // 1 chunk is 16x16 blocks
+ return blockVal >> 4; // ">> 4" == "/ 16"
+ }
+
+ public static int blockToRegion(int blockVal) { // 1 region is 512x512 blocks
+ return blockVal >> 9; // ">> 9" == "/ 512"
+ }
+
+ public static int chunkToRegion(int chunkVal) { // 1 region is 32x32 chunks
+ return chunkVal >> 5; // ">> 5" == "/ 32"
+ }
+
+ public static int chunkToBlock(int chunkVal) {
+ return chunkVal << 4; // "<< 4" == "* 16"
+ }
+
+ public static int regionToBlock(int regionVal) {
+ return regionVal << 9; // "<< 9" == "* 512"
+ }
+
+ public static int regionToChunk(int regionVal) {
+ return regionVal << 5; // "<< 5" == "* 32"
+ }
+
+ //----------------------------------------------//
+ // Misc Geometry
+ //----------------------------------------------//
+
+ public FLocation getRelative(int dx, int dz) {
+ return new FLocation(this.worldName, this.x + dx, this.z + dz);
+ }
+
+ public double getDistanceTo(FLocation that) {
+ double dx = that.x - this.x;
+ double dz = that.z - this.z;
+ return Math.sqrt(dx * dx + dz * dz);
+ }
+
+ public double getDistanceSquaredTo(FLocation that) {
+ double dx = that.x - this.x;
+ double dz = that.z - this.z;
+ return dx * dx + dz * dz;
+ }
+
+ public boolean isInChunk(Location loc) {
+ if (loc == null) {
+ return false;
+ }
+ Chunk chunk = loc.getChunk();
+ return loc.getWorld().getName().equalsIgnoreCase(getWorldName()) && chunk.getX() == x && chunk.getZ() == z;
+ }
+
+ /**
+ * Checks if the chunk represented by this FLocation is outside the world border
+ *
+ * @param buffer the number of chunks from the border that will be treated as "outside"
+ * @return whether this location is outside of the border
+ */
+ public boolean isOutsideWorldBorder(int buffer) {
+ if (!worldBorderSupport) {
+ return false;
+ }
+
+ WorldBorder border = getWorld().getWorldBorder();
+ Chunk chunk = border.getCenter().getChunk();
+
+ int lim = FLocation.chunkToRegion((int) border.getSize()) - buffer;
+ int diffX = Math.abs(chunk.getX() - x);
+ int diffZ = Math.abs(chunk.getZ() - z);
+ return diffX > lim || diffZ > lim;
+ }
+
+ //----------------------------------------------//
+ // Some Geometry
+ //----------------------------------------------//
+ public Set getCircle(double radius) {
+ double radiusSquared = radius * radius;
+
+ Set ret = new LinkedHashSet();
+ if (radius <= 0) {
+ return ret;
+ }
+
+ int xfrom = (int) Math.floor(this.x - radius);
+ int xto = (int) Math.ceil(this.x + radius);
+ int zfrom = (int) Math.floor(this.z - radius);
+ int zto = (int) Math.ceil(this.z + radius);
+
+ for (int x = xfrom; x <= xto; x++) {
+ for (int z = zfrom; z <= zto; z++) {
+ FLocation potential = new FLocation(this.worldName, x, z);
+ if (this.getDistanceSquaredTo(potential) <= radiusSquared) {
+ ret.add(potential);
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ public static HashSet getArea(FLocation from, FLocation to) {
+ HashSet ret = new HashSet();
+
+ for (long x : MiscUtil.range(from.getX(), to.getX())) {
+ for (long z : MiscUtil.range(from.getZ(), to.getZ())) {
+ ret.add(new FLocation(from.getWorldName(), (int) x, (int) z));
+ }
+ }
+
+ return ret;
+ }
+
+ //----------------------------------------------//
+ // Comparison
+ //----------------------------------------------//
+
+ @Override
+ public int hashCode() {
+ // should be fast, with good range and few hash collisions: (x * 512) + z + worldName.hashCode
+ return (this.x << 9) + this.z + (this.worldName != null ? this.worldName.hashCode() : 0);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof FLocation)) {
+ return false;
+ }
+
+ FLocation that = (FLocation) obj;
+ return this.x == that.x && this.z == that.z && (this.worldName == null ? that.worldName == null : this.worldName.equals(that.worldName));
+ }
+}
\ No newline at end of file
diff --git a/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/FPlayer.java b/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/FPlayer.java
new file mode 100644
index 0000000..3c54b6a
--- /dev/null
+++ b/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/FPlayer.java
@@ -0,0 +1,264 @@
+package com.massivecraft.factions;
+
+import com.massivecraft.factions.iface.EconomyParticipator;
+import com.massivecraft.factions.iface.RelationParticipator;
+import com.massivecraft.factions.struct.ChatMode;
+import com.massivecraft.factions.struct.Relation;
+import com.massivecraft.factions.struct.Role;
+import com.massivecraft.factions.util.WarmUpUtil;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+
+import java.util.List;
+
+
+/**
+ * Logged in players always have exactly one FPlayer instance. Logged out players may or may not have an FPlayer
+ * instance. They will always have one if they are part of a faction. This is because only players with a faction are
+ * saved to disk (in order to not waste disk space).
+ *
+ * The FPlayer is linked to a minecraft player using the player name.
+ *
+ * The same instance is always returned for the same player. This means you can use the == operator. No .equals method
+ * necessary.
+ */
+
+public interface FPlayer extends EconomyParticipator {
+ public void login();
+
+ public void logout();
+
+ public Faction getFaction();
+
+ public String getFactionId();
+
+ public boolean hasFaction();
+
+ public void setFaction(Faction faction);
+
+ public boolean willAutoLeave();
+
+ public void setAutoLeave(boolean autoLeave);
+
+ public long getLastFrostwalkerMessage();
+
+ public void setLastFrostwalkerMessage();
+
+ public void setMonitorJoins(boolean monitor);
+
+ public boolean isMonitoringJoins();
+
+ public Role getRole();
+
+ public void setRole(Role role);
+
+ public double getPowerBoost();
+
+ public void setPowerBoost(double powerBoost);
+
+ public Faction getAutoClaimFor();
+
+ public void setAutoClaimFor(Faction faction);
+
+ public boolean isAutoSafeClaimEnabled();
+
+ public void setIsAutoSafeClaimEnabled(boolean enabled);
+
+ public boolean isAutoWarClaimEnabled();
+
+ public void setIsAutoWarClaimEnabled(boolean enabled);
+
+ public boolean isAdminBypassing();
+
+ public boolean isVanished();
+
+ public void setIsAdminBypassing(boolean val);
+
+ public void setChatMode(ChatMode chatMode);
+
+ public ChatMode getChatMode();
+
+ public void setIgnoreAllianceChat(boolean ignore);
+
+ public boolean isIgnoreAllianceChat();
+
+ public void setSpyingChat(boolean chatSpying);
+
+ public boolean isSpyingChat();
+
+ public boolean showScoreboard();
+
+ public void setShowScoreboard(boolean show);
+
+ // FIELD: account
+ public String getAccountId();
+
+ public void resetFactionData(boolean doSpoutUpdate);
+
+ public void resetFactionData();
+
+ public long getLastLoginTime();
+
+ public void setLastLoginTime(long lastLoginTime);
+
+ public boolean isMapAutoUpdating();
+
+ public void setMapAutoUpdating(boolean mapAutoUpdating);
+
+ public boolean hasLoginPvpDisabled();
+
+ public FLocation getLastStoodAt();
+
+ public void setLastStoodAt(FLocation flocation);
+
+ public String getTitle();
+
+ public void setTitle(String title);
+
+ public String getName();
+
+ public String getTag();
+
+ // Base concatenations:
+
+ public String getNameAndSomething(String something);
+
+ public String getNameAndTitle();
+
+ public String getNameAndTag();
+
+ // Colored concatenations:
+ // These are used in information messages
+
+ public String getNameAndTitle(Faction faction);
+
+ public String getNameAndTitle(FPlayer fplayer);
+
+ // Chat CoreTag:
+ // These are injected into the format of global chat messages.
+
+ public String getChatTag();
+
+ // Colored Chat CoreTag
+ public String getChatTag(Faction faction);
+
+ public String getChatTag(FPlayer fplayer);
+
+ public int getKills();
+
+ public int getDeaths();
+
+
+ // -------------------------------
+ // Relation and relation colors
+ // -------------------------------
+
+ @Override
+ public String describeTo(RelationParticipator that, boolean ucfirst);
+
+ @Override
+ public String describeTo(RelationParticipator that);
+
+ @Override
+ public Relation getRelationTo(RelationParticipator rp);
+
+ @Override
+ public Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful);
+
+ public Relation getRelationToLocation();
+
+ @Override
+ public ChatColor getColorTo(RelationParticipator rp);
+
+ //----------------------------------------------//
+ // Health
+ //----------------------------------------------//
+ public void heal(int amnt);
+
+
+ //----------------------------------------------//
+ // Power
+ //----------------------------------------------//
+ public double getPower();
+
+ public void alterPower(double delta);
+
+ public double getPowerMax();
+
+ public double getPowerMin();
+
+ public int getPowerRounded();
+
+ public int getPowerMaxRounded();
+
+ public int getPowerMinRounded();
+
+ public void updatePower();
+
+ public void losePowerFromBeingOffline();
+
+ public void onDeath();
+
+ //----------------------------------------------//
+ // Territory
+ //----------------------------------------------//
+ public boolean isInOwnTerritory();
+
+ public boolean isInOthersTerritory();
+
+ public boolean isInAllyTerritory();
+
+ public boolean isInNeutralTerritory();
+
+ public boolean isInEnemyTerritory();
+
+ public void sendFactionHereMessage(Faction from);
+
+ // -------------------------------
+ // Actions
+ // -------------------------------
+
+ public void leave(boolean makePay);
+
+ public boolean canClaimForFaction(Faction forFaction);
+
+ public boolean canClaimForFactionAtLocation(Faction forFaction, Location location, boolean notifyFailure);
+
+ public boolean attemptClaim(Faction forFaction, Location location, boolean notifyFailure);
+
+ public void msg(String str, Object... args);
+
+ public String getId();
+
+ public Player getPlayer();
+
+ public boolean isOnline();
+
+ public void sendMessage(String message);
+
+ public void sendMessage(List messages);
+
+ public boolean isOnlineAndVisibleTo(Player me);
+
+ public void remove();
+
+ public boolean isOffline();
+
+ public void setId(String id);
+
+ // -------------------------------
+ // Warmups
+ // -------------------------------
+
+ public boolean isWarmingUp();
+
+ public WarmUpUtil.Warmup getWarmupType();
+
+ public void addWarmup(WarmUpUtil.Warmup warmup, int taskId);
+
+ public void stopWarmup();
+
+ public void clearWarmup();
+
+}
diff --git a/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/FPlayers.java b/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/FPlayers.java
new file mode 100644
index 0000000..fb56eff
--- /dev/null
+++ b/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/FPlayers.java
@@ -0,0 +1,41 @@
+package com.massivecraft.factions;
+
+import com.massivecraft.factions.zcore.persist.json.JSONFPlayers;
+import org.bukkit.OfflinePlayer;
+import org.bukkit.entity.Player;
+
+import java.util.Collection;
+
+public abstract class FPlayers {
+ protected static FPlayers instance = getFPlayersImpl();
+
+ public abstract void clean();
+
+ public static FPlayers getInstance() {
+ return instance;
+ }
+
+ private static FPlayers getFPlayersImpl() {
+ switch (Conf.backEnd) {
+ case JSON:
+ return new JSONFPlayers();
+ }
+ return null;
+ }
+
+ public abstract Collection getOnlinePlayers();
+
+ public abstract FPlayer getByPlayer(Player player);
+
+ public abstract Collection getAllFPlayers();
+
+ public abstract void forceSave();
+
+ public abstract void forceSave(boolean sync);
+
+ public abstract FPlayer getByOfflinePlayer(OfflinePlayer player);
+
+ public abstract FPlayer getById(String string);
+
+ public abstract void load();
+}
diff --git a/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/Faction.java b/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/Faction.java
new file mode 100644
index 0000000..7b4b056
--- /dev/null
+++ b/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/Faction.java
@@ -0,0 +1,265 @@
+package com.massivecraft.factions;
+
+import com.massivecraft.factions.eco.EcoResult;
+import com.massivecraft.factions.iface.EconomyParticipator;
+import com.massivecraft.factions.iface.RelationParticipator;
+import com.massivecraft.factions.struct.Relation;
+import com.massivecraft.factions.struct.Role;
+import com.massivecraft.factions.util.LazyLocation;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+public interface Faction extends EconomyParticipator {
+ public HashMap> getAnnouncements();
+
+ public ConcurrentHashMap getWarps();
+
+ public LazyLocation getWarp(String name);
+
+ public void setWarp(String name, LazyLocation loc);
+
+ public boolean isWarp(String name);
+
+ public boolean removeWarp(String name);
+
+ public void clearWarps();
+
+ public int getMaxVaults();
+
+ public void setMaxVaults(int value);
+
+ public void addAnnouncement(FPlayer fPlayer, String msg);
+
+ public void sendUnreadAnnouncements(FPlayer fPlayer);
+
+ public void removeAnnouncements(FPlayer fPlayer);
+
+ public Set getInvites();
+
+ public String getId();
+
+ public void invite(FPlayer fplayer);
+
+ public void deinvite(FPlayer fplayer);
+
+ public boolean isInvited(FPlayer fplayer);
+
+ public boolean getOpen();
+
+ public void setOpen(boolean isOpen);
+
+ public boolean isPeaceful();
+
+ public void setPeaceful(boolean isPeaceful);
+
+ public void setPeacefulExplosionsEnabled(boolean val);
+
+ public boolean getPeacefulExplosionsEnabled();
+
+ public boolean noExplosionsInTerritory();
+
+ public boolean isPermanent();
+
+ public void setPermanent(boolean isPermanent);
+
+ public String getTag();
+
+ public String getTag(String prefix);
+
+ public String getTag(Faction otherFaction);
+
+ public String getTag(FPlayer otherFplayer);
+
+ public void setTag(String str);
+
+ public String getComparisonTag();
+
+ public String getDescription();
+
+ public void setDescription(String value);
+
+ public void setHome(Location home);
+
+ public boolean hasHome();
+
+ public Location getHome();
+
+ public long getFoundedDate();
+
+ public void setFoundedDate(long newDate);
+
+ public void confirmValidHome();
+
+ public String getAccountId();
+
+ public Integer getPermanentPower();
+
+ public void setPermanentPower(Integer permanentPower);
+
+ public boolean hasPermanentPower();
+
+ public double getPowerBoost();
+
+ public void setPowerBoost(double powerBoost);
+
+ public boolean noPvPInTerritory();
+
+ public boolean noMonstersInTerritory();
+
+ public boolean isNormal();
+
+ @Deprecated
+ public boolean isNone();
+
+ public boolean isWilderness();
+
+ public boolean isSafeZone();
+
+ public boolean isWarZone();
+
+ public boolean isPlayerFreeType();
+
+ public boolean isPowerFrozen();
+
+ public void setLastDeath(long time);
+
+ public int getKills();
+
+ public int getDeaths();
+
+ // -------------------------------
+ // Relation and relation colors
+ // -------------------------------
+
+ @Override
+ public String describeTo(RelationParticipator that, boolean ucfirst);
+
+ @Override
+ public String describeTo(RelationParticipator that);
+
+ @Override
+ public Relation getRelationTo(RelationParticipator rp);
+
+ @Override
+ public Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful);
+
+ @Override
+ public ChatColor getColorTo(RelationParticipator rp);
+
+ public Relation getRelationWish(Faction otherFaction);
+
+ public void setRelationWish(Faction otherFaction, Relation relation);
+
+ public int getRelationCount(Relation relation);
+
+ // ----------------------------------------------//
+ // Power
+ // ----------------------------------------------//
+ public double getPower();
+
+ public double getPowerMax();
+
+ public int getPowerRounded();
+
+ public int getPowerMaxRounded();
+
+ public int getLandRounded();
+
+ public int getLandRoundedInWorld(String worldName);
+
+ public boolean hasLandInflation();
+
+ // -------------------------------
+ // FPlayers
+ // -------------------------------
+
+ // maintain the reference list of FPlayers in this faction
+ public void refreshFPlayers();
+
+ public boolean addFPlayer(FPlayer fplayer);
+
+ public boolean removeFPlayer(FPlayer fplayer);
+
+ public int getSize();
+
+ public Set getFPlayers();
+
+ public Set getFPlayersWhereOnline(boolean online);
+
+ public FPlayer getFPlayerAdmin();
+
+ public ArrayList getFPlayersWhereRole(Role role);
+
+ public ArrayList getOnlinePlayers();
+
+ // slightly faster check than getOnlinePlayers() if you just want to see if
+ // there are any players online
+ public boolean hasPlayersOnline();
+
+ public void memberLoggedOff();
+
+ // used when current leader is about to be removed from the faction;
+ // promotes new leader, or disbands faction if no other members left
+ public void promoteNewLeader();
+
+ // ----------------------------------------------//
+ // Messages
+ // ----------------------------------------------//
+ public void msg(String message, Object... args);
+
+ public void sendMessage(String message);
+
+ public void sendMessage(List messages);
+
+ // ----------------------------------------------//
+ // Ownership of specific claims
+ // ----------------------------------------------//
+
+ public Map> getClaimOwnership();
+
+ public void clearAllClaimOwnership();
+
+ public void clearClaimOwnership(FLocation loc);
+
+ public void clearClaimOwnership(FPlayer player);
+
+ public int getCountOfClaimsWithOwners();
+
+ public boolean doesLocationHaveOwnersSet(FLocation loc);
+
+ public boolean isPlayerInOwnerList(FPlayer player, FLocation loc);
+
+ public void setPlayerAsOwner(FPlayer player, FLocation loc);
+
+ public void removePlayerAsOwner(FPlayer player, FLocation loc);
+
+ public Set getOwnerList(FLocation loc);
+
+ public String getOwnerListString(FLocation loc);
+
+ public boolean playerHasOwnershipRights(FPlayer fplayer, FLocation loc);
+
+ // ----------------------------------------------//
+ // Persistance and entity management
+ // ----------------------------------------------//
+ public void remove();
+
+ public Set getAllClaims();
+
+ public void setId(String id);
+
+ // ----------------------------------------------//
+ // Economy Faction stash
+ // ----------------------------------------------//
+ public double getStash();
+
+ public EcoResult addToStash(double amount);
+
+ public EcoResult takeFromStash(double amount);
+
+ public void setStash(double amount);
+}
diff --git a/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/Factions.java b/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/Factions.java
new file mode 100644
index 0000000..5459b6d
--- /dev/null
+++ b/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/Factions.java
@@ -0,0 +1,55 @@
+package com.massivecraft.factions;
+
+import com.massivecraft.factions.zcore.persist.json.JSONFactions;
+
+import java.util.ArrayList;
+import java.util.Set;
+
+public abstract class Factions {
+ protected static Factions instance = getFactionsImpl();
+
+ public abstract Faction getFactionById(String id);
+
+ public abstract Faction getByTag(String str);
+
+ public abstract Faction getBestTagMatch(String start);
+
+ public abstract boolean isTagTaken(String str);
+
+ public abstract boolean isValidFactionId(String id);
+
+ public abstract Faction createFaction();
+
+ public abstract void removeFaction(String id);
+
+ public abstract Set getFactionTags();
+
+ public abstract ArrayList getAllFactions();
+
+ @Deprecated
+ public abstract Faction getNone();
+
+ public abstract Faction getWilderness();
+
+ public abstract Faction getSafeZone();
+
+ public abstract Faction getWarZone();
+
+ public abstract void forceSave();
+
+ public abstract void forceSave(boolean sync);
+
+ public static Factions getInstance() {
+ return instance;
+ }
+
+ private static Factions getFactionsImpl() {
+ switch (Conf.backEnd) {
+ case JSON:
+ return new JSONFactions();
+ }
+ return null;
+ }
+
+ public abstract void load();
+}
diff --git a/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/P.java b/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/P.java
new file mode 100644
index 0000000..864d78e
--- /dev/null
+++ b/cartels-master@e4f5c2ecec5/src/main/java/com/massivecraft/factions/P.java
@@ -0,0 +1,334 @@
+package com.massivecraft.factions;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+import com.massivecraft.factions.cmd.CmdAutoHelp;
+import com.massivecraft.factions.cmd.FCmdRoot;
+import com.massivecraft.factions.integration.Econ;
+import com.massivecraft.factions.integration.Essentials;
+import com.massivecraft.factions.integration.Worldguard;
+import com.massivecraft.factions.integration.dynmap.EngineDynmap;
+import com.massivecraft.factions.listeners.*;
+import com.massivecraft.factions.struct.ChatMode;
+import com.massivecraft.factions.util.*;
+import com.massivecraft.factions.zcore.MPlugin;
+import com.massivecraft.factions.zcore.util.TextUtil;
+import net.grandtheftmc.core.menus.MenuManager;
+import net.milkbowl.vault.permission.Permission;
+import org.bukkit.Bukkit;
+import org.bukkit.OfflinePlayer;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.event.player.AsyncPlayerChatEvent;
+import org.bukkit.plugin.RegisteredServiceProvider;
+
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+
+
+public class P extends MPlugin {
+
+ // Our single plugin instance.
+ // Single 4 life.
+ public static P p;
+ public static Permission perms = null;
+
+ // Persistence related
+ private boolean locked = false;
+
+ public boolean getLocked() {
+ return this.locked;
+ }
+
+ public void setLocked(boolean val) {
+ this.locked = val;
+ this.setAutoSave(val);
+ }
+
+ private Integer AutoLeaveTask = null;
+
+ // Commands
+ public FCmdRoot cmdBase;
+ public CmdAutoHelp cmdAutoHelp;
+
+ private boolean hookedPlayervaults;
+
+ public P() {
+ p = this;
+ }
+
+ @Override
+ public void onEnable() {
+ if (!preEnable()) {
+ return;
+ }
+ this.loadSuccessful = false;
+ saveDefaultConfig();
+
+ // Load Conf from disk
+ Conf.load();
+ Essentials.setup();
+ FPlayers.getInstance().load();
+ Factions.getInstance().load();
+ for (FPlayer fPlayer : FPlayers.getInstance().getAllFPlayers()) {
+ Faction faction = Factions.getInstance().getFactionById(fPlayer.getFactionId());
+ if (faction == null) {
+ log("Invalid cartel id on " + fPlayer.getName() + ":" + fPlayer.getFactionId());
+ fPlayer.resetFactionData(false);
+ continue;
+ }
+ faction.addFPlayer(fPlayer);
+ }
+ Board.getInstance().load();
+ Board.getInstance().clean();
+
+ // Add Base Commands
+ this.cmdBase = new FCmdRoot();
+ this.cmdAutoHelp = new CmdAutoHelp();
+ this.getBaseCommands().add(cmdBase);
+
+ Econ.setup();
+ setupPermissions();
+
+ if (Conf.worldGuardChecking || Conf.worldGuardBuildPriority) {
+ Worldguard.init(this);
+ }
+
+ EngineDynmap.getInstance().init();
+
+ // start up task which runs the autoLeaveAfterDaysOfInactivity routine
+ startAutoLeaveTask(false);
+
+ // Register Event Handlers
+ getServer().getPluginManager().registerEvents(new FactionsPlayerListener(this), this);
+ getServer().getPluginManager().registerEvents(new FactionsChatListener(this), this);
+ getServer().getPluginManager().registerEvents(new FactionsEntityListener(this), this);
+ getServer().getPluginManager().registerEvents(new FactionsExploitListener(), this);
+ getServer().getPluginManager().registerEvents(new FactionsBlockListener(this), this);
+ getServer().getPluginManager().registerEvents(new MenuListener(), this);
+
+ // since some other plugins execute commands directly through this command interface, provide it
+ this.getCommand(this.refCommand).setExecutor(this);
+
+ MenuManager.addMenu("carteltop", 54, "&cTop Cartels");
+
+ postEnable();
+ this.loadSuccessful = true;
+ }
+
+ private boolean setupPermissions() {
+ try {
+ RegisteredServiceProvider rsp = getServer().getServicesManager().getRegistration(Permission.class);
+ if (rsp != null) {
+ perms = rsp.getProvider();
+ }
+ } catch (NoClassDefFoundError ex) {
+ return false;
+ }
+ return perms != null;
+ }
+
+ @Override
+ public GsonBuilder getGsonBuilder() {
+ Type mapFLocToStringSetType = new TypeToken