refactor: clean source code
BIN
Art/BlackFriday.png
Normal file
After Width: | Height: | Size: 170 KiB |
BIN
Art/Carl.png
Normal file
After Width: | Height: | Size: 345 KiB |
BIN
Art/ChristmasChaos.png
Normal file
After Width: | Height: | Size: 438 KiB |
BIN
Art/ClansBanner.png
Normal file
After Width: | Height: | Size: 1017 KiB |
BIN
Art/Halloween Horror.jpg
Normal file
After Width: | Height: | Size: 356 KiB |
BIN
Art/Logos/AU server.png
Normal file
After Width: | Height: | Size: 238 KiB |
1073
Art/Logos/MINEPLEX LOGO RGB.ai
Normal file
BIN
Art/Logos/logo.jpg
Normal file
After Width: | Height: | Size: 201 KiB |
BIN
Art/MS SMoke.psd
Normal file
BIN
Art/Pumpkin.png
Normal file
After Width: | Height: | Size: 692 KiB |
BIN
Art/Resource Packs/Icons/Icons34x34byAilsEnglish2013.zip
Normal file
BIN
Art/Resource Packs/Icons/RPGIconsExtra_by_Ails.zip
Normal file
BIN
Art/Resource Packs/MineStrike.zip
Normal file
BIN
Art/Resource Packs/Res Pack Guide.zip
Normal file
BIN
Art/Resource Packs/ResWizards.zip
Normal file
BIN
Art/Resource Packs/hh.zip
Normal file
BIN
Art/Resource Packs/xmas.zip
Normal file
BIN
Art/Skywars/Skywars.lip
Normal file
BIN
Art/Skywars/Skywars.png
Normal file
After Width: | Height: | Size: 2.0 MiB |
BIN
Art/Skywars/Skywars.psd
Normal file
BIN
Art/Spooky Sale.png
Normal file
After Width: | Height: | Size: 176 KiB |
BIN
Art/TitanLogo.png
Normal file
After Width: | Height: | Size: 375 KiB |
BIN
Art/Treasure/4Qq2m6x.png
Normal file
After Width: | Height: | Size: 169 KiB |
BIN
Art/Treasure/canc.jpg
Normal file
After Width: | Height: | Size: 119 KiB |
BIN
Art/Treasure/legend.jpg
Normal file
After Width: | Height: | Size: 1.1 MiB |
BIN
Art/Treasure/xxiJkbb.png
Normal file
After Width: | Height: | Size: 182 KiB |
BIN
Art/WinterTreasure.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
BIN
Art/WinterTreasureTrim.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
BIN
Art/y5O7WYh.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
Art/zKzkfLE.png
Normal file
After Width: | Height: | Size: 93 KiB |
3
Bungee & Mineplexer/Mineplexer/.idea/.gitignore
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
6
Bungee & Mineplexer/Mineplexer/.idea/misc.xml
generated
@ -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>
|
|
11
Bungee & Mineplexer/Mineplexer/.idea/modules.xml
generated
@ -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>
|
|
@ -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>
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
@ -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>
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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>
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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>
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
@ -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>
|
|
||||||
*/
|
|
||||||
}
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|