Converted Bungee to redis.

Increased DBPool maximum connections to 5.
This commit is contained in:
Jonathan Williams 2015-03-13 17:53:36 -07:00
parent 838df3f57a
commit cb93769e03
31 changed files with 994 additions and 208 deletions

View File

@ -264,6 +264,9 @@
<fileset dir="../Mineplex.BungeeRotator/bin">
<include name="**/*.class"/>
</fileset>
<fileset dir="../Mineplex.ServerData/bin">
<include name="**/*.class"/>
</fileset>
<zipfileset src="../Libraries/mysql.zip" />
@ -272,14 +275,18 @@
value="mineplex.bungee.BungeeRotator"/>
</manifest>
<zipfileset src="../Libraries/jooq-3.5.2.jar" />
<zipfileset src="../Libraries/httpclient-4.2.jar" />
<zipfileset src="../Libraries/httpcore-4.2.jar" />
<zipfileset src="../Libraries/httpclient-cache-4.2.jar" />
<zipfileset src="../Libraries/httpmime-4.2.jar" />
<zipfileset src="../Libraries/gson-2.2.1.jar" />
<zipfileset src="../Libraries/javax.mail.jar" />
<zipfileset src="../Libraries/commons-logging-1.1.1.jar" />
<zipfileset src="../Libraries/commons-codec-1.6.jar" />
<zipfileset src="../Libraries/commons-dbcp2-2.0.1.jar" />
<zipfileset src="../Libraries/jedis-2.4.2.jar" />
<zipfileset src="../Libraries/commons-pool2-2.2.jar" />
<zipfileset src="../Libraries/commons-dbcp2-2.0.1.jar" />
</jar>
<copy file="../bin/BungeeRotator.jar" todir="../../Testing/BungeeRotator/"/>
</target>

View File

@ -19,7 +19,7 @@ public class Mineplexer extends Plugin
PlayerCount playerCount = new PlayerCount(this);
new FileUpdater(this);
new PlayerStats(this);
new InternetStatus(this);
//new InternetStatus(this);
new PlayerTracker(this);
new AccountManager(this, playerCount);
}

View File

@ -8,10 +8,10 @@ import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import mineplex.serverdata.MinecraftServer;
import mineplex.serverdata.Region;
import mineplex.serverdata.ServerManager;
import mineplex.serverdata.ServerRepository;
import mineplex.serverdata.data.MinecraftServer;
import net.md_5.bungee.api.event.ServerConnectEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.plugin.Plugin;

View File

@ -2,7 +2,7 @@ package mineplex.bungee.lobbyBalancer;
import java.util.Comparator;
import mineplex.serverdata.MinecraftServer;
import mineplex.serverdata.data.MinecraftServer;
public class LobbySorter implements Comparator<MinecraftServer>
{

View File

@ -47,14 +47,14 @@ public class MotdManager implements Listener, Runnable, CustomMotdFactory
{
_motdLines = _repository.retrieveMotd();
if (_repository.retrieveMotdAnimated())
{
//if (true)
//{
InitialHandler.setCustomMotdFactory(this);
}
else
{
InitialHandler.setCustomMotdFactory(null);
}
//}
//else
//{
// InitialHandler.setCustomMotdFactory(null);
//}
}
public List<String> getMotdLines()

View File

@ -1,7 +1,12 @@
package mineplex.bungee.playerCount;
import java.io.File;
import java.util.concurrent.TimeUnit;
import mineplex.serverdata.Region;
import mineplex.serverdata.ServerManager;
import mineplex.serverdata.ServerRepository;
import mineplex.serverdata.data.BungeeServer;
import net.md_5.bungee.api.ServerPing.Players;
import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.api.event.ProxyPingEvent;
@ -12,7 +17,8 @@ import net.md_5.bungee.event.EventHandler;
public class PlayerCount implements Listener, Runnable
{
private Plugin _plugin;
private PlayerCountRepository _repository;
private ServerRepository _repository;
private ListenerInfo _listenerInfo;
private int _totalPlayers = -1;
@ -20,22 +26,25 @@ public class PlayerCount implements Listener, Runnable
{
_plugin = plugin;
_plugin.getProxy().getScheduler().schedule(_plugin, this, 1L, 1L, TimeUnit.SECONDS);
_plugin.getProxy().getScheduler().schedule(_plugin, this, 500L, 500L, TimeUnit.MILLISECONDS);
_plugin.getProxy().getPluginManager().registerListener(_plugin, this);
ListenerInfo listenerInfo = _plugin.getProxy().getConfigurationAdapter().getListeners().iterator().next();
_listenerInfo = _plugin.getProxy().getConfigurationAdapter().getListeners().iterator().next();
_repository = new PlayerCountRepository(listenerInfo.getHost().getAddress().getHostAddress() + ":" + listenerInfo.getHost().getPort(), listenerInfo.getMaxPlayers());
_repository.initialize();
Region region = !new File("eu.dat").exists() ? Region.US : Region.EU;
_repository = ServerManager.getServerRepository(region);
}
public void run()
{
_repository.updatePlayerCountInDatabase(_plugin.getProxy().getOnlineCount());
_repository.updateBungeeStatus(new BungeeServer(_listenerInfo.getHost().getAddress().getHostAddress(), _listenerInfo.getHost().getAddress().getHostAddress(), _listenerInfo.getHost().getPort(), _plugin.getProxy().getOnlineCount(), 1250, (int) ((Runtime.getRuntime().maxMemory() - Runtime.getRuntime().freeMemory()) / 1048576), (int) (Runtime.getRuntime().maxMemory() / 1048576)), 15);
_totalPlayers = 0;
PlayerTotalData playerTotalData = _repository.retrievePlayerCount();
_totalPlayers = playerTotalData.CurrentPlayers;
for (BungeeServer server : _repository.getGlobalBungeeStatuses())
{
_totalPlayers += server.getPlayerCount();
}
}
@EventHandler

View File

@ -7,6 +7,8 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import mineplex.serverdata.Region;
public class PlayerCountRepository
{
private Connection _connection = null;
@ -14,18 +16,20 @@ public class PlayerCountRepository
private String _userName = "root";
private String _password = "tAbechAk3wR7tuTh";
private static String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS BungeeServers (id INT NOT NULL AUTO_INCREMENT, address VARCHAR(256), updated LONG, players INT, maxPlayers INT, ram INT, maxRam INT, PRIMARY KEY (id));";
private static String INSERT_PLAYER_COUNT = "INSERT INTO BungeeServers(address, updated, players, maxPlayers, ram, maxRam) values(?, now(), ?, ?, ?, ?);";
private static String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS BungeeServers (id INT NOT NULL AUTO_INCREMENT, address VARCHAR(256), updated LONG, players INT, US BOOLEAN, maxPlayers INT, ram INT, maxRam INT, PRIMARY KEY (id));";
private static String INSERT_PLAYER_COUNT = "INSERT INTO BungeeServers(address, updated, US, players, maxPlayers, ram, maxRam) values(?, now(), ?, ?, ?, ?);";
private static String UPDATE_PLAYER_COUNT = "UPDATE BungeeServers SET updated = now(), players = ?, maxPlayers = ?, ram = ?, maxRam = ? WHERE id = ?;";
private static String RETRIEVE_ID = "SELECT id FROM BungeeServers WHERE address = ?;";
private static String RETRIEVE_PLAYER_COUNT = "SELECT SUM(players) AS playerCount, SUM(maxPlayers) AS maxPlayerCount FROM BungeeServers WHERE TIME_TO_SEC(TIMEDIFF(now(), BungeeServers.updated)) < 10;";
private int _id = -1;
private Region _region;
private String _address;
private int _maxPlayers = 0;
public PlayerCountRepository(String address, int maxPlayers)
public PlayerCountRepository(Region region, String address, int maxPlayers)
{
_region = region;
_address = address;
_maxPlayers = maxPlayers;
}
@ -65,8 +69,9 @@ public class PlayerCountRepository
preparedStatementInsert.setString(1, _address);
preparedStatementInsert.setInt(2, 0);
preparedStatementInsert.setInt(3, _maxPlayers);
preparedStatementInsert.setInt(4, (int) ((Runtime.getRuntime().maxMemory() - Runtime.getRuntime().freeMemory()) / 1048576));
preparedStatementInsert.setInt(5, (int) (Runtime.getRuntime().maxMemory() / 1048576));
preparedStatementInsert.setBoolean(4, _region == Region.US);
preparedStatementInsert.setInt(5, (int) ((Runtime.getRuntime().maxMemory() - Runtime.getRuntime().freeMemory()) / 1048576));
preparedStatementInsert.setInt(6, (int) (Runtime.getRuntime().maxMemory() / 1048576));
int affectedRows = preparedStatementInsert.executeUpdate();

View File

@ -8,5 +8,6 @@
<classpathentry kind="var" path="REPO_DIR/Plugins/Libraries/gson-2.2.1.jar"/>
<classpathentry kind="var" path="REPO_DIR/Plugins/Libraries/javax.mail.jar"/>
<classpathentry combineaccessrules="false" kind="src" path="/Mineplex.Core"/>
<classpathentry combineaccessrules="false" kind="src" path="/Mineplex.ServerData"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -1,142 +0,0 @@
package mineplex.bungee;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
public class BungeeRepository
{
// Yip Yip actual IP because if null route happens we can't resolve the HOSTNAME DERP FACE DEFEK7!!! -defek7
private String _connectionString = "jdbc:mysql://db.mineplex.com:3306/BungeeServers?autoReconnect=true&failOverReadOnly=false&maxReconnects=10";
private String _userName = "root";
private String _password = "tAbechAk3wR7tuTh";
private static String CREATE_ONLINE_TABLE = "CREATE TABLE IF NOT EXISTS bungeeOnlineStatus (id INT NOT NULL AUTO_INCREMENT, address VARCHAR(40), online BOOLEAN NOT NULL DEFAULT 0, updated LONG, us BOOLEAN NOT NULL DEFAULT 1, lastOnline LONG, PRIMARY KEY (id), UNIQUE INDEX addressIndex(address));";
private static String CREATE_PLAYER_TABLE = "CREATE TABLE IF NOT EXISTS BungeeServers (id INT NOT NULL AUTO_INCREMENT, address VARCHAR(256), updated LONG, players INT, maxPlayers INT, ram INT, maxRam INT, PRIMARY KEY (id));";
private static String RETRIEVE_SERVERS_PLAYERCOUNTS = "SELECT bos.address, players, maxPlayers, BungeeServers.updated, bos.lastOnline, BungeeServers.US, now() FROM BungeeServers INNER JOIN bungeeOnlineStatus AS bos ON bos.address = BungeeServers.address WHERE TIME_TO_SEC(TIMEDIFF(now(), BungeeServers.updated)) < 15;";
public void initialize()
{
Connection connection = null;
PreparedStatement preparedStatement = null;
try
{
connection = DriverManager.getConnection(_connectionString, _userName, _password);
// Create table
preparedStatement = connection.prepareStatement(CREATE_ONLINE_TABLE);
preparedStatement.execute();
preparedStatement.close();
preparedStatement = connection.prepareStatement(CREATE_PLAYER_TABLE);
preparedStatement.execute();
}
catch (Exception exception)
{
exception.printStackTrace();
}
finally
{
if (preparedStatement != null)
{
try
{
preparedStatement.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
if (connection != null)
{
try
{
connection.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}
}
public List<BungeeServer> getBungeeServers()
{
List<BungeeServer> bungeeServers = new ArrayList<BungeeServer>();
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try
{
connection = DriverManager.getConnection(_connectionString, _userName, _password);
preparedStatement = connection.prepareStatement(RETRIEVE_SERVERS_PLAYERCOUNTS);
resultSet = preparedStatement.executeQuery();
while (resultSet.next())
{
long current = dateFormat.parse(resultSet.getString(7)).getTime();
long updated = dateFormat.parse(resultSet.getString(4)).getTime();
long lastOnline = dateFormat.parse(resultSet.getString(5)).getTime();
if (current - updated <= 15000 && current - lastOnline <= 300000)
{
BungeeServer server = new BungeeServer();
server.Address = resultSet.getString(1).split(":")[0];
server.Players = resultSet.getInt(2);
server.MaxPlayers = resultSet.getInt(3);
server.US = resultSet.getBoolean(6);
bungeeServers.add(server);
}
}
}
catch (Exception exception)
{
exception.printStackTrace();
}
finally
{
if (preparedStatement != null)
{
try
{
preparedStatement.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
if (connection != null)
{
try
{
connection.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}
return bungeeServers;
}
}

View File

@ -1,8 +1,10 @@
package mineplex.bungee;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
@ -18,10 +20,14 @@ import mineplex.bungee.api.ApiPostCall;
import mineplex.bungee.api.token.ARecord;
import mineplex.bungee.api.token.DnsRecord;
import mineplex.bungee.api.token.DomainRecords;
import mineplex.serverdata.Region;
import mineplex.serverdata.ServerManager;
import mineplex.serverdata.ServerRepository;
import mineplex.serverdata.data.BungeeServer;
public class BungeeRotator
{
private static BungeeRepository _repository = null;
private static ServerRepository _repository = null;
private static SimpleDateFormat _dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
private static Logger _logger = Logger.getLogger("BungeeRotator");
@ -56,7 +62,8 @@ public class BungeeRotator
e1.printStackTrace();
}
_repository = new BungeeRepository();
Region region = !new File("eu.dat").exists() ? Region.US : Region.EU;
_repository = ServerManager.getServerRepository(region);
BungeeSorter bungeeSorter = new BungeeSorter();
int maxRecordCount = 10;
@ -64,7 +71,7 @@ public class BungeeRotator
{
try
{
List<BungeeServer> bungeeServers = _repository.getBungeeServers();
List<BungeeServer> bungeeServers = new ArrayList<BungeeServer>(_repository.getGlobalBungeeStatuses());
HashSet<String> usServers = new HashSet<String>();
HashSet<String> euServers = new HashSet<String>();
@ -72,21 +79,21 @@ public class BungeeRotator
for (BungeeServer server : bungeeServers)
{
if (usServers.size() < maxRecordCount && server.US)
if (usServers.size() < maxRecordCount && server.getRegion() == Region.US)
{
if (usServers.size() >= 2 && server.Players > 900)
if (usServers.size() >= 2 && server.getPlayerCount() > 900)
continue;
log("SELECTED " + server.Address + " " + (server.US ? "us" : "eu") + " " + server.Players + "/" + server.MaxPlayers);
usServers.add(server.Address);
log("SELECTED " + server.getPublicAddress() + " " + (server.getRegion() == Region.US ? "us" : "eu") + " " + server.getPlayerCount() + "/" + server.getMaxPlayerCount());
usServers.add(server.getPublicAddress());
}
else if (euServers.size() < maxRecordCount && !server.US)
else if (euServers.size() < maxRecordCount && server.getRegion() != Region.US)
{
if (euServers.size() >= 2 && server.Players > 900)
if (euServers.size() >= 2 && server.getPlayerCount() > 900)
continue;
log("SELECTED " + server.Address + " " + (server.US ? "us" : "eu") + " " + server.Players + "/" + server.MaxPlayers);
euServers.add(server.Address);
log("SELECTED " + server.getPublicAddress() + " " + (server.getRegion() == Region.US ? "us" : "eu") + " " + server.getPlayerCount() + "/" + server.getMaxPlayerCount());
euServers.add(server.getPublicAddress());
}
}

View File

@ -1,9 +0,0 @@
package mineplex.bungee;
public class BungeeServer
{
public String Address;
public int Players;
public int MaxPlayers;
public boolean US;
}

View File

@ -2,14 +2,16 @@ package mineplex.bungee;
import java.util.Comparator;
import mineplex.serverdata.data.BungeeServer;
public class BungeeSorter implements Comparator<BungeeServer>
{
public int compare(BungeeServer a, BungeeServer b)
{
if (a.Players < b.Players)
if (a.getPlayerCount() < b.getPlayerCount())
return -1;
if (b.Players < a.Players)
if (b.getPlayerCount() < a.getPlayerCount())
return 1;
return 0;

View File

@ -24,8 +24,8 @@ public final class DBPool
source.setUrl(url);
source.setUsername(username);
source.setPassword(password);
source.setMaxTotal(3);
source.setMaxIdle(3);
source.setMaxTotal(5);
source.setMaxIdle(5);
source.setTimeBetweenEvictionRunsMillis(180 * 1000);
source.setSoftMinEvictableIdleTimeMillis(180 * 1000);

View File

@ -16,8 +16,8 @@ import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilTime;
import mineplex.core.party.redis.RedisPartyData;
import mineplex.serverdata.Region;
import mineplex.serverdata.ServerGroup;
import mineplex.serverdata.ServerManager;
import mineplex.serverdata.data.ServerGroup;
import mineplex.serverdata.transfers.ServerTransfer;
import mineplex.serverdata.transfers.TransferCommand;

View File

@ -23,9 +23,9 @@ import mineplex.core.common.util.UtilPlayer;
import mineplex.core.itemstack.ItemStackFactory;
import mineplex.core.recharge.Recharge;
import mineplex.serverdata.Region;
import mineplex.serverdata.ServerGroup;
import mineplex.serverdata.ServerManager;
import mineplex.serverdata.ServerRepository;
import mineplex.serverdata.data.ServerGroup;
public class PersonalServerManager extends MiniPlugin
{

View File

@ -23,11 +23,11 @@ import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilTabTitle;
import mineplex.core.portal.Commands.SendCommand;
import mineplex.core.portal.Commands.ServerCommand;
import mineplex.serverdata.MinecraftServer;
import mineplex.serverdata.Region;
import mineplex.serverdata.ServerCommandManager;
import mineplex.serverdata.ServerManager;
import mineplex.serverdata.ServerRepository;
import mineplex.serverdata.data.MinecraftServer;
import mineplex.serverdata.transfers.ServerTransfer;
import mineplex.serverdata.transfers.TransferCommand;

View File

@ -14,8 +14,8 @@ import mineplex.core.MiniPlugin;
import mineplex.core.account.CoreClientManager;
import mineplex.core.common.Rank;
import mineplex.serverdata.Region;
import mineplex.serverdata.ServerGroup;
import mineplex.serverdata.ServerManager;
import mineplex.serverdata.data.ServerGroup;
public class ServerConfiguration extends MiniPlugin
{

View File

@ -14,13 +14,13 @@ import mineplex.core.common.util.Callback;
import mineplex.core.monitor.LagMeter;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
import mineplex.serverdata.MinecraftServer;
import mineplex.serverdata.Region;
import mineplex.serverdata.ServerCommandManager;
import mineplex.serverdata.ServerGroup;
import mineplex.serverdata.ServerManager;
import mineplex.serverdata.ServerRepository;
import mineplex.serverdata.Utility;
import mineplex.serverdata.data.MinecraftServer;
import mineplex.serverdata.data.ServerGroup;
import mineplex.serverdata.transfers.SuicideCommand;
public class ServerStatusManager extends MiniPlugin

View File

@ -57,8 +57,8 @@ import mineplex.hub.queue.ui.QueueShop;
import mineplex.hub.server.ui.LobbyShop;
import mineplex.hub.server.ui.QuickShop;
import mineplex.hub.server.ui.ServerNpcShop;
import mineplex.serverdata.MinecraftServer;
import mineplex.serverdata.ServerGroup;
import mineplex.serverdata.data.MinecraftServer;
import mineplex.serverdata.data.ServerGroup;
public class ServerManager extends MiniPlugin
{

View File

@ -11,12 +11,12 @@ import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import mineplex.serverdata.ConnectionData;
import mineplex.serverdata.DataRepository;
import mineplex.serverdata.MinecraftServer;
import mineplex.serverdata.RedisDataRepository;
import mineplex.serverdata.Region;
import mineplex.serverdata.ServerManager;
import mineplex.serverdata.ServerRepository;
import mineplex.serverdata.Utility;
import mineplex.serverdata.data.MinecraftServer;
import mineplex.serverdata.transfers.ServerTransfer;
import mineplex.serverdata.transfers.TransferCommand;

View File

@ -2,6 +2,8 @@ package mineplex.serverdata;
import java.util.Comparator;
import mineplex.serverdata.data.DedicatedServer;
public class DedicatedServerSorter implements Comparator<DedicatedServer>
{
@Override

View File

@ -9,9 +9,13 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import mineplex.serverdata.data.BungeeServer;
import mineplex.serverdata.data.DedicatedServer;
import mineplex.serverdata.data.MinecraftServer;
import mineplex.serverdata.data.PlayerStatus;
import mineplex.serverdata.data.ServerGroup;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Response;
import redis.clients.jedis.Transaction;
@ -552,6 +556,311 @@ public class RedisServerRepository implements ServerRepository
return server;
}
@Override
public void updateBungeeStatus(BungeeServer serverData, int timeout)
{
Jedis jedis = _writePool.getResource();
try
{
String serializedData = Utility.serialize(serverData);
String serverName = serverData.getName();
String setKey = concatenate("bungeestatus", "minecraft", _region.toString());
String dataKey = concatenate(setKey, serverName);
long expiry = Utility.currentTimeSeconds() + timeout;
Transaction transaction = jedis.multi();
transaction.set(dataKey, serializedData);
transaction.zadd(setKey, expiry, serverName);
transaction.exec();
}
catch (JedisConnectionException exception)
{
exception.printStackTrace();
_writePool.returnBrokenResource(jedis);
jedis = null;
}
finally
{
if (jedis != null)
{
_writePool.returnResource(jedis);
}
}
}
@Override
public void removeBungeeStatus(BungeeServer serverData)
{
Jedis jedis = _writePool.getResource();
try
{
String serverName = serverData.getName();
String setKey = concatenate("bungeestatus", "minecraft", _region.toString());
String dataKey = concatenate(setKey, serverName);
Transaction transaction = jedis.multi();
transaction.del(dataKey);
transaction.zrem(setKey, serverName);
transaction.exec();
}
catch (JedisConnectionException exception)
{
exception.printStackTrace();
_writePool.returnBrokenResource(jedis);
jedis = null;
}
finally
{
if (jedis != null)
{
_writePool.returnResource(jedis);
}
}
}
@Override
public Collection<BungeeServer> getBungeeStatuses()
{
Collection<BungeeServer> servers = new HashSet<BungeeServer>();
Jedis jedis = _readPool.getResource();
try
{
String setKey = concatenate("bungeestatus", "minecraft", _region.toString());
Pipeline pipeline = jedis.pipelined();
List<Response<String>> responses = new ArrayList<Response<String>>();
for (String serverName : getActiveNames(setKey))
{
String dataKey = concatenate(setKey, serverName);
responses.add(pipeline.get(dataKey));
}
pipeline.sync();
for (Response<String> response : responses)
{
String serializedData = response.get();
BungeeServer server = Utility.deserialize(serializedData, BungeeServer.class);
if (server != null)
{
servers.add(server);
}
}
}
catch (JedisConnectionException exception)
{
exception.printStackTrace();
_readPool.returnBrokenResource(jedis);
jedis = null;
}
finally
{
if (jedis != null)
{
_readPool.returnResource(jedis);
}
}
return servers;
}
@Override
public void updatePlayerStatus(PlayerStatus serverData, int timeout)
{
Jedis jedis = _writePool.getResource();
try
{
String serializedData = Utility.serialize(serverData);
String serverName = serverData.getName();
String setKey = concatenate("playerstatus", "minecraft", _region.toString());
String dataKey = concatenate(setKey, serverName);
long expiry = Utility.currentTimeSeconds() + timeout;
Transaction transaction = jedis.multi();
transaction.set(dataKey, serializedData);
transaction.zadd(setKey, expiry, serverName);
transaction.exec();
}
catch (JedisConnectionException exception)
{
exception.printStackTrace();
_writePool.returnBrokenResource(jedis);
jedis = null;
}
finally
{
if (jedis != null)
{
_writePool.returnResource(jedis);
}
}
}
@Override
public void removePlayerStatus(PlayerStatus serverData)
{
Jedis jedis = _writePool.getResource();
try
{
String serverName = serverData.getName();
String setKey = concatenate("playerstatus", "minecraft", _region.toString());
String dataKey = concatenate(setKey, serverName);
Transaction transaction = jedis.multi();
transaction.del(dataKey);
transaction.zrem(setKey, serverName);
transaction.exec();
}
catch (JedisConnectionException exception)
{
exception.printStackTrace();
_writePool.returnBrokenResource(jedis);
jedis = null;
}
finally
{
if (jedis != null)
{
_writePool.returnResource(jedis);
}
}
}
@Override
public PlayerStatus getPlayerStatus(String playerName)
{
PlayerStatus status = null;
Jedis jedis = _readPool.getResource();
try
{
String setKey = concatenate("playerstatus", "minecraft", _region.toString());
String dataKey = concatenate(setKey, playerName);
String serializedData = jedis.get(dataKey);
status = Utility.deserialize(serializedData, PlayerStatus.class);
}
catch (JedisConnectionException exception)
{
exception.printStackTrace();
_readPool.returnBrokenResource(jedis);
jedis = null;
}
finally
{
if (jedis != null)
{
_readPool.returnResource(jedis);
}
}
return status;
}
@Override
public Collection<PlayerStatus> getPlayerStatuses()
{
Collection<PlayerStatus> servers = new HashSet<PlayerStatus>();
Jedis jedis = _readPool.getResource();
try
{
String setKey = concatenate("playerstatus", "minecraft", _region.toString());
Pipeline pipeline = jedis.pipelined();
List<Response<String>> responses = new ArrayList<Response<String>>();
for (String serverName : getActiveNames(setKey))
{
String dataKey = concatenate(setKey, serverName);
responses.add(pipeline.get(dataKey));
}
pipeline.sync();
for (Response<String> response : responses)
{
String serializedData = response.get();
PlayerStatus server = Utility.deserialize(serializedData, PlayerStatus.class);
if (server != null)
{
servers.add(server);
}
}
}
catch (JedisConnectionException exception)
{
exception.printStackTrace();
_readPool.returnBrokenResource(jedis);
jedis = null;
}
finally
{
if (jedis != null)
{
_readPool.returnResource(jedis);
}
}
return servers;
}
@Override
public Collection<BungeeServer> getGlobalBungeeStatuses()
{
Collection<BungeeServer> servers = new HashSet<BungeeServer>();
Jedis jedis = _readPool.getResource();
try
{
for (Region region : Region.values())
{
String setKey = concatenate("bungeestatus", "minecraft", region.toString());
Pipeline pipeline = jedis.pipelined();
List<Response<String>> responses = new ArrayList<Response<String>>();
for (String serverName : getActiveNames(setKey))
{
String dataKey = concatenate(setKey, serverName);
responses.add(pipeline.get(dataKey));
}
pipeline.sync();
for (Response<String> response : responses)
{
String serializedData = response.get();
BungeeServer server = Utility.deserialize(serializedData, BungeeServer.class);
server.setRegion(region);
if (server != null)
{
servers.add(server);
}
}
}
}
catch (JedisConnectionException exception)
{
exception.printStackTrace();
_readPool.returnBrokenResource(jedis);
jedis = null;
}
finally
{
if (jedis != null)
{
_readPool.returnResource(jedis);
}
}
return servers;
}
/*
* <region> = "US" or "EU"
* serverstatus.minecraft.<region>.<name> stores the JSON encoded information of an active MinecraftServer instance.

View File

@ -1,6 +1,13 @@
package mineplex.serverdata;
import java.util.Collection;
import java.util.List;
import mineplex.serverdata.data.BungeeServer;
import mineplex.serverdata.data.DedicatedServer;
import mineplex.serverdata.data.MinecraftServer;
import mineplex.serverdata.data.PlayerStatus;
import mineplex.serverdata.data.ServerGroup;
/**
* The ServerRepository is used for storing/retrieving active sessions
@ -46,6 +53,14 @@ public interface ServerRepository
*/
public void removeServerStatus(MinecraftServer serverData);
public void updateBungeeStatus(BungeeServer serverData, int timeout);
public void removeBungeeStatus(BungeeServer serverData);
public Collection<BungeeServer> getBungeeStatuses();
public void updatePlayerStatus(PlayerStatus serverData, int timeout);
public void removePlayerStatus(PlayerStatus serverData);
public Collection<PlayerStatus> getPlayerStatuses();
/**
* @param serverName - the name of the server whose existence is being checked.
* @return true, if there exists an active {@link MinecraftServer} session with a
@ -73,4 +88,8 @@ public interface ServerRepository
public void removeServerGroup(ServerGroup serverGroup);
PlayerStatus getPlayerStatus(String playerName);
public Collection<BungeeServer> getGlobalBungeeStatuses();
}

View File

@ -0,0 +1,77 @@
package mineplex.serverdata.data;
import mineplex.serverdata.Region;
public class BungeeServer
{
// The name of this server.
private String _name;
public String getName() { return _name; }
private Region _region;
public Region getRegion() { return _region; }
// The number of players currently online.
private int _playerCount;
public int getPlayerCount() { return _playerCount; }
public void incrementPlayerCount(int amount) { this._playerCount += amount; }
// The maximum number of players allowed on the server.
private int _maxPlayerCount;
public int getMaxPlayerCount() { return _maxPlayerCount; }
// The current amount of RAM allocated to the server.
private int _ram;
public int getRam() { return _ram; }
// The maximum amount of available RAM that can be allocated to the server.
private int _maxRam;
public int getMaxRam() { return _maxRam; }
// The public I.P address used by players to connect to the server.
private String _publicAddress;
public String getPublicAddress() { return _publicAddress; }
// The port the server is currently running/listening on.
private int _port;
public int getPort() { return _port; }
/**
* Class constructor
* @param name
* @param publicAddress
* @param port
* @param playerCount
* @param maxPlayerCount
* @param ram
* @param maxRam
*/
public BungeeServer(String name, String publicAddress, int port,
int playerCount, int maxPlayerCount, int ram, int maxRam)
{
_name = name;
_playerCount = playerCount;
_maxPlayerCount = maxPlayerCount;
_ram = ram;
_maxRam = maxRam;
_publicAddress = publicAddress;
_port = port;
}
/**
* @return true, if {@value _playerCount} equals 0, false otherwise.
*/
public boolean isEmpty()
{
return _playerCount == 0;
}
public void setName(String name)
{
_name = name;
}
public void setRegion(Region region)
{
_region = region;
}
}

View File

@ -0,0 +1,111 @@
package mineplex.serverdata.data;
import java.util.HashMap;
import java.util.Map;
import mineplex.serverdata.Region;
public class DedicatedServer
{
// The default amount of available CPU usage.
public static final int DEFAULT_CPU = 32;
// The default amount of available ram usage.
public static final int DEFAULT_RAM = 14000;
// The unique name representing this server
private String _name;
public String getName() { return _name; }
// The public I.P address used to connect to this server
private String _publicAddress;
public String getPublicAddress() { return _publicAddress; }
// The private I.P address of this server
private String _privateAddress;
public String getPrivateAddress() { return _privateAddress; }
// The geographical region that this dedicated server is located in
private Region _region;
public Region getRegion() { return _region; }
public boolean isUsRegion() { return _region == Region.US; }
// The amount of available CPU usage on this server box.
private int _availableCpu;
public int getAvailableCpu() { return _availableCpu; }
// The amount of available ram usage on this server box.
private int _availableRam;
public int getAvailableRam() { return _availableRam; }
// The amount of available CPU usage on this server box.
private int _maxCpu;
public int getMaxCpu() { return _maxCpu; }
// The amount of available ram usage on this server box.
private int _maxRam;
public int getMaxRam() { return _maxRam; }
// A mapping of server group names (Key) to the number of server instances (Value)
private Map<String, Integer> _serverCounts;
/**
* Class constructor
* @param data - the set of serialized data values representing
* the internal state of this DedicatedServer.
*/
public DedicatedServer(Map<String, String> data)
{
_name = data.get("name");
_publicAddress = data.get("publicAddress");
_privateAddress = data.get("privateAddress");
_region = Region.valueOf(data.get("region").toUpperCase());
_availableCpu = Integer.valueOf(data.get("cpu"));
_availableRam = Integer.valueOf(data.get("ram"));
_maxCpu = Integer.valueOf(data.get("cpu"));
_maxRam = Integer.valueOf(data.get("ram"));
_serverCounts = new HashMap<String, Integer>();
}
/**
* Set the number of {@link MinecraftServer} instances on this server
* for a specific {@link ServerGroup} type.
* @param serverGroup - the {@link ServerGroup} whose server instance count is being set.
* @param serverCount - the number of {@link MinecraftServer} instances active on this server.
*/
public void setServerCount(ServerGroup serverGroup, int serverCount)
{
if (_serverCounts.containsKey(serverGroup.getName()))
{
int currentAmount = _serverCounts.get(serverGroup.getName());
_availableCpu += serverGroup.getRequiredCpu() * currentAmount;
_availableRam += serverGroup.getRequiredRam() * currentAmount;
}
_serverCounts.put(serverGroup.getName(), serverCount);
_availableCpu -= serverGroup.getRequiredCpu() * serverCount;
_availableRam -= serverGroup.getRequiredRam() * serverCount;
}
/**
* @param serverGroup - the server group whose server count on this dedicated server is being fetched.
* @return the number of active {@link MinecraftServer}s on this dedicated server
* that belong to {@code serverGroup}.
*/
public int getServerCount(ServerGroup serverGroup)
{
String groupName = serverGroup.getName();
return _serverCounts.containsKey(groupName) ? _serverCounts.get(groupName) : 0;
}
/**
* Increment the number of {@link MinecraftServer} instances on this server
* for a specific {@link ServerGroup} type by 1.
* @param serverGroup - the {@link ServerGroup} whose server instance count is being incremented
*/
public void incrementServerCount(ServerGroup serverGroup)
{
setServerCount(serverGroup, getServerCount(serverGroup) + 1);
}
}

View File

@ -1,4 +1,4 @@
package mineplex.serverdata;
package mineplex.serverdata.data;
public class MinecraftServer
{

View File

@ -0,0 +1,23 @@
package mineplex.serverdata.data;
public class PlayerStatus
{
// The name of this server.
private String _name;
public String getName() { return _name; }
// The current message of the day (MOTD) of the server.
private String _server;
public String getServer() { return _server; }
/**
* Class constructor
* @param name
* @param server
*/
public PlayerStatus(String name, String server)
{
_name = name;
_server = server;
}
}

View File

@ -0,0 +1,353 @@
package mineplex.serverdata.data;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import mineplex.serverdata.Region;
public class ServerGroup
{
private HashMap<String, String> _dataMap = null;
private String _name;
private String _host;
private String _prefix;
private int _minPlayers;
private int _maxPlayers;
private int _requiredRam;
private int _requiredCpu;
private int _requiredTotalServers;
private int _requiredJoinableServers;
private boolean _arcadeGroup;
private String _worldZip;
private String _plugin;
private String _configPath;
private int _portSection;
private boolean _pvp;
private boolean _tournament;
private boolean _tournamentPoints;
private boolean _teamRejoin;
private boolean _teamAutoJoin;
private boolean _teamForceBalance;
private boolean _gameAutoStart;
private boolean _gameTimeout;
private boolean _rewardGems;
private boolean _rewardItems;
private boolean _rewardStats;
private boolean _rewardAchievements;
private boolean _hotbarInventory;
private boolean _hotbarHubClock;
private boolean _playerKickIdle;
private boolean _generateFreeVersions;
private String _games;
private String _serverType;
private boolean _addNoCheat;
private boolean _whitelist;
private boolean _staffOnly;
private String _resourcePack = "";
private Region _region;
private Set<MinecraftServer> _servers;
public ServerGroup(Map<String, String> data, Collection<MinecraftServer> serverStatuses)
{
_name = data.get("name");
_prefix = data.get("prefix");
_requiredRam = Integer.valueOf(data.get("ram"));
_requiredCpu = Integer.valueOf(data.get("cpu"));
_requiredTotalServers = Integer.valueOf(data.get("totalServers"));
_requiredJoinableServers = Integer.valueOf(data.get("joinableServers"));
_portSection = Integer.valueOf(data.get("portSection"));
_arcadeGroup = Boolean.valueOf(data.get("arcadeGroup"));
_worldZip = data.get("worldZip");
_plugin = data.get("plugin");
_configPath = data.get("configPath");
_minPlayers = Integer.valueOf(data.get("minPlayers"));
_maxPlayers = Integer.valueOf(data.get("maxPlayers"));
_pvp = Boolean.valueOf(data.get("pvp"));
_tournament = Boolean.valueOf(data.get("tournament"));
_tournamentPoints = Boolean.valueOf(data.get("tournamentPoints"));
_generateFreeVersions = Boolean.valueOf(data.get("generateFreeVersions"));
_games = data.get("games");
_serverType = data.get("serverType");
_addNoCheat = Boolean.valueOf(data.get("addNoCheat"));
_teamRejoin = Boolean.valueOf(data.get("teamRejoin"));
_teamAutoJoin = Boolean.valueOf(data.get("teamAutoJoin"));
_teamForceBalance = Boolean.valueOf(data.get("teamForceBalance"));
_gameAutoStart = Boolean.valueOf(data.get("gameAutoStart"));
_gameTimeout = Boolean.valueOf(data.get("gameTimeout"));
_rewardGems = Boolean.valueOf(data.get("rewardGems"));
_rewardItems = Boolean.valueOf(data.get("rewardItems"));
_rewardStats = Boolean.valueOf(data.get("rewardStats"));
_rewardAchievements = Boolean.valueOf(data.get("rewardAchievements"));
_hotbarInventory = Boolean.valueOf(data.get("hotbarInventory"));
_hotbarHubClock = Boolean.valueOf(data.get("hotbarHubClock"));
_playerKickIdle = Boolean.valueOf(data.get("playerKickIdle"));
_staffOnly = Boolean.valueOf(data.get("staffOnly"));
_whitelist = Boolean.valueOf(data.get("whitelist"));
_resourcePack = data.containsKey("resourcePack") ? data.get("resourcePack") : "";
_host = data.get("host");
_region = data.containsKey("region") ? Region.valueOf(data.get("region")) : Region.ALL;
if (serverStatuses != null)
parseServers(serverStatuses);
}
public ServerGroup(String name, String prefix, String host, int ram, int cpu, int totalServers, int joinable, int portSection, boolean arcade, String worldZip, String plugin, String configPath
, int minPlayers, int maxPlayers, boolean pvp, boolean tournament, boolean tournamentPoints, String games, String serverType, boolean noCheat, boolean teamRejoin
, boolean teamAutoJoin, boolean teamForceBalance, boolean gameAutoStart, boolean gameTimeout, boolean rewardGems, boolean rewardItems, boolean rewardStats
, boolean rewardAchievements, boolean hotbarInventory, boolean hotbarHubClock, boolean playerKickIdle, boolean staffOnly, boolean whitelist, String resourcePack, Region region)
{
_name = name;
_prefix = prefix;
_host = host;
_requiredRam = ram;
_requiredCpu = cpu;
_requiredTotalServers = totalServers;
_requiredJoinableServers = joinable;
_portSection = portSection;
_arcadeGroup = arcade;
_worldZip = worldZip;
_plugin = plugin;
_configPath = configPath;
_minPlayers = minPlayers;
_maxPlayers = maxPlayers;
_pvp = pvp;
_tournament = tournament;
_tournamentPoints = tournamentPoints;
_games = games;
_serverType = serverType;
_addNoCheat = noCheat;
_teamRejoin = teamRejoin;
_teamAutoJoin = teamAutoJoin;
_teamForceBalance = teamForceBalance;
_gameAutoStart = gameAutoStart;
_gameTimeout = gameTimeout;
_rewardGems = rewardGems;
_rewardItems = rewardItems;
_rewardStats = rewardStats;
_rewardAchievements = rewardAchievements;
_hotbarInventory = hotbarInventory;
_hotbarHubClock = hotbarHubClock;
_playerKickIdle = playerKickIdle;
_staffOnly = staffOnly;
_whitelist = whitelist;
_resourcePack = resourcePack;
_region = region;
}
public String getName() { return _name; }
public String getHost() { return _host; }
public String getPrefix() { return _prefix; }
public int getMinPlayers() { return _minPlayers; }
public int getMaxPlayers() { return _maxPlayers; }
public int getRequiredRam() { return _requiredRam; }
public int getRequiredCpu() { return _requiredCpu; }
public int getRequiredTotalServers() { return _requiredTotalServers; }
public int getRequiredJoinableServers() { return _requiredJoinableServers; }
public int getPortSection() { return _portSection; }
public boolean getArcadeGroup() { return _arcadeGroup; }
public String getWorldZip() { return _worldZip; }
public String getPlugin() { return _plugin; }
public String getConfigPath() { return _configPath; }
public boolean getPvp() { return _pvp; }
public boolean getTournament() { return _tournament; }
public boolean getTournamentPoints() { return _tournamentPoints; }
public boolean getTeamRejoin() { return _teamRejoin; }
public boolean getTeamAutoJoin() { return _teamAutoJoin; }
public boolean getTeamForceBalance() { return _teamForceBalance; }
public boolean getGameAutoStart() { return _gameAutoStart; }
public boolean getGameTimeout() { return _gameTimeout; }
public boolean getRewardGems() { return _rewardGems; }
public boolean getRewardItems() { return _rewardItems; }
public boolean getRewardStats() { return _rewardStats; }
public boolean getRewardAchievements() { return _rewardAchievements; }
public boolean getHotbarInventory() { return _hotbarInventory; }
public boolean getHotbarHubClock() { return _hotbarHubClock; }
public boolean getPlayerKickIdle() { return _playerKickIdle; }
public boolean getGenerateFreeVersions() { return _generateFreeVersions; }
public String getGames() { return _games; }
public String getServerType() { return _serverType; }
public boolean getAddNoCheat() { return _addNoCheat; }
public boolean getWhitelist() { return _whitelist; }
public boolean getStaffOnly() { return _staffOnly; }
public String getResourcePack() { return _resourcePack; }
public Region getRegion() { return _region; }
public Set<MinecraftServer> getServers() { return _servers; }
public int getServerCount()
{
return _servers.size();
}
public int getJoinableCount()
{
int joinable = 0;
for (MinecraftServer server : _servers)
{
if (server.isJoinable())
{
joinable++;
}
}
return joinable;
}
public int getPlayerCount()
{
int playerCount = 0;
for (MinecraftServer server : _servers)
{
playerCount += server.getPlayerCount();
}
return playerCount;
}
public int getMaxPlayerCount()
{
int maxPlayerCount = 0;
for (MinecraftServer server : _servers)
{
maxPlayerCount += server.getMaxPlayerCount();
}
return maxPlayerCount;
}
public Collection<MinecraftServer> getEmptyServers()
{
Collection<MinecraftServer> emptyServers = new HashSet<MinecraftServer>();
for (MinecraftServer server : _servers)
{
if (server.isEmpty() && server.getUptime() >= 150) // Only return empty servers that have been online for >150 seconds
{
emptyServers.add(server);
}
}
return emptyServers;
}
private void parseServers(Collection<MinecraftServer> servers)
{
_servers = new HashSet<MinecraftServer>();
for (MinecraftServer server : servers)
{
if (_name.equalsIgnoreCase(server.getGroup()))
{
_servers.add(server);
}
}
}
public int generateUniqueId(int startId)
{
int id = startId;
while (true)
{
boolean uniqueId = true;
for (MinecraftServer server : _servers)
{
String serverName = server.getName();
try
{
int serverNum = Integer.parseInt(serverName.split("-")[1]);
if (serverNum == id)
{
uniqueId = false;
break;
}
}
catch (Exception exception)
{
exception.printStackTrace();
}
}
if (uniqueId)
{
return id;
}
else
{
id++;
}
}
}
public HashMap<String, String> getDataMap()
{
if (_dataMap == null)
{
_dataMap = new HashMap<String, String>();
_dataMap.put("name", _name);
_dataMap.put("prefix", _prefix);
_dataMap.put("ram", _requiredRam + "");
_dataMap.put("cpu", _requiredCpu + "");
_dataMap.put("totalServers", _requiredTotalServers + "");
_dataMap.put("joinableServers", _requiredJoinableServers + "");
_dataMap.put("portSection", _portSection + "");
_dataMap.put("arcadeGroup", _arcadeGroup + "");
_dataMap.put("worldZip", _worldZip);
_dataMap.put("plugin", _plugin);
_dataMap.put("configPath", _configPath);
_dataMap.put("minPlayers", _minPlayers + "");
_dataMap.put("maxPlayers", _maxPlayers + "");
_dataMap.put("pvp", _pvp + "");
_dataMap.put("tournament", _tournament + "");
_dataMap.put("tournamentPoints", _tournamentPoints + "");
_dataMap.put("games", _games);
_dataMap.put("serverType", _serverType);
_dataMap.put("addNoCheat", _addNoCheat + "");
_dataMap.put("teamRejoin", _teamRejoin + "");
_dataMap.put("teamAutoJoin", _teamAutoJoin + "");
_dataMap.put("teamForceBalance", _teamForceBalance + "");
_dataMap.put("gameAutoStart", _gameAutoStart + "");
_dataMap.put("gameTimeout", _gameTimeout + "");
_dataMap.put("rewardGems", _rewardGems + "");
_dataMap.put("rewardItems", _rewardItems + "");
_dataMap.put("rewardStats", _rewardStats + "");
_dataMap.put("rewardAchievements", _rewardAchievements + "");
_dataMap.put("hotbarInventory", _hotbarInventory + "");
_dataMap.put("hotbarHubClock", _hotbarHubClock + "");
_dataMap.put("playerKickIdle", _playerKickIdle + "");
_dataMap.put("staffOnly", _staffOnly + "");
_dataMap.put("whitelist", _whitelist + "");
_dataMap.put("resourcePack", _resourcePack);
_dataMap.put("host", _host);
_dataMap.put("region", _region.name());
}
return _dataMap;
}
}

View File

@ -20,13 +20,13 @@ import java.util.logging.FileHandler;
import java.util.logging.Logger;
import mineplex.core.common.util.NautHashMap;
import mineplex.serverdata.DedicatedServer;
import mineplex.serverdata.DedicatedServerSorter;
import mineplex.serverdata.MinecraftServer;
import mineplex.serverdata.Region;
import mineplex.serverdata.ServerGroup;
import mineplex.serverdata.ServerManager;
import mineplex.serverdata.ServerRepository;
import mineplex.serverdata.data.DedicatedServer;
import mineplex.serverdata.data.MinecraftServer;
import mineplex.serverdata.data.ServerGroup;
import mineplex.serverdata.transfers.RestartCommand;
import mineplex.serverdata.transfers.SuicideCommand;
@ -54,6 +54,18 @@ public class ServerMonitor
public static void main (String args[])
{
/*
MinecraftPingReply data = null;
try
{
data = new MinecraftPing().getPing(new MinecraftPingOptions().setHostname("127.0.0.1").setPort(25565));
}
catch (IOException e2)
{
e2.printStackTrace();
}
System.out.println(data.getDescription() + " " + data.getPlayers().getOnline());
*/
_region = !new File("eu.dat").exists() ? Region.US : Region.EU;
_debug = new File("debug.dat").exists();
_repository = ServerManager.getServerRepository(_region); // Fetches and connects to server repo

View File

@ -2,7 +2,7 @@ package mineplex.servermonitor;
import java.util.Comparator;
import mineplex.serverdata.MinecraftServer;
import mineplex.serverdata.data.MinecraftServer;
public class ServerSorter implements Comparator<MinecraftServer>
{

View File

@ -9,9 +9,9 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import mineplex.serverdata.DedicatedServer;
import mineplex.serverdata.Region;
import mineplex.serverdata.ServerGroup;
import mineplex.serverdata.data.DedicatedServer;
import mineplex.serverdata.data.ServerGroup;
import mineplex.servermonitor.data.BungeeStatusData;
public class StatusHistoryRepository