1
0

refactor: clean source code

This commit is contained in:
labalityowo
2022-07-07 10:09:42 +07:00
parent 49950087f5
commit de68079e8a
16487 changed files with 721393 additions and 227033 deletions

BIN
Art/BlackFriday.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

BIN
Art/Carl.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 KiB

BIN
Art/ChristmasChaos.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 KiB

BIN
Art/ClansBanner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1017 KiB

BIN
Art/Halloween Horror.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 KiB

BIN
Art/Logos/AU server.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

File diff suppressed because one or more lines are too long

BIN
Art/Logos/logo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

BIN
Art/MS SMoke.psd Normal file

Binary file not shown.

BIN
Art/Pumpkin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Art/Resource Packs/hh.zip Normal file

Binary file not shown.

BIN
Art/Resource Packs/xmas.zip Normal file

Binary file not shown.

BIN
Art/Skywars/Skywars.lip Normal file

Binary file not shown.

BIN
Art/Skywars/Skywars.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

BIN
Art/Skywars/Skywars.psd Normal file

Binary file not shown.

BIN
Art/Spooky Sale.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

BIN
Art/TitanLogo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 KiB

BIN
Art/Treasure/4Qq2m6x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

BIN
Art/Treasure/canc.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

BIN
Art/Treasure/legend.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
Art/Treasure/xxiJkbb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

BIN
Art/WinterTreasure.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Art/WinterTreasureTrim.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Art/y5O7WYh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
Art/zKzkfLE.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

View File

@ -1,3 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -1,17 +0,0 @@
<component name="ArtifactManager">
<artifact type="jar" name="Mineplex.Bungee.Mineplexer:jar">
<output-path>$PROJECT_DIR$/../</output-path>
<root id="archive" name="Mineplexer.jar">
<element id="module-output" name="Mineplex.Cache" />
<element id="module-output" name="Mineplex.ServerData" />
<element id="extracted-dir" path="$PROJECT_DIR$/Libraries/gson-2.2.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/Libraries/commons-pool2-2.9.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/Libraries/jedis-2.8.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/Libraries/httpclient-4.5.2.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/Libraries/commons-dbcp2-2.0.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/Libraries/jooq-3.5.2.jar" path-in-jar="/" />
<element id="module-output" name="Mineplex.Bungee.Mineplexer" />
<element id="file-copy" path="$PROJECT_DIR$/Mineplex.Bungee.Mineplexer/plugin.yml" />
</root>
</artifact>
</component>

View File

@ -1,9 +0,0 @@
<component name="ArtifactManager">
<artifact type="jar" name="Mineplex.Cache:jar">
<output-path>$PROJECT_DIR$/out/artifacts/Mineplex_Cache_jar</output-path>
<root id="archive" name="Mineplex.Cache.jar">
<element id="module-output" name="Mineplex.Cache" />
<element id="module-output" name="Mineplex.ServerData" />
</root>
</artifact>
</component>

View File

@ -1,8 +0,0 @@
<component name="ArtifactManager">
<artifact type="jar" name="Mineplex.ServerData:jar">
<output-path>$PROJECT_DIR$/out/artifacts/Mineplex_ServerData_jar</output-path>
<root id="archive" name="Mineplex.ServerData.jar">
<element id="module-output" name="Mineplex.ServerData" />
</root>
</artifact>
</component>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8 (2)" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/Mineplex.Bungee.Mineplexer/Mineplex.Bungee.Mineplexer.iml" filepath="$PROJECT_DIR$/Mineplex.Bungee.Mineplexer/Mineplex.Bungee.Mineplexer.iml" />
<module fileurl="file://$PROJECT_DIR$/Mineplex.Cache/Mineplex.Cache.iml" filepath="$PROJECT_DIR$/Mineplex.Cache/Mineplex.Cache.iml" />
<module fileurl="file://$PROJECT_DIR$/Mineplex.ServerData/Mineplex.ServerData.iml" filepath="$PROJECT_DIR$/Mineplex.ServerData/Mineplex.ServerData.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/Mineplexer.iml" filepath="$PROJECT_DIR$/.idea/Mineplexer.iml" />
</modules>
</component>
</project>

View File

@ -1,96 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="Mineplex.Cache" />
<orderEntry type="module" module-name="Mineplex.ServerData" />
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../Libraries/Bungeecord.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../Libraries/commons-dbcp2-2.0.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../Libraries/commons-pool2-2.9.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../Libraries/craftbukkit.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$MODULE_DIR$/../Libraries/craftbukkit.jar!/" />
</SOURCES>
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../Libraries/gson-2.2.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../Libraries/httpclient-4.5.2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../Libraries/jd-gui-1.6.6.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../Libraries/jedis-2.8.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../Libraries/jooq-3.5.2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>

View File

@ -1,21 +0,0 @@
package mineplex.bungee;
import mineplex.bungee.lobbyBalancer.LobbyBalancer;
import mineplex.bungee.motd.MotdManager;
import mineplex.bungee.playerCount.PlayerCount;
import mineplex.bungee.playerStats.PlayerStats;
import mineplex.bungee.playerTracker.PlayerTracker;
import net.md_5.bungee.api.plugin.Plugin;
public class Mineplexer extends Plugin
{
@Override
public void onEnable() {
new MotdManager(this);
new LobbyBalancer(this);
new PlayerCount(this);
//new FileUpdater(this);
new PlayerStats(this);
new PlayerTracker(this);
}
}

View File

@ -1,132 +0,0 @@
package mineplex.bungee.lobbyBalancer;
import java.io.File;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import net.md_5.bungee.api.event.ServerConnectEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.event.EventHandler;
import mineplex.serverdata.Region;
import mineplex.serverdata.data.MinecraftServer;
import mineplex.serverdata.servers.ServerManager;
import mineplex.serverdata.servers.ServerRepository;
public class LobbyBalancer implements Listener, Runnable
{
private Plugin _plugin;
private ServerRepository _repository;
private final Map<LobbyType, List<MinecraftServer>> _sortedLobbyMap = new EnumMap<>(LobbyType.class);
private final Map<LobbyType, Integer> _nextIndexMap = new EnumMap<>(LobbyType.class);
private static final LobbySorter LOBBY_SORTER = new LobbySorter();
private static final Object _serverLock = new Object();
public LobbyBalancer(Plugin plugin)
{
_plugin = plugin;
Region region = !new File("eu.dat").exists() ? Region.US : Region.EU;
_repository = ServerManager.getServerRepository(region);
run();
_plugin.getProxy().getPluginManager().registerListener(_plugin, this);
_plugin.getProxy().getScheduler().schedule(_plugin, this, 500L, 500L, TimeUnit.MILLISECONDS);
}
@EventHandler
public void playerConnect(ServerConnectEvent event)
{
Arrays.stream(LobbyType.values())
.filter(type -> type.getConnectName().equalsIgnoreCase(event.getTarget().getName()))
.findFirst()
.ifPresent(lobbyType ->
{
synchronized (_serverLock)
{
List<MinecraftServer> lobbies = _sortedLobbyMap.get(lobbyType);
System.out.println(lobbies.toString());
if(lobbies.size() == 0) {
event.getPlayer().disconnect("Sorry! There aren't any servers that are currently active right now. Come back later :3");
System.out.println("NOTICE! The network doesn't have any active servers. Are we in development status?");
return;
}
int nextIndex = _nextIndexMap.getOrDefault(lobbyType, 0);
if (nextIndex >= lobbies.size())
{
nextIndex = 0;
}
MinecraftServer server = lobbies.get(nextIndex);
event.setTarget(_plugin.getProxy().getServerInfo(server.getName()));
server.incrementPlayerCount(1);
System.out.println("Sending " + event.getPlayer().getName() + " to " + server.getName() + "(" + server.getPublicAddress() + ")");
_nextIndexMap.put(lobbyType, ++nextIndex);
}
});
}
public void run()
{
loadServers();
for (LobbyType type : LobbyType.values())
{
if (!_plugin.getProxy().getServers().containsKey(type.getConnectName()))
{
_plugin.getProxy().getServers().put(type.getConnectName(), _plugin.getProxy().constructServerInfo(type.getConnectName(), new InetSocketAddress("lobby.mineplex.com", 25565), "LobbyBalancer", false));
}
}
}
public void loadServers()
{
Collection<MinecraftServer> servers = _repository.getServerStatuses();
synchronized (_serverLock)
{
long startTime = System.currentTimeMillis();
_sortedLobbyMap.clear();
for (LobbyType type : LobbyType.values())
{
_sortedLobbyMap.put(type, new ArrayList<>());
}
for (MinecraftServer server : servers)
{
if (server.getName() == null)
continue;
InetSocketAddress socketAddress = new InetSocketAddress(server.getPublicAddress(), server.getPort());
_plugin.getProxy().getServers().put(server.getName(), _plugin.getProxy().constructServerInfo(server.getName(), socketAddress, "LobbyBalancer", false));
if (server.getMotd() != null && server.getMotd().contains("Restarting"))
{
continue;
}
Arrays.stream(LobbyType.values())
.filter(type -> server.getName().toUpperCase().startsWith(type.getUppercasePrefix()))
.findFirst()
.ifPresent(type -> _sortedLobbyMap.get(type).add(server));
}
_sortedLobbyMap.values().forEach(lobbies -> Collections.sort(lobbies, LOBBY_SORTER));
long timeSpentInLock = System.currentTimeMillis() - startTime;
if (timeSpentInLock > 50)
System.out.println("[==] TIMING [==] Locked loading servers for " + timeSpentInLock + "ms");
_nextIndexMap.clear();
}
}
}

View File

@ -1,34 +0,0 @@
package mineplex.bungee.lobbyBalancer;
public enum LobbyType
{
NORMAL("LOBBY", "LOBBY-", "MainMotd"),
CLANS("ClansHub", "CLANSHUB-", "ClansMotd"),
BETA("BetaHub","BETAHUB-", "BetaMotd"),
MIN("MIN","MIN-", "MinMotd");
private final String _connectName; // The name of the server the player is connecting to
private final String _uppercasePrefix; // The (toUpperCase()) prefix given to servers of this lobby type
private final String _redisMotdKey;
LobbyType(String connectName, String uppercasePrefix, String redisMotdKey)
{
_connectName = connectName;
_uppercasePrefix = uppercasePrefix;
_redisMotdKey = redisMotdKey;
}
public String getConnectName()
{
return _connectName;
}
public String getUppercasePrefix()
{
return _uppercasePrefix;
}
public String getRedisMotdKey()
{
return _redisMotdKey;
}
}

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/motd.iml" filepath="$PROJECT_DIR$/motd.iml" />
</modules>
</component>
</project>

View File

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="bea7784e-3ad7-4932-98e1-587634f5a436" name="Default Changelist" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ProjectId" id="1sqbrMnQda6CEC49dy4Wm5DJWAn" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="bea7784e-3ad7-4932-98e1-587634f5a436" name="Default Changelist" comment="" />
<created>1621603265666</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1621603265666</updated>
</task>
<servers />
</component>
</project>

View File

@ -1,84 +0,0 @@
package mineplex.bungee.motd;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import net.md_5.bungee.api.event.ProxyPingEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.event.EventHandler;
import mineplex.bungee.lobbyBalancer.LobbyType;
import mineplex.serverdata.Region;
import mineplex.serverdata.data.DataRepository;
import mineplex.serverdata.redis.RedisDataRepository;
import mineplex.serverdata.servers.ServerManager;
public class MotdManager implements Listener, Runnable
{
private static final String DEFAULT_HEADLINE = " §b§l§m §8§l§m[ §r §9§lThieunang.club§r §f§lGames§r §8§l§m ]§b§l§m §r";
private final DataRepository<GlobalMotd> _repository;
private final Random _random = new Random();
private final Map<LobbyType, GlobalMotd> motds = new EnumMap<>(LobbyType.class);
public MotdManager(Plugin plugin)
{
plugin.getProxy().getScheduler().schedule(plugin, this, 5L, 30L, TimeUnit.SECONDS);
plugin.getProxy().getPluginManager().registerListener(plugin, this);
_repository = new RedisDataRepository<GlobalMotd>(ServerManager.getConnection(true, ServerManager.SERVER_STATUS_LABEL), ServerManager.getConnection(false, ServerManager.SERVER_STATUS_LABEL),
Region.ALL, GlobalMotd.class, "globalMotd");
run();
}
@EventHandler
public void serverPing(ProxyPingEvent event)
{
net.md_5.bungee.api.ServerPing serverPing = event.getResponse();
Optional<LobbyType> maybeType = Optional.empty();
if (event.getConnection().getListener() != null)
{
maybeType = Arrays.stream(LobbyType.values())
.filter(type -> event.getConnection().getListener().getDefaultServer().equalsIgnoreCase(type.getConnectName()))
.findFirst();
}
LobbyType lobbyType = maybeType.orElse(LobbyType.NORMAL);
GlobalMotd globalMotd = motds.get(lobbyType);
String motd = DEFAULT_HEADLINE;
if (globalMotd != null && globalMotd.getHeadline() != null)
{
motd = globalMotd.getHeadline() == null ? DEFAULT_HEADLINE : globalMotd.getHeadline();
if (globalMotd.getMotd() != null)
{
motd += "\n" + globalMotd.getMotd().get(_random.nextInt(globalMotd.getMotd().size()));
}
}
event.setResponse(new net.md_5.bungee.api.ServerPing(serverPing.getVersion(), serverPing.getPlayers(), motd, serverPing.getFaviconObject()));
}
@Override
public void run()
{
/*
for (LobbyType type : LobbyType.values())
{
GlobalMotd motd = _repository.getElement(type.getRedisMotdKey());
if (motd != null)
{
motds.put(type, motd);
}
}
*/
}
}

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -1,118 +0,0 @@
package mineplex.bungee.playerCount;
import java.io.File;
import java.util.concurrent.TimeUnit;
import mineplex.bungee.status.InternetStatus;
import mineplex.serverdata.Region;
import mineplex.serverdata.data.BungeeServer;
import mineplex.serverdata.data.DataRepository;
import mineplex.serverdata.redis.RedisDataRepository;
import mineplex.serverdata.servers.ConnectionData;
import mineplex.serverdata.servers.ConnectionData.ConnectionType;
import mineplex.serverdata.servers.ServerManager;
import net.md_5.bungee.api.ServerPing.Players;
import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.api.event.ProxyPingEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.event.EventHandler;
public class PlayerCount implements Listener, Runnable
{
private DataRepository<BungeeServer> _repository;
private DataRepository<BungeeServer> _secondRepository;
private Region _region;
private ListenerInfo _listenerInfo;
private Plugin _plugin;
private int _totalPlayers = -1;
public PlayerCount(Plugin plugin)
{
_region = !new File("eu.dat").exists() ? Region.US : Region.EU;
_plugin = plugin;
_plugin.getProxy().getScheduler().schedule(_plugin, this, 4L, 4L, TimeUnit.SECONDS);
_plugin.getProxy().getPluginManager().registerListener(_plugin, this);
for (ListenerInfo info : _plugin.getProxy().getConfigurationAdapter().getListeners())
{
if (info.getDefaultServer().equalsIgnoreCase("Lobby"))
{
_listenerInfo = info;
}
}
_repository = new RedisDataRepository<BungeeServer>(ServerManager.getConnection(true, ServerManager.SERVER_STATUS_LABEL), ServerManager.getConnection(false, ServerManager.SERVER_STATUS_LABEL),
Region.ALL, BungeeServer.class, "bungeeServers");
if (_region == Region.US)
_secondRepository = new RedisDataRepository<BungeeServer>(new ConnectionData("127.0.0.1", 6379, ConnectionType.MASTER, "ServerStatus"), new ConnectionData("127.0.0.1", 6379, ConnectionType.SLAVE, "ServerStatus"),
Region.ALL, BungeeServer.class, "bungeeServers");
else
_secondRepository = new RedisDataRepository<BungeeServer>(new ConnectionData("127.0.0.1", 6379, ConnectionType.MASTER, "ServerStatus"), new ConnectionData("127.0.0.1", 6379, ConnectionType.SLAVE, "ServerStatus"),
Region.ALL, BungeeServer.class, "bungeeServers");
}
public void run()
{
BungeeServer snapshot = generateSnapshot();
if (snapshot != null)
{
_repository.addElement(snapshot, 15); // Update with a 15 second expiry on session
}
_totalPlayers = fetchPlayerCount();
}
/**
* @return an up-to-date total player count across all active Bungee Servers.
*/
private int fetchPlayerCount()
{
int totalPlayers = 0;
for (BungeeServer server : _repository.getElements())
{
totalPlayers += server.getPlayerCount();
}
for (BungeeServer server : _secondRepository.getElements())
{
totalPlayers += server.getPlayerCount();
}
return totalPlayers;
}
/**
* @return a newly instantiated {@link BungeeServer} snapshot of the current state of this server.
*/
private BungeeServer generateSnapshot()
{
if (_listenerInfo == null)
{
return null;
}
String name = _listenerInfo.getHost().getAddress().getHostAddress();
String host = _listenerInfo.getHost().getAddress().getHostAddress();
int port = _listenerInfo.getHost().getPort();
boolean connected = InternetStatus.isConnected();
int playerCount = _plugin.getProxy().getOnlineCount();
return new BungeeServer(name, _region, host, port, playerCount, connected);
}
@EventHandler
public void ServerPing(ProxyPingEvent event)
{
net.md_5.bungee.api.ServerPing serverPing = event.getResponse();
event.setResponse(new net.md_5.bungee.api.ServerPing(serverPing.getVersion(), new Players(_totalPlayers + 1, _totalPlayers, null), serverPing.getDescription(), serverPing.getFaviconObject()));
}
public int getTotalPlayers()
{
return _totalPlayers;
}
}

View File

@ -1,146 +0,0 @@
package mineplex.bungee.playerStats;
import java.util.HashSet;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import mineplex.bungee.playerStats.data.IpInfo;
import mineplex.cache.player.PlayerCache;
import mineplex.cache.player.PlayerInfo;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.event.EventHandler;
public class PlayerStats implements Listener, Runnable
{
private Plugin _plugin;
private PlayerStatsRepository _repository;
private HashSet<UUID> _retrievingPlayerInfo = new HashSet<UUID>();
public PlayerStats(Plugin plugin)
{
_plugin = plugin;
_plugin.getProxy().getScheduler().schedule(_plugin, this, 5L, 5L, TimeUnit.MINUTES);
_plugin.getProxy().getPluginManager().registerListener(_plugin, this);
_repository = new PlayerStatsRepository();
}
@EventHandler
public void playerConnect(final PostLoginEvent event)
{
_plugin.getProxy().getScheduler().runAsync(_plugin, new Runnable()
{
public void run()
{
String address = event.getPlayer().getPendingConnection().getAddress().getAddress().getHostAddress();
UUID uuid = event.getPlayer().getUniqueId();
String name = event.getPlayer().getName();
int version = event.getPlayer().getPendingConnection().getVersion();
try
{
PlayerInfo playerInfo = null;
IpInfo ipInfo = _repository.getIp(address);
boolean addOrUpdatePlayer = false;
playerInfo = PlayerCache.getInstance().getPlayer(uuid);
if (playerInfo == null)
{
addOrUpdatePlayer = true;
_retrievingPlayerInfo.add(uuid);
}
if (!addOrUpdatePlayer)
{
if (playerInfo.getVersion() != version)
addOrUpdatePlayer = true;
else if (!playerInfo.getName().equalsIgnoreCase(name))
addOrUpdatePlayer = true;
}
if (addOrUpdatePlayer)
{
// Just update? what about other properties?
PlayerInfo updatedPlayerInfo = _repository.getPlayer(uuid, name, version);
if (playerInfo != null)
{
playerInfo.setName(updatedPlayerInfo.getName());
playerInfo.setVersion(updatedPlayerInfo.getVersion());
}
else
playerInfo = updatedPlayerInfo;
}
playerInfo.setSessionId(_repository.updatePlayerStats(playerInfo.getId(), ipInfo.id));
playerInfo.updateLoginTime();
PlayerCache.getInstance().addPlayer(playerInfo);
}
finally
{
_retrievingPlayerInfo.remove(uuid);
}
}
});
}
@EventHandler
public void playerDisconnect(final PlayerDisconnectEvent event)
{
_plugin.getProxy().getScheduler().runAsync(_plugin, new Runnable()
{
public void run()
{
UUID uuid = event.getPlayer().getUniqueId();
PlayerInfo playerInfo = null;
playerInfo = PlayerCache.getInstance().getPlayer(uuid);
int timeout = 5;
while (playerInfo == null && _retrievingPlayerInfo.contains(uuid) && timeout <= 5)
{
playerInfo = PlayerCache.getInstance().getPlayer(uuid);
if (playerInfo != null)
break;
System.out.println("ERROR - Player disconnecting and isn't in cache... sleeping");
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
timeout++;
}
if(playerInfo == null){
System.out.println("playerInfo is null, did the player even join the server before left?");
return;
}
System.out.println(playerInfo.getName() + ":" + playerInfo.getSessionId());
_repository.updatePlayerSession(playerInfo.getSessionId());
}
});
}
@Override
public void run()
{
PlayerCache.getInstance().clean();
}
}

View File

@ -1,106 +0,0 @@
package mineplex.bungee.playerTracker;
import java.util.List;
import java.util.UUID;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import mineplex.serverdata.Region;
import mineplex.serverdata.commands.PlayerJoinCommand;
import mineplex.serverdata.commands.ServerCommandManager;
import mineplex.serverdata.data.DataRepository;
import mineplex.serverdata.data.PlayerStatus;
import mineplex.serverdata.redis.RedisDataRepository;
import mineplex.serverdata.servers.ServerManager;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.event.ServerConnectedEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.event.EventHandler;
public class PlayerTracker implements Listener
{
private static final int DEFAULT_STATUS_TIMEOUT = 60 * 60 * 8;
private DataRepository<PlayerStatus> _repository;
private Plugin _plugin;
private final List<UUID> _ignoreKick = Lists.newArrayList();
public PlayerTracker(Plugin plugin)
{
_plugin = plugin;
_plugin.getProxy().getPluginManager().registerListener(_plugin, this);
_repository = new RedisDataRepository<PlayerStatus>(ServerManager.getMasterConnection(), ServerManager.getSlaveConnection(),
Region.currentRegion(), PlayerStatus.class, "playerStatus");
ServerCommandManager.getInstance().initializeServer("BUNGEE ENABLE - " + System.currentTimeMillis(), new Gson());
ServerCommandManager.getInstance().registerCommandType(mineplex.serverdata.commands.PlayerJoinCommand.class, new PlayerJoinHandler(this));
System.out.println("Initialized PlayerTracker.");
}
public Plugin getPlugin()
{
return _plugin;
}
@EventHandler
public void playerConnect(final ServerConnectedEvent event)
{
_plugin.getProxy().getScheduler().runAsync(_plugin, new Runnable()
{
public void run()
{
PlayerStatus snapshot = new PlayerStatus(event.getPlayer().getUniqueId(), event.getPlayer().getName(), event.getServer().getInfo().getName());
_repository.addElement(snapshot, DEFAULT_STATUS_TIMEOUT);
}
});
}
@EventHandler
public void playerDisconnect(final PlayerDisconnectEvent event)
{
_plugin.getProxy().getScheduler().runAsync(_plugin, new Runnable()
{
public void run()
{
_repository.removeElement(event.getPlayer().getUniqueId().toString());
}
});
}
@EventHandler
public void playerConnect(final PostLoginEvent event)
{
_ignoreKick.add(event.getPlayer().getUniqueId());
PlayerJoinCommand command = new PlayerJoinCommand(event.getPlayer().getUniqueId(), event.getPlayer().getName());
command.publish();
}
public boolean isPlayerOnline(UUID uuid)
{
return _plugin.getProxy().getPlayer(uuid) != null;
}
public void kickPlayerIfOnline(UUID uuid)
{
if (_ignoreKick.remove(uuid))
{
return;
}
if (isPlayerOnline(uuid))
{
ProxiedPlayer player = _plugin.getProxy().getPlayer(uuid);
player.disconnect(new TextComponent("You have logged in from another location."));
}
}
}

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="Mineplex.ServerData" />
</component>
</module>

View File

@ -1,110 +0,0 @@
package mineplex.cache.player;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import mineplex.serverdata.Region;
import mineplex.serverdata.redis.RedisDataRepository;
import mineplex.serverdata.redis.atomic.RedisStringRepository;
import mineplex.serverdata.servers.ServerManager;
public enum PlayerCache
{
INSTANCE;
public static PlayerCache getInstance()
{
return INSTANCE;
}
private final RedisDataRepository<PlayerInfo> _playerInfoRepository;
private final RedisStringRepository _accountIdRepository;
PlayerCache()
{
_playerInfoRepository = new RedisDataRepository<PlayerInfo>(
ServerManager.getMasterConnection(),
ServerManager.getSlaveConnection(),
Region.ALL,
PlayerInfo.class,
"playercache");
_accountIdRepository = new RedisStringRepository(
ServerManager.getMasterConnection(),
ServerManager.getSlaveConnection(),
Region.ALL,
"accountid",
(int) TimeUnit.HOURS.toSeconds(6)
);
}
public void addPlayer(PlayerInfo player)
{
try
{
_playerInfoRepository.addElement(player, 60 * 60 * 6); // 6 Hours
}
catch (Exception exception)
{
System.out.println("Error adding player info in PlayerCache : " + exception.getMessage());
exception.printStackTrace();
}
}
public PlayerInfo getPlayer(UUID uuid)
{
try
{
return _playerInfoRepository.getElement(uuid.toString());
}
catch (Exception exception)
{
System.out.println("Error retrieving player info in PlayerCache : " + exception.getMessage());
exception.printStackTrace();
}
return null;
}
/**
* Attempts to grab a player's account ID from the cache
*
* @param uuid Minecraft Account UUID
* @return The account id of the player, or -1 if the player is not in the cache
*/
public int getAccountId(UUID uuid)
{
String accountIdStr = _accountIdRepository.get(uuid.toString());
if (accountIdStr == null)
return -1;
try
{
int accountId = Integer.parseInt(accountIdStr);
if (accountId <= 0)
{
// remove invalid account id
_accountIdRepository.del(uuid.toString());
return -1;
}
return accountId;
}
catch (NumberFormatException ex)
{
// remove invalid account id
_accountIdRepository.del(uuid.toString());
return -1;
}
}
public void updateAccountId(UUID uuid, int newId)
{
_accountIdRepository.set(uuid.toString(), String.valueOf(newId));
}
public void clean()
{
_playerInfoRepository.clean();
}
}

View File

@ -1,56 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../Libraries/Bungeecord.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../Libraries/jedis-2.8.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../Libraries/commons-dbcp2-2.0.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../Libraries/jooq-3.5.2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../Libraries/commons-pool2-2.9.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>

View File

@ -1,195 +0,0 @@
package mineplex.serverdata;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import com.google.gson.Gson;
import mineplex.serverdata.servers.ConnectionData;
import mineplex.serverdata.servers.ServerManager;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.api.plugin.Plugin;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* Utility offers various necessary utility-based methods for use in Mineplex.ServerData.
* @author Ty
*
*/
public class Utility
{
private static boolean _retrievedRedisTime = false;
private static long _millisTimeDifference;
// The Gson instance used to serialize/deserialize objects in JSON form.
private static Gson _gson = new Gson();
public static Gson getGson() { return _gson; }
// map of all instantiated connection pools, distinguished by their ip:port combination
private static final ConcurrentHashMap<String, JedisPool> _pools = new ConcurrentHashMap<String, JedisPool>();
// Public static jedis pool for interacting with central default jedis repo.
private static JedisPool _masterPool;
private static JedisPool _slavePool;
private static final Object _poolLock = new Object();
/**
* @param object - the (non-null) object to serialize
* @return the serialized form of {@code object}.
*/
public static String serialize(Object object)
{
return _gson.toJson(object);
}
/**
* @param serializedData - the serialized data to be deserialized
* @param type - the resulting class type of the object to be deserialized
* @return the deserialized form of {@code serializedData} for class {@code type}.
*/
public static <T> T deserialize(String serializedData, Class<T> type)
{
if (serializedData == null) return null;
return _gson.fromJson(serializedData, type);
}
/**
* @param delimiter - the delimiter character used to separate the concatenated elements
* @param elements - the set of string elements to be concatenated and returned.
* @return the concatenated string of all {@code elements} separated by the {@code delimiter}.
*/
public static String concatenate(char delimiter, String... elements)
{
int length = elements.length;
String result = length > 0 ? elements[0] : new String();
for (int i = 1; i < length; i++)
{
result += delimiter + elements[i];
}
return result;
}
/**
* @return the current timestamp (in seconds) fetched from the central jedis repository
* for synced timestamps.
*/
public static long currentTimeSeconds()
{
if (!_retrievedRedisTime)
setTimeDifference();
return (System.currentTimeMillis() + _millisTimeDifference) / 1000;
}
/**
* @return the current timestamp (in milliseconds) fetched from the central jedis repository
* for synced timestamps.
*/
public static long currentTimeMillis()
{
if (!_retrievedRedisTime)
setTimeDifference();
return System.currentTimeMillis() + _millisTimeDifference;
}
/**
* @param connData - the connection data specifying the database to be connected to.
* @return a newly instantiated {@link JedisPool} connected to the provided {@link ConnectionData} repository.
*/
public static JedisPool generatePool(ConnectionData connData)
{
synchronized(_poolLock)
{
String key = "127.0.0.1:6379";
if(connData != null){
key = getConnKey(connData);
}
JedisPool pool = _pools.get(key);
if (pool == null)
{
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxWaitMillis(1000);
jedisPoolConfig.setMinIdle(5);
jedisPoolConfig.setTestOnBorrow(true);
jedisPoolConfig.setMaxTotal(20);
jedisPoolConfig.setBlockWhenExhausted(true);
if(connData != null){
pool = new JedisPool(jedisPoolConfig, connData.getHost(), connData.getPort());
}else{
pool = new JedisPool(jedisPoolConfig, "127.0.0.1", 6379);
}
_pools.put(key, pool);
}
return pool;
}
}
/**
* @param writeable - whether or not the Jedis connections returned should be writeable to.
* @return a globally available {@link JedisPool}
*/
public static JedisPool getPool(boolean writeable)
{
if (writeable)
{
if (_masterPool == null)
{
_masterPool = generatePool(ServerManager.getMasterConnection());
}
return _masterPool;
}
else
{
if (_slavePool == null)
{
ConnectionData slave = ServerManager.getSlaveConnection();
_slavePool = generatePool(slave);
}
return _slavePool;
}
}
private static String getConnKey(ConnectionData connData)
{
return connData.getHost() + ":" + connData.getPort();
}
private static void setTimeDifference()
{
long currentTime = 0;
JedisPool pool = getPool(false);
try (Jedis jedis = pool.getResource())
{
// Try multiple times in case one isn't valid
// Addresses an error in sentry
List<String> times = jedis.time();
for (String time : times.subList(0, Math.min(5, times.size())))
{
try
{
currentTime = Long.parseLong(time);
break;
} catch (NumberFormatException ex) { }
}
}
_millisTimeDifference = (currentTime * 1000) - System.currentTimeMillis();
}
}

View File

@ -1,132 +0,0 @@
package mineplex.serverdata.data;
public class MinecraftServer
{
// The name of this server.
private String _name;
public String getName() { return _name; }
// The ServerGroup that this MinecraftServer belongs to.
private String _group;
public String getGroup() { return _group; }
// The current message of the day (MOTD) of the server.
private String _motd;
public String getMotd() { return _motd; }
// 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 ticks per second (TPS) of the server.
private int _tps;
public int getTps() { return _tps; }
// 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; }
private int _donorsOnline;
public int getDonorsOnline() { return _donorsOnline; }
private long _startUpDate;
private long _currentTime;
public long getCurrentTime()
{
return this._currentTime;
}
/**
* Class constructor
* @param name
* @param group
* @param motd
* @param publicAddress
* @param port
* @param playerCount
* @param maxPlayerCount
* @param tps
* @param ram
* @param maxRam
*/
public MinecraftServer(String name, String group, String motd, String publicAddress, int port,
int playerCount, int maxPlayerCount, int tps, int ram, int maxRam, long startUpDate, int donorsOnline)
{
_name = name;
_group = group;
_motd = motd;
_playerCount = playerCount;
_maxPlayerCount = maxPlayerCount;
_tps = tps;
_ram = ram;
_maxRam = maxRam;
_publicAddress = publicAddress;
_port = port;
_donorsOnline = donorsOnline;
_startUpDate = startUpDate;
_currentTime = System.currentTimeMillis();
}
public boolean isEmpty()
{
return _playerCount == 0;
}
/**
* @return the amount of time (in seconds) that this {@link MinecraftServer} has been online for.
*/
public double getUptime()
{
return (System.currentTimeMillis() / 1000d - _startUpDate);
}
/**
* @return true, if this server is currently joinable by players, false otherwise.
*/
public boolean isJoinable()
{
if (_motd == null)
{
return false;
}
// This is super dodgy, this is the only way around monitor not killing game servers with the new MOTD system
if (_motd.isEmpty() || _motd.contains("VOTING") || _motd.contains("STARTING") || _motd.contains("WAITING") || _motd.contains("ALWAYS_OPEN"))
{
if (_playerCount < _maxPlayerCount)
{
int availableSlots = _maxPlayerCount - _playerCount;
return !_motd.isEmpty() || (availableSlots > 20);
}
}
return false;
}
public void setGroup(String group)
{
_group = group;
}
public void setName(String name)
{
_name = name;
}
}

View File

@ -1,179 +0,0 @@
package mineplex.serverdata.database;
import javax.sql.DataSource;
import java.io.File;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.sql.Connection;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.dbcp2.BasicDataSource;
public final class DBPool
{
private static DataSource ACCOUNT;
private static DataSource QUEUE;
private static DataSource MINEPLEX;
private static DataSource MINEPLEX_STATS;
private static DataSource PLAYER_STATS;
private static DataSource SERVER_STATS;
private static DataSource MSSQL_MOCK;
private static DataSource openDataSource(String url, String username, String password)
{
BasicDataSource source = new BasicDataSource();
source.addConnectionProperty("autoReconnect", "true");
source.addConnectionProperty("allowMultiQueries", "true");
source.addConnectionProperty("zeroDateTimeBehavior", "convertToNull");
source.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
source.setDriverClassName("com.mysql.jdbc.Driver");
source.setUrl(url);
source.setUsername(username);
source.setPassword(password);
source.setMaxTotal(5);
source.setMaxIdle(5);
source.setTimeBetweenEvictionRunsMillis(180 * 1000);
source.setSoftMinEvictableIdleTimeMillis(180 * 1000);
return source;
}
public static DataSource getMssqlMock()
{
if (MSSQL_MOCK == null)
loadDataSources();
return MSSQL_MOCK;
}
public static DataSource getAccount()
{
if (ACCOUNT == null)
loadDataSources();
return ACCOUNT;
}
public static DataSource getQueue()
{
if (QUEUE == null)
loadDataSources();
return QUEUE;
}
public static DataSource getMineplex()
{
if (MINEPLEX == null)
loadDataSources();
return MINEPLEX;
}
public static DataSource getMineplexStats()
{
if (MINEPLEX_STATS == null)
loadDataSources();
return MINEPLEX_STATS;
}
public static DataSource getPlayerStats()
{
if (PLAYER_STATS == null)
loadDataSources();
return PLAYER_STATS;
}
public static DataSource getServerStats()
{
if (SERVER_STATS == null)
loadDataSources();
return SERVER_STATS;
}
private static void loadDataSources()
{
try
{
File configFile = new File("database-config.dat");
if (configFile.exists())
{
List<String> lines = Files.readAllLines(configFile.toPath(), Charset.defaultCharset());
for (String line : lines)
{
deserializeConnection(line);
}
}
else
{
System.out.println("database-config.dat not found at " + configFile.toPath().toString());
}
}
catch (Exception exception)
{
exception.printStackTrace();
System.out.println("---Unable To Parse DBPOOL Configuration File---");
}
}
private static void deserializeConnection(String line)
{
String[] args = line.split(" ");
if (args.length == 3)
{
String dbHost = args[0];
String userName = args[1];
String password = args[2];
ACCOUNT = openDataSource("jdbc:mysql://" + dbHost + "/account", userName, password);
QUEUE = openDataSource("jdbc:mysql://" + dbHost + "/queue", userName, password);
MINEPLEX = openDataSource("jdbc:mysql://" + dbHost + "/mineplex", userName, password);
MINEPLEX_STATS = openDataSource("jdbc:mysql://" + dbHost + "/mineplex_stats", userName, password);
PLAYER_STATS = openDataSource("jdbc:mysql://" + dbHost + "/player_stats", userName, password);
SERVER_STATS = openDataSource("jdbc:mysql://" + dbHost + "/server_stats", userName, password);
}
/*
String[] args = line.split(" ");
if (args.length == 4)
{
String dbHost = args[0];
String userName = args[1];
String password = args[2];
System.out.println(userName.toString());
System.out.println(dbHost.toString());
System.out.println(password.toString());
ACCOUNT = openDataSource("jdbc:mysql://" + dbHost, userName, password);
QUEUE = openDataSource("jdbc:mysql://" + dbHost, userName, password);
MINEPLEX = openDataSource("jdbc:mysql://" + dbHost, userName, password);
MINEPLEX_STATS = openDataSource("jdbc:mysql://" + dbHost, userName, password);
PLAYER_STATS = openDataSource("jdbc:mysql://" + dbHost, userName, password);
SERVER_STATS = openDataSource("jdbc:mysql://" + dbHost, userName, password);
MSSQL_MOCK = openDataSource("jdbc:mysql://" + dbHost, userName, password);
if (dbSource.toUpperCase().equalsIgnoreCase("ACCOUNT"))
ACCOUNT = openDataSource("jdbc:mysql://" + dbHost, userName, password);
else if (dbSource.toUpperCase().equalsIgnoreCase("QUEUE"))
QUEUE = openDataSource("jdbc:mysql://" + dbHost, userName, password);
else if (dbSource.toUpperCase().equalsIgnoreCase("MINEPLEX"))
MINEPLEX = openDataSource("jdbc:mysql://" + dbHost, userName, password);
else if (dbSource.toUpperCase().equalsIgnoreCase("MINEPLEX_STATS"))
MINEPLEX_STATS = openDataSource("jdbc:mysql://" + dbHost, userName, password);
else if (dbSource.toUpperCase().equalsIgnoreCase("PLAYER_STATS"))
PLAYER_STATS = openDataSource("jdbc:mysql://" + dbHost, userName, password);
else if (dbSource.toUpperCase().equalsIgnoreCase("SERVER_STATS"))
SERVER_STATS = openDataSource("jdbc:mysql://" + dbHost, userName, password);
else if (dbSource.toUpperCase().equalsIgnoreCase("MSSQL_MOCK"))
MSSQL_MOCK = openDataSource("jdbc:mysql://" + dbHost, userName, password);
}
*/
}
}

View File

@ -1,392 +0,0 @@
package mineplex.serverdata.redis;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import mineplex.serverdata.Region;
import mineplex.serverdata.Utility;
import mineplex.serverdata.data.DedicatedServer;
import mineplex.serverdata.data.MinecraftServer;
import mineplex.serverdata.data.ServerGroup;
import mineplex.serverdata.servers.ConnectionData;
import mineplex.serverdata.servers.ServerRepository;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Response;
import redis.clients.jedis.Transaction;
import redis.clients.jedis.Tuple;
import redis.clients.jedis.exceptions.JedisConnectionException;
/**
* RedisServerRepository offers a Redis-based implementation of {@link ServerRepository}
* using a mixture of hash and JSON encoded storage.
* @author Ty
*
*/
public class RedisServerRepository extends RedisRepository implements ServerRepository
{
public RedisServerRepository(ConnectionData writeConn, ConnectionData readConn, Region region)
{
super(writeConn, readConn, region);
}
@Override
public Collection<MinecraftServer> getServerStatuses()
{
return getServerStatusesByPrefix("");
}
@Override
public Collection<MinecraftServer> getServerStatusesByPrefix(String prefix)
{
Collection<MinecraftServer> servers = new HashSet<MinecraftServer>();
try(Jedis jedis = getResource(false))
{
String setKey = concatenate("serverstatus", "minecraft", getRegion().toString());
Pipeline pipeline = jedis.pipelined();
List<Response<String>> responses = new ArrayList<Response<String>>();
for (String serverName : getActiveNames(setKey))
{
if (prefix.isEmpty() || serverName.startsWith(prefix))
{
String dataKey = concatenate(setKey, serverName);
responses.add(pipeline.get(dataKey));
}
}
pipeline.sync();
for (Response<String> response : responses)
{
String serializedData = response.get();
MinecraftServer server = Utility.deserialize(serializedData, MinecraftServer.class);
if (server != null)
{
servers.add(server);
}
}
}
return servers;
}
@Override
public Collection<MinecraftServer> getServersByGroup(String serverGroup)
{
Collection<MinecraftServer> servers = new HashSet<MinecraftServer>();
for (MinecraftServer server : getServerStatuses())
{
if (server.getGroup().equalsIgnoreCase(serverGroup))
{
servers.add(server);
}
}
return servers;
}
@Override
public MinecraftServer getServerStatus(String serverName)
{
MinecraftServer server = null;
try(Jedis jedis = getResource(false))
{
String setKey = concatenate("serverstatus", "minecraft", getRegion().toString());
String dataKey = concatenate(setKey, serverName);
String serializedData = jedis.get(dataKey);
server = Utility.deserialize(serializedData, MinecraftServer.class);
}
return server;
}
@Override
public void updataServerStatus(MinecraftServer serverData, int timeout)
{
try(Jedis jedis = getResource(true))
{
String serializedData = Utility.serialize(serverData);
String serverName = serverData.getName();
String setKey = concatenate("serverstatus", "minecraft", getRegion().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();
}
}
@Override
public void removeServerStatus(MinecraftServer serverData)
{
try(Jedis jedis = getResource(true))
{
String serverName = serverData.getName();
String setKey = concatenate("serverstatus", "minecraft", getRegion().toString());
String dataKey = concatenate(setKey, serverName);
Transaction transaction = jedis.multi();
transaction.del(dataKey);
transaction.zrem(setKey, serverName);
transaction.exec();
}
}
@Override
public boolean serverExists(String serverName)
{
return getServerStatus(serverName) != null;
}
@Override
public Collection<DedicatedServer> getDedicatedServers()
{
Collection<DedicatedServer> servers = new HashSet<DedicatedServer>();
try(Jedis jedis = getResource(false))
{
String key = concatenate("serverstatus", "dedicated");
Set<String> serverNames = jedis.smembers(key);
HashMap<String, Response<Map<String, String>>> serverDatas = new HashMap<String, Response<Map<String, String>>>();
Pipeline pipeline = jedis.pipelined();
for (String serverName : serverNames)
{
String dataKey = concatenate(key, serverName);
serverDatas.put(serverName, pipeline.hgetAll(dataKey));
}
pipeline.sync();
for (Entry<String, Response<Map<String, String>>> responseEntry : serverDatas.entrySet())
{
Map<String, String> data = responseEntry.getValue().get();
try
{
DedicatedServer server = new DedicatedServer(data);
if (server.getRegion() == getRegion())
servers.add(server);
}
catch (Exception ex)
{
System.out.println(responseEntry.getKey() + " Errored");
throw ex;
}
}
}
return servers;
}
@Override
public Collection<ServerGroup> getServerGroups(Collection<MinecraftServer> serverStatuses)
{
Collection<ServerGroup> servers = new HashSet<ServerGroup>();
try(Jedis jedis = getResource(false))
{
String key = "servergroups";
Set<String> names = jedis.smembers(key);
Set<Response<Map<String, String>>> serverDatas = new HashSet<Response<Map<String, String>>>();
Pipeline pipeline = jedis.pipelined();
for (String serverName : names)
{
String dataKey = concatenate(key, serverName);
serverDatas.add(pipeline.hgetAll(dataKey));
}
pipeline.sync();
for (Response<Map<String, String>> response : serverDatas)
{
Map<String, String> data = response.get();
if (data.entrySet().size() == 0)
{
// please no
// System.out.println("Encountered empty map! Skipping...");
continue;
}
try
{
ServerGroup serverGroup = new ServerGroup(data, serverStatuses);
if (serverGroup.getRegion() == Region.ALL || serverGroup.getRegion() == getRegion())
servers.add(serverGroup);
}
catch (Exception exception)
{
System.out.println("Error parsing ServerGroup : " + data.get("name"));
exception.printStackTrace();
}
}
}
return servers;
}
/**
* @param key - the key where the sorted set of server sessions is stored
* @return the {@link Set} of active server names stored at {@code key} for non-expired
* servers.
*/
protected Set<String> getActiveNames(String key)
{
Set<String> names = new HashSet<String>();
try(Jedis jedis = getResource(false))
{
String min = "(" + Utility.currentTimeSeconds();
String max = "+inf";
names = jedis.zrangeByScore(key, min, max);
}
return names;
}
/**
* @param key - the key where the sorted set of server sessions is stored
* @return the {@link Set} of dead (expired) server names stored at {@code key}.
*/
protected Set<String> getDeadNames(String key)
{
Set<String> names = new HashSet<String>();
try(Jedis jedis = getResource(false))
{
String min = "-inf";
String max = Utility.currentTimeSeconds() + "";
names = jedis.zrangeByScore(key, min, max);
}
return names;
}
@Override
public Collection<MinecraftServer> getDeadServers()
{
Set<MinecraftServer> servers = new HashSet<MinecraftServer>();
try(Jedis jedis = getResource(false))
{
Pipeline pipeline = jedis.pipelined();
String setKey = concatenate("serverstatus", "minecraft", getRegion().toString());
String min = "-inf";
String max = Utility.currentTimeSeconds() + "";
List<Response<String>> responses = new ArrayList<Response<String>>();
for (Tuple serverName : jedis.zrangeByScoreWithScores(setKey, min, max))
{
String dataKey = concatenate(setKey, serverName.getElement());
responses.add(pipeline.get(dataKey));
}
pipeline.sync();
for (Response<String> response : responses)
{
String serializedData = response.get();
MinecraftServer server = Utility.deserialize(serializedData, MinecraftServer.class);
if (server != null)
servers.add(server);
}
}
return servers;
}
@Override
public void updateServerGroup(ServerGroup serverGroup)
{
try(Jedis jedis = getResource(true))
{
HashMap<String, String> serializedData = serverGroup.getDataMap();
String serverGroupName = serverGroup.getName();
String key = "servergroups";
String dataKey = concatenate(key, serverGroupName);
Transaction transaction = jedis.multi();
transaction.hmset(dataKey, serializedData);
transaction.sadd(key, serverGroupName);
transaction.exec();
}
}
@Override
public void removeServerGroup(ServerGroup serverGroup)
{
try(Jedis jedis = getResource(true))
{
String serverName = serverGroup.getName();
String setKey = "servergroups";
String dataKey = concatenate(setKey, serverName);
Transaction transaction = jedis.multi();
transaction.del(dataKey);
transaction.srem(setKey, serverName);
transaction.exec();
}
}
@Override
public ServerGroup getServerGroup(String serverGroup)
{
ServerGroup server = null;
try(Jedis jedis = getResource(false))
{
String key = concatenate("servergroups", serverGroup);
Map<String, String> data = jedis.hgetAll(key);
server = new ServerGroup(data, null);
}
return server;
}
/*
* <region> = "US" or "EU"
* serverstatus.minecraft.<region>.<name> stores the JSON encoded information of an active MinecraftServer instance.
* serverstatus.minecraft.<region> stores a sorted set with the set of name's for MinecraftServers
* with a value of their expiry date (in ms)
*
* -----------------------
*
* serverstatus.dedicated.<name> stores the hash containing information of an active dedicated server instance
* serverstatus.dedicated stores the set of active dedicated server names.
* serverstatus.dedicated uses a hash with the following keys:
* name, publicAddress, privateAddress, region, cpu, ram
*
* Example commands for adding/creating a new dedicated server:
* 1. HMSET serverstatus.dedicated.<name> name <?> publicAddress <?> privateAddress <?> region <?> cpu <?> ram <?>
* 2. SADD serverstatus.dedicated <name>
*
* ------------------------
*
* servergroups.<name> stores the hash-set containing information for the server group type.
* servergroups stores the set of active server group names.
* servergroups.<name> stores a hash of the following key name/values
* name, prefix, scriptName, ram, cpu, totalServers, joinableServers
*
* Example commands for adding/creating a new server group:
*
* 1. HMSET servergroups.<name> name <?> prefix <?> scriptName <?> ram <?> cpu <?> totalServers <?> joinableServers <?>
* 2. SADD servergroups <name>
*/
}

View File

@ -1,54 +0,0 @@
package mineplex.serverdata.servers;
/**
* ConnectionData stores information relevant for initiating a connection to a repository.
* @author MrTwiggy
*
*/
public class ConnectionData
{
public enum ConnectionType
{
MASTER,
SLAVE;
}
private ConnectionType _type; // The type of connection available
public ConnectionType getType() { return _type; }
private String _name; // The name associated with this connection
public String getName() { return _name; }
private String _host; // The host URL to connect to repository
public String getHost() { return _host; }
private int _port; // The port to connect to repository
public int getPort() { return _port; }
/**
* Constructor
* @param host - the host URL defining the repository
* @param port - the port used for connection to repository
* @param type - the type of connection referenced by this ConnectionData
* @param name - the name associated with ConnectionData
*/
public ConnectionData(String host, int port, ConnectionType type, String name)
{
_host = host;
_port = port;
_type = type;
_name = name;
}
/**
* @param name
* @return true, if {@code name} is null or it matches (case-insensitive) the {@code _name} associated
* with this ConnectionData, false otherwise.
*/
public boolean nameMatches(String name)
{
return (name == null || name.equalsIgnoreCase(_name));
}
}

View File

@ -1,20 +0,0 @@
package mineplex.serverdata.servers;
import java.util.Comparator;
import mineplex.serverdata.data.DedicatedServer;
public class DedicatedServerSorter implements Comparator<DedicatedServer>
{
@Override
public int compare(DedicatedServer first, DedicatedServer second)
{
if (second.getAvailableRam() <= 1024) return -1;
else if (first.getAvailableRam() <= 1024) return 1;
else if (first.getAvailableRam() > second.getAvailableRam()) return -1;
else if (second.getAvailableRam() > first.getAvailableRam()) return 1;
else if (first.getAvailableCpu() > second.getAvailableCpu()) return -1;
else if (second.getAvailableCpu() > first.getAvailableCpu()) return 1;
else return 0;
}
}

View File

@ -1,170 +0,0 @@
package mineplex.serverdata.servers;
import java.io.File;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import mineplex.serverdata.Region;
import mineplex.serverdata.redis.RedisConfig;
import mineplex.serverdata.redis.RedisServerRepository;
import mineplex.serverdata.servers.ConnectionData.ConnectionType;
/**
* ServerManager handles the creation/management of {@link ServerRepository}s for use.
* @author Ty
*
*/
public class ServerManager
{
public static final String SERVER_STATUS_LABEL = "ServerStatus"; // Label differentiating ServerStatus related servers
private static final String DEFAULT_CONFIG = "redis-config.dat";
// Configuration determining connection information
private static RedisConfig _config;
// The cached repository instances
private static Map<Region, ServerRepository> repositories = new HashMap<Region, ServerRepository>();
/**
* @param host - the host url used to connect to the database
* @param port - the port to connect to the repository
* @param region - the geographical region of the {@link ServerRepository}.
* @return a newly instanced (or cached) {@link ServerRepository} for the specified {@code region}.
*/
private static ServerRepository getServerRepository(ConnectionData writeConn, ConnectionData readConn, Region region)
{
if (repositories.containsKey(region)) return repositories.get(region);
ServerRepository repository = new RedisServerRepository(writeConn, readConn, region);
repositories.put(region, repository);
return repository;
}
/**
* {@code host} defaults to {@value DEFAULT_REDIS_HOST} and
* {@code port} defaults to {@value DEFAULT_REDIS_PORT}.
*
* @see #getServerRepository(String, int, Region)
*/
public static ServerRepository getServerRepository(Region region)
{
return getServerRepository(getConnection(true, SERVER_STATUS_LABEL), getConnection(false, SERVER_STATUS_LABEL), region);
}
/**
* @return the {@link ConnectionData} associated with the master instance connection.
*/
public static ConnectionData getMasterConnection()
{
return getConnection(true);
}
/**
* Non-Deterministic: Generates random slave instance connection.
* @return the {@link ConnectionData} associated with a random slave connection.
*/
public static ConnectionData getSlaveConnection()
{
return getConnection(false);
}
public static ConnectionData getConnection(boolean writeable, String name)
{
return getDefaultConfig().getConnection(writeable, name);
}
/**
* @param writeable - whether the connection referenced in return can receive write-requests
* @return a newly generated {@code ConnectionData} pointing to a valid connection.
*/
public static ConnectionData getConnection(boolean writeable)
{
return getConnection(writeable, "DefaultConnection");
}
/**
* @return the default {@link RedisConfig} associated with this manager, providing appropriate connections.
*/
public static RedisConfig getDefaultConfig()
{
return getConfig(DEFAULT_CONFIG);
}
/**
* @return the {@link RedisConfig} associated with this manager, providing appropriate connections.
*/
public static RedisConfig getConfig(String fileName)
{
if (_config == null)
_config = loadConfig(fileName);
return _config;
}
public static RedisConfig loadConfig(String fileName)
{
try
{
File configFile = new File(fileName);
if (configFile.exists())
{
List<ConnectionData> connections = new ArrayList<ConnectionData>();
List<String> lines = Files.readAllLines(configFile.toPath(), Charset.defaultCharset());
for (String line : lines)
{
ConnectionData connection = deserializeConnection(line);
connections.add(connection);
}
return new RedisConfig(connections);
}
else
{
log(fileName + " not found at " + configFile.toPath().toString());
return new RedisConfig();
}
}
catch (Exception exception)
{
exception.printStackTrace();
log("---Unable To Parse Redis Configuration File---");
}
return null;
}
/**
* @param line - the serialized line representing a valid {@link ConnectionData} object.
* @return a deserialized {@link ConnectionData} referenced by the {@code line} passed in.
*/
private static ConnectionData deserializeConnection(String line)
{
String[] args = line.split(" ");
if (args.length >= 2)
{
String ip = args[0];
int port = Integer.parseInt(args[1]);
String typeName = (args.length >= 3) ? args[2].toUpperCase() : "MASTER"; // Defaults to MASTER if omitted.
ConnectionType type = ConnectionType.valueOf(typeName);
String name = (args.length >= 4) ? args[3] : "DefaultConnection"; // Defaults to DefaultConnection if omitted.
return new ConnectionData(ip, port, type, name);
}
return null;
}
private static void log(String message)
{
System.out.println(String.format("[ServerManager] %s", message));
}
}

View File

@ -1,81 +0,0 @@
package mineplex.serverdata.servers;
import java.util.Collection;
import java.util.List;
import mineplex.serverdata.data.DedicatedServer;
import mineplex.serverdata.data.MinecraftServer;
import mineplex.serverdata.data.ServerGroup;
/**
* The ServerRepository is used for storing/retrieving active sessions
* for {@link MinecraftServer}s, {@link DedicatedServer}s, and {@link ServerGroup}s
* from a persistent database/repoistory.
* @author Ty
*
*/
public interface ServerRepository
{
/**
* @return a newly instanced snapshot {@link Collection} of all currently active
* {@link MinecraftServer}s in the repository.
*/
public Collection<MinecraftServer> getServerStatuses();
public Collection<MinecraftServer> getServerStatusesByPrefix(String prefix);
public Collection<MinecraftServer> getServersByGroup(String serverGroup);
/**
* @param serverName - the name of the {@link MinecraftServer} to be fetched.
* @return the currently active {@link MinecraftServer} with a matching {@code serverName},
* if an active one exists, null otherwise.
*/
public MinecraftServer getServerStatus(String serverName);
/**
* Update (or add, if it doesn't already exist) a {@link MinecraftServer}s data
* in the repository.
*
* A {@link MinecraftServer} must be updated within {@code timeout} milliseconds before
* it expires and is removed from the repository.
* @param serverData - the {@link MinecraftServer} to add/update in the repository.
* @param timeout - the timeout (in milliseconds) before the {@link MinecraftServer} session expires.
*/
public void updataServerStatus(MinecraftServer serverData, int timeout);
/**
* Remove an active {@link MinecraftServer} from the repository.
* @param serverData - the {@link MinecraftServer} to be removed.
*/
public void removeServerStatus(MinecraftServer serverData);
/**
* @param serverName - the name of the server whose existence is being checked.
* @return true, if there exists an active {@link MinecraftServer} session with a
* matching {@code serverName}, false otherwise.
*/
public boolean serverExists(String serverName);
/**
* @return a newly instanced snapshot {@link Collection} of all the
* currently active {@link DedicatedServer}s in the repository.
*/
public Collection<DedicatedServer> getDedicatedServers();
/**
* @return a newly instanced snapshot {@link Collection} of all the
* currently active {@link ServerGroup}s in the repository.
*/
public Collection<ServerGroup> getServerGroups(Collection<MinecraftServer> servers);
public ServerGroup getServerGroup(String serverGroup);
public Collection<MinecraftServer> getDeadServers();
void updateServerGroup(ServerGroup serverGroup);
public void removeServerGroup(ServerGroup serverGroup);
}

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/motd.iml" filepath="$PROJECT_DIR$/motd.iml" />
</modules>
</component>
</project>

View File

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="bea7784e-3ad7-4932-98e1-587634f5a436" name="Default Changelist" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ProjectId" id="1sqbrMnQda6CEC49dy4Wm5DJWAn" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="bea7784e-3ad7-4932-98e1-587634f5a436" name="Default Changelist" comment="" />
<created>1621603265666</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1621603265666</updated>
</task>
<servers />
</component>
</project>

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

Some files were not shown because too many files have changed in this diff Show More