mirror of
https://github.com/filoghost/HolographicDisplays.git
synced 2024-12-21 16:28:37 +01:00
Refactor BungeeCord-related code
This commit is contained in:
parent
9a56a032de
commit
57fd78eac5
@ -30,7 +30,6 @@ import me.filoghost.holographicdisplays.object.internal.InternalHologram;
|
||||
import me.filoghost.holographicdisplays.object.internal.InternalHologramManager;
|
||||
import me.filoghost.holographicdisplays.placeholder.AnimationsRegistry;
|
||||
import me.filoghost.holographicdisplays.placeholder.PlaceholdersManager;
|
||||
import me.filoghost.holographicdisplays.task.BungeeCleanupTask;
|
||||
import me.filoghost.holographicdisplays.task.WorldPlayerCounterTask;
|
||||
import me.filoghost.holographicdisplays.util.NMSVersion;
|
||||
import org.bstats.bukkit.MetricsLite;
|
||||
@ -38,6 +37,7 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class HolographicDisplays extends FCommonsPlugin implements ProtocolPacketSettings {
|
||||
|
||||
@ -112,7 +112,6 @@ public class HolographicDisplays extends FCommonsPlugin implements ProtocolPacke
|
||||
|
||||
// Start repeating tasks.
|
||||
placeholderManager.startRefreshTask(this);
|
||||
Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new BungeeCleanupTask(bungeeServerTracker), 5 * 60 * 20, 5 * 60 * 20);
|
||||
Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new WorldPlayerCounterTask(), 0L, 3 * 20);
|
||||
|
||||
HologramCommandManager commandManager = new HologramCommandManager(configManager, internalHologramManager, nmsManager);
|
||||
@ -142,7 +141,6 @@ public class HolographicDisplays extends FCommonsPlugin implements ProtocolPacke
|
||||
public void load(boolean deferHologramsCreation, ErrorCollector errorCollector) {
|
||||
placeholderManager.untrackAll();
|
||||
internalHologramManager.clearAll();
|
||||
bungeeServerTracker.resetTrackedServers();
|
||||
|
||||
configManager.reloadCustomPlaceholders(errorCollector);
|
||||
configManager.reloadMainConfig(errorCollector);
|
||||
@ -153,7 +151,7 @@ public class HolographicDisplays extends FCommonsPlugin implements ProtocolPacke
|
||||
errorCollector.add(e, "failed to load animation files");
|
||||
}
|
||||
|
||||
bungeeServerTracker.restartTask(Configuration.bungeeRefreshSeconds);
|
||||
bungeeServerTracker.restart(Configuration.bungeeRefreshSeconds, TimeUnit.SECONDS);
|
||||
|
||||
if (deferHologramsCreation) {
|
||||
// For the initial load: holograms are loaded later, when the worlds are ready
|
||||
|
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.bridge.bungeecord;
|
||||
|
||||
import me.filoghost.fcommons.logging.Log;
|
||||
import me.filoghost.holographicdisplays.HolographicDisplays;
|
||||
import me.filoghost.holographicdisplays.disk.Configuration;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
public class BungeeChannel implements PluginMessageListener {
|
||||
|
||||
private static final String BUNGEECORD_CHANNEL = "BungeeCord";
|
||||
private static final String REDISBUNGEE_CHANNEL = "legacy:redisbungee";
|
||||
|
||||
private final BungeeServerTracker bungeeServerTracker;
|
||||
|
||||
public BungeeChannel(BungeeServerTracker bungeeServerTracker) {
|
||||
this.bungeeServerTracker = bungeeServerTracker;
|
||||
}
|
||||
|
||||
public void register(Plugin plugin) {
|
||||
Bukkit.getMessenger().registerOutgoingPluginChannel(plugin, BUNGEECORD_CHANNEL);
|
||||
Bukkit.getMessenger().registerIncomingPluginChannel(plugin, BUNGEECORD_CHANNEL, this);
|
||||
|
||||
Bukkit.getMessenger().registerOutgoingPluginChannel(plugin, REDISBUNGEE_CHANNEL);
|
||||
Bukkit.getMessenger().registerIncomingPluginChannel(plugin, REDISBUNGEE_CHANNEL, this);
|
||||
}
|
||||
|
||||
private String getTargetChannel() {
|
||||
if (Configuration.useRedisBungee) {
|
||||
return REDISBUNGEE_CHANNEL;
|
||||
} else {
|
||||
return BUNGEECORD_CHANNEL;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
|
||||
if (channel.equals(getTargetChannel())) {
|
||||
DataInputStream in = new DataInputStream(new ByteArrayInputStream(message));
|
||||
|
||||
try {
|
||||
String subChannel = in.readUTF();
|
||||
|
||||
if (subChannel.equals("PlayerCount")) {
|
||||
String server = in.readUTF();
|
||||
|
||||
if (in.available() > 0) {
|
||||
int online = in.readInt();
|
||||
|
||||
BungeeServerInfo serverInfo = bungeeServerTracker.getOrCreateServerInfo(server);
|
||||
serverInfo.setOnlinePlayers(online);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (EOFException e) {
|
||||
// Do nothing.
|
||||
} catch (IOException e) {
|
||||
// This should never happen.
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void askPlayerCount(String server) {
|
||||
ByteArrayOutputStream b = new ByteArrayOutputStream();
|
||||
DataOutputStream out = new DataOutputStream(b);
|
||||
|
||||
try {
|
||||
out.writeUTF("PlayerCount");
|
||||
out.writeUTF(server);
|
||||
} catch (IOException e) {
|
||||
// It should not happen.
|
||||
Log.warning("I/O Exception while asking for player count on server '" + server + "'.", e);
|
||||
}
|
||||
|
||||
// OR, if you don't need to send it to a specific player
|
||||
Collection<? extends Player> players = Bukkit.getOnlinePlayers();
|
||||
if (players.size() > 0) {
|
||||
players.iterator().next().sendPluginMessage(HolographicDisplays.getInstance(), getTargetChannel(), b.toByteArray());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.bridge.bungeecord;
|
||||
|
||||
import me.filoghost.fcommons.logging.Log;
|
||||
import me.filoghost.holographicdisplays.disk.Configuration;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
public class BungeeMessenger implements PluginMessageListener {
|
||||
|
||||
private static final String BUNGEECORD_CHANNEL = "BungeeCord";
|
||||
private static final String REDISBUNGEE_CHANNEL = "legacy:redisbungee";
|
||||
|
||||
private final Plugin plugin;
|
||||
private final PlayerCountCallback playerCountCallback;
|
||||
|
||||
private BungeeMessenger(Plugin plugin, PlayerCountCallback playerCountCallback) {
|
||||
this.plugin = plugin;
|
||||
this.playerCountCallback = playerCountCallback;
|
||||
}
|
||||
|
||||
public static BungeeMessenger registerNew(Plugin plugin, PlayerCountCallback playerCountCallback) {
|
||||
BungeeMessenger bungeeMessenger = new BungeeMessenger(plugin, playerCountCallback);
|
||||
|
||||
Bukkit.getMessenger().registerOutgoingPluginChannel(plugin, BUNGEECORD_CHANNEL);
|
||||
Bukkit.getMessenger().registerIncomingPluginChannel(plugin, BUNGEECORD_CHANNEL, bungeeMessenger);
|
||||
|
||||
Bukkit.getMessenger().registerOutgoingPluginChannel(plugin, REDISBUNGEE_CHANNEL);
|
||||
Bukkit.getMessenger().registerIncomingPluginChannel(plugin, REDISBUNGEE_CHANNEL, bungeeMessenger);
|
||||
|
||||
return bungeeMessenger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
|
||||
if (Configuration.pingerEnabled || !channel.equals(getTargetChannel())) {
|
||||
return;
|
||||
}
|
||||
|
||||
DataInputStream in = new DataInputStream(new ByteArrayInputStream(message));
|
||||
|
||||
try {
|
||||
String subChannel = in.readUTF();
|
||||
if (!subChannel.equals("PlayerCount")) {
|
||||
return;
|
||||
}
|
||||
|
||||
String server = in.readUTF();
|
||||
int online = in.readInt();
|
||||
playerCountCallback.onReceive(server, online);
|
||||
} catch (IOException e) {
|
||||
Log.warning("Error while decoding player count from BungeeCord.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendPlayerCountRequest(String server) {
|
||||
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
|
||||
DataOutputStream out = new DataOutputStream(byteOut);
|
||||
|
||||
try {
|
||||
out.writeUTF("PlayerCount");
|
||||
out.writeUTF(server);
|
||||
} catch (IOException e) {
|
||||
Log.warning("Error while encoding player count message for server \"" + server + "\".", e);
|
||||
}
|
||||
|
||||
// Send the message through a random player (BungeeCord will not forward it to them)
|
||||
Collection<? extends Player> players = Bukkit.getOnlinePlayers();
|
||||
if (players.size() > 0) {
|
||||
Player player = players.iterator().next();
|
||||
player.sendPluginMessage(plugin, getTargetChannel(), byteOut.toByteArray());
|
||||
}
|
||||
}
|
||||
|
||||
private String getTargetChannel() {
|
||||
if (Configuration.useRedisBungee) {
|
||||
return REDISBUNGEE_CHANNEL;
|
||||
} else {
|
||||
return BUNGEECORD_CHANNEL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface PlayerCountCallback {
|
||||
|
||||
void onReceive(String serverName, int playerCount);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.bridge.bungeecord;
|
||||
|
||||
import me.filoghost.holographicdisplays.disk.Configuration;
|
||||
|
||||
public class BungeeServerInfo {
|
||||
|
||||
private volatile boolean isOnline;
|
||||
private volatile int onlinePlayers;
|
||||
private volatile int maxPlayers;
|
||||
|
||||
// The two lines of a motd
|
||||
private volatile String motd1; // Should never be null
|
||||
private volatile String motd2; // Should never be null
|
||||
|
||||
private volatile long lastRequest;
|
||||
|
||||
protected BungeeServerInfo() {
|
||||
isOnline = false;
|
||||
this.motd1 = "";
|
||||
this.motd2 = "";
|
||||
updateLastRequest();
|
||||
}
|
||||
|
||||
public boolean isOnline() {
|
||||
return isOnline;
|
||||
}
|
||||
|
||||
public void setOnline(boolean isOnline) {
|
||||
this.isOnline = isOnline;
|
||||
}
|
||||
|
||||
public int getOnlinePlayers() {
|
||||
return onlinePlayers;
|
||||
}
|
||||
|
||||
public void setOnlinePlayers(int onlinePlayers) {
|
||||
this.onlinePlayers = onlinePlayers;
|
||||
}
|
||||
|
||||
public int getMaxPlayers() {
|
||||
return maxPlayers;
|
||||
}
|
||||
|
||||
public void setMaxPlayers(int maxPlayers) {
|
||||
this.maxPlayers = maxPlayers;
|
||||
}
|
||||
|
||||
public String getMotd1() {
|
||||
return motd1;
|
||||
}
|
||||
|
||||
public String getMotd2() {
|
||||
return motd2;
|
||||
}
|
||||
|
||||
public void setMotd(String motd) {
|
||||
if (motd == null) {
|
||||
this.motd1 = "";
|
||||
this.motd2 = "";
|
||||
return;
|
||||
}
|
||||
|
||||
int separatorIndex = motd.indexOf("\n");
|
||||
if (separatorIndex >= 0) {
|
||||
String line1 = motd.substring(0, separatorIndex);
|
||||
String line2 = motd.substring(separatorIndex + 1);
|
||||
this.motd1 = Configuration.pingerTrimMotd ? line1.trim() : line1;
|
||||
this.motd2 = Configuration.pingerTrimMotd ? line2.trim() : line2;
|
||||
} else {
|
||||
this.motd1 = Configuration.pingerTrimMotd ? motd.trim() : motd;
|
||||
this.motd2 = "";
|
||||
}
|
||||
}
|
||||
|
||||
public long getLastRequest() {
|
||||
return lastRequest;
|
||||
}
|
||||
|
||||
public void updateLastRequest() {
|
||||
this.lastRequest = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
}
|
@ -7,8 +7,9 @@ package me.filoghost.holographicdisplays.bridge.bungeecord;
|
||||
|
||||
import me.filoghost.fcommons.logging.Log;
|
||||
import me.filoghost.holographicdisplays.HolographicDisplays;
|
||||
import me.filoghost.holographicdisplays.bridge.bungeecord.serverpinger.PingResponse;
|
||||
import me.filoghost.holographicdisplays.bridge.bungeecord.serverpinger.ServerPinger;
|
||||
import me.filoghost.holographicdisplays.bridge.bungeecord.pinger.PingResponse;
|
||||
import me.filoghost.holographicdisplays.bridge.bungeecord.pinger.ServerPinger;
|
||||
import me.filoghost.holographicdisplays.core.DebugLogger;
|
||||
import me.filoghost.holographicdisplays.disk.Configuration;
|
||||
import me.filoghost.holographicdisplays.disk.ServerAddress;
|
||||
import org.bukkit.Bukkit;
|
||||
@ -17,184 +18,122 @@ import org.bukkit.plugin.Plugin;
|
||||
import java.io.IOException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BungeeServerTracker {
|
||||
|
||||
private static final String PINGER_NOT_ENABLED_ERROR = "[Please enable pinger]";
|
||||
private static final long UNTRACK_AFTER_TIME_WITHOUT_REQUESTS = TimeUnit.MINUTES.toMillis(10);
|
||||
|
||||
private final BungeeChannel bungeeChannel;
|
||||
private final Map<String, BungeeServerInfo> trackedServers;
|
||||
private final ConcurrentMap<String, TrackedServer> trackedServers;
|
||||
private final BungeeMessenger bungeeMessenger;
|
||||
|
||||
private int taskID = -1;
|
||||
|
||||
public BungeeServerTracker(Plugin plugin) {
|
||||
bungeeChannel = new BungeeChannel(this);
|
||||
bungeeChannel.register(plugin);
|
||||
trackedServers = new ConcurrentHashMap<>();
|
||||
bungeeMessenger = BungeeMessenger.registerNew(plugin, this::updateServerInfoFromBungee);
|
||||
}
|
||||
|
||||
public void resetTrackedServers() {
|
||||
public void restart(int updateInterval, TimeUnit timeUnit) {
|
||||
trackedServers.clear();
|
||||
}
|
||||
|
||||
public void track(String server) {
|
||||
if (!trackedServers.containsKey(server)) {
|
||||
BungeeServerInfo info = new BungeeServerInfo();
|
||||
info.setMotd(Configuration.pingerOfflineMotd);
|
||||
trackedServers.put(server, info);
|
||||
|
||||
if (!Configuration.pingerEnabled) {
|
||||
bungeeChannel.askPlayerCount(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected BungeeServerInfo getOrCreateServerInfo(String server) {
|
||||
BungeeServerInfo info = trackedServers.get(server);
|
||||
if (info == null) {
|
||||
info = new BungeeServerInfo();
|
||||
info.setMotd(Configuration.pingerOfflineMotd);
|
||||
trackedServers.put(server, info);
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
public int getPlayersOnline(String server) {
|
||||
BungeeServerInfo info = trackedServers.get(server);
|
||||
if (info != null) {
|
||||
info.updateLastRequest();
|
||||
return info.getOnlinePlayers();
|
||||
} else {
|
||||
// It was not tracked, add it.
|
||||
track(server);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public String getMaxPlayers(String server) {
|
||||
if (!Configuration.pingerEnabled) {
|
||||
return PINGER_NOT_ENABLED_ERROR;
|
||||
}
|
||||
|
||||
BungeeServerInfo info = trackedServers.get(server);
|
||||
if (info != null) {
|
||||
info.updateLastRequest();
|
||||
return String.valueOf(info.getMaxPlayers());
|
||||
} else {
|
||||
// It was not tracked, add it.
|
||||
track(server);
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
|
||||
public String getMotd1(String server) {
|
||||
if (!Configuration.pingerEnabled) {
|
||||
return PINGER_NOT_ENABLED_ERROR;
|
||||
}
|
||||
|
||||
BungeeServerInfo info = trackedServers.get(server);
|
||||
if (info != null) {
|
||||
info.updateLastRequest();
|
||||
return info.getMotd1();
|
||||
} else {
|
||||
// It was not tracked, add it.
|
||||
track(server);
|
||||
return Configuration.pingerOfflineMotd;
|
||||
}
|
||||
}
|
||||
|
||||
public String getMotd2(String server) {
|
||||
if (!Configuration.pingerEnabled) {
|
||||
return PINGER_NOT_ENABLED_ERROR;
|
||||
}
|
||||
|
||||
BungeeServerInfo info = trackedServers.get(server);
|
||||
if (info != null) {
|
||||
info.updateLastRequest();
|
||||
return info.getMotd2();
|
||||
} else {
|
||||
// It was not tracked, add it.
|
||||
track(server);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public String getOnlineStatus(String server) {
|
||||
if (!Configuration.pingerEnabled) {
|
||||
return PINGER_NOT_ENABLED_ERROR;
|
||||
}
|
||||
|
||||
BungeeServerInfo info = trackedServers.get(server);
|
||||
if (info != null) {
|
||||
info.updateLastRequest();
|
||||
return info.isOnline() ? Configuration.pingerStatusOnline : Configuration.pingerStatusOffline;
|
||||
} else {
|
||||
// It was not tracked, add it.
|
||||
track(server);
|
||||
return Configuration.pingerStatusOffline;
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, BungeeServerInfo> getTrackedServers() {
|
||||
return trackedServers;
|
||||
}
|
||||
|
||||
public void restartTask(int refreshSeconds) {
|
||||
if (taskID != -1) {
|
||||
Bukkit.getScheduler().cancelTask(taskID);
|
||||
}
|
||||
|
||||
taskID = Bukkit.getScheduler().scheduleSyncRepeatingTask(HolographicDisplays.getInstance(), () -> {
|
||||
if (Configuration.pingerEnabled) {
|
||||
runAsyncPinger();
|
||||
} else {
|
||||
for (String server : trackedServers.keySet()) {
|
||||
bungeeChannel.askPlayerCount(server);
|
||||
}
|
||||
}
|
||||
|
||||
}, 1, refreshSeconds * 20L);
|
||||
taskID = Bukkit.getScheduler().scheduleSyncRepeatingTask(HolographicDisplays.getInstance(),
|
||||
this::runPeriodicUpdateTask, 1, timeUnit.toSeconds(updateInterval) * 20L);
|
||||
}
|
||||
|
||||
private void runAsyncPinger() {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(HolographicDisplays.getInstance(), () -> {
|
||||
for (ServerAddress serverAddress : Configuration.pingerServers) {
|
||||
BungeeServerInfo serverInfo = getOrCreateServerInfo(serverAddress.getName());
|
||||
boolean displayOffline = false;
|
||||
public ServerInfo getCurrentServerInfo(String serverName) {
|
||||
// If it wasn't already tracked, send an update request instantly
|
||||
if (!Configuration.pingerEnabled && !trackedServers.containsKey(serverName)) {
|
||||
bungeeMessenger.sendPlayerCountRequest(serverName);
|
||||
}
|
||||
|
||||
try {
|
||||
PingResponse data = ServerPinger.fetchData(serverAddress, Configuration.pingerTimeout);
|
||||
TrackedServer trackedServer = trackedServers.computeIfAbsent(serverName, TrackedServer::new);
|
||||
trackedServer.updateLastRequest();
|
||||
return trackedServer.serverInfo;
|
||||
}
|
||||
|
||||
if (data.isOnline()) {
|
||||
serverInfo.setOnline(true);
|
||||
serverInfo.setOnlinePlayers(data.getOnlinePlayers());
|
||||
serverInfo.setMaxPlayers(data.getMaxPlayers());
|
||||
serverInfo.setMotd(data.getMotd());
|
||||
} else {
|
||||
displayOffline = true;
|
||||
}
|
||||
} catch (SocketTimeoutException e) {
|
||||
// Common error, avoid logging
|
||||
displayOffline = true;
|
||||
} catch (UnknownHostException e) {
|
||||
Log.warning("Couldn't fetch data from " + serverAddress + ": unknown host address.");
|
||||
displayOffline = true;
|
||||
} catch (IOException e) {
|
||||
Log.warning("Couldn't fetch data from " + serverAddress + ".", e);
|
||||
displayOffline = true;
|
||||
private void runPeriodicUpdateTask() {
|
||||
removeUnusedServers();
|
||||
|
||||
if (Configuration.pingerEnabled) {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(HolographicDisplays.getInstance(), () -> {
|
||||
for (TrackedServer trackedServer : trackedServers.values()) {
|
||||
updateServerInfoWithPinger(trackedServer);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (String serverName : trackedServers.keySet()) {
|
||||
bungeeMessenger.sendPlayerCountRequest(serverName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (displayOffline) {
|
||||
serverInfo.setOnline(false);
|
||||
serverInfo.setOnlinePlayers(0);
|
||||
serverInfo.setMaxPlayers(0);
|
||||
serverInfo.setMotd(Configuration.pingerOfflineMotd);
|
||||
}
|
||||
private void updateServerInfoWithPinger(TrackedServer trackedServer) {
|
||||
ServerAddress serverAddress = Configuration.pingerServerAddresses.get(trackedServer.serverName);
|
||||
|
||||
if (serverAddress != null) {
|
||||
trackedServer.serverInfo = pingServer(serverAddress);
|
||||
} else {
|
||||
trackedServer.serverInfo = ServerInfo.offline("[Unknown server: " + trackedServer.serverName + "]");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateServerInfoFromBungee(String serverName, int onlinePlayers) {
|
||||
TrackedServer trackedServer = trackedServers.get(serverName);
|
||||
if (trackedServer != null) {
|
||||
trackedServer.serverInfo = ServerInfo.online(onlinePlayers, 0, "");
|
||||
}
|
||||
}
|
||||
|
||||
private ServerInfo pingServer(ServerAddress serverAddress) {
|
||||
try {
|
||||
PingResponse data = ServerPinger.fetchData(serverAddress, Configuration.pingerTimeout);
|
||||
return ServerInfo.online(data.getOnlinePlayers(), data.getMaxPlayers(), data.getMotd());
|
||||
} catch (SocketTimeoutException e) {
|
||||
// Common error, do not log
|
||||
} catch (UnknownHostException e) {
|
||||
Log.warning("Couldn't fetch data from " + serverAddress + ": unknown host address.");
|
||||
} catch (IOException e) {
|
||||
Log.warning("Couldn't fetch data from " + serverAddress + ".", e);
|
||||
}
|
||||
|
||||
return ServerInfo.offline(Configuration.pingerOfflineMotd);
|
||||
}
|
||||
|
||||
private void removeUnusedServers() {
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
trackedServers.values().removeIf(trackedServer -> {
|
||||
if (now - trackedServer.lastRequest > UNTRACK_AFTER_TIME_WITHOUT_REQUESTS) {
|
||||
DebugLogger.info("Untracked unused server \"" + trackedServer.serverName + "\".");
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static class TrackedServer {
|
||||
|
||||
private final String serverName;
|
||||
private volatile ServerInfo serverInfo;
|
||||
private volatile long lastRequest;
|
||||
|
||||
private TrackedServer(String serverName) {
|
||||
this.serverName = serverName;
|
||||
this.serverInfo = ServerInfo.offline(Configuration.pingerOfflineMotd);
|
||||
}
|
||||
|
||||
private void updateLastRequest() {
|
||||
this.lastRequest = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.bridge.bungeecord;
|
||||
|
||||
import me.filoghost.fcommons.Strings;
|
||||
import me.filoghost.holographicdisplays.disk.Configuration;
|
||||
|
||||
public class ServerInfo {
|
||||
|
||||
private final boolean online;
|
||||
private final int onlinePlayers;
|
||||
private final int maxPlayers;
|
||||
private final String motdLine1, motdLine2;
|
||||
|
||||
public static ServerInfo online(int onlinePlayers, int maxPlayers, String motd) {
|
||||
return new ServerInfo(true, onlinePlayers, maxPlayers, motd);
|
||||
}
|
||||
|
||||
public static ServerInfo offline(String motd) {
|
||||
return new ServerInfo(false, 0, 0, motd);
|
||||
}
|
||||
|
||||
private ServerInfo(boolean online, int onlinePlayers, int maxPlayers, String motd) {
|
||||
this.online = online;
|
||||
this.onlinePlayers = onlinePlayers;
|
||||
this.maxPlayers = maxPlayers;
|
||||
|
||||
if (Strings.isEmpty(motd)) {
|
||||
motdLine1 = "";
|
||||
motdLine2 = "";
|
||||
} else if (motd.contains("\n")) {
|
||||
String[] lines = Strings.split(motd, "\n", 2);
|
||||
if (Configuration.pingerTrimMotd) {
|
||||
lines = Strings.trim(lines);
|
||||
}
|
||||
motdLine1 = lines[0];
|
||||
motdLine2 = lines.length > 1 ? lines[1] : "";
|
||||
} else {
|
||||
if (Configuration.pingerTrimMotd) {
|
||||
motd = motd.trim();
|
||||
}
|
||||
motdLine1 = motd;
|
||||
motdLine2 = "";
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOnline() {
|
||||
return online;
|
||||
}
|
||||
|
||||
public int getOnlinePlayers() {
|
||||
return onlinePlayers;
|
||||
}
|
||||
|
||||
public int getMaxPlayers() {
|
||||
return maxPlayers;
|
||||
}
|
||||
|
||||
public String getMotdLine1() {
|
||||
return motdLine1;
|
||||
}
|
||||
|
||||
public String getMotdLine2() {
|
||||
return motdLine2;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.bridge.bungeecord.pinger;
|
||||
|
||||
import me.filoghost.holographicdisplays.core.DebugLogger;
|
||||
import me.filoghost.holographicdisplays.disk.ServerAddress;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
|
||||
public class PingResponse {
|
||||
|
||||
private final String motd;
|
||||
private final int onlinePlayers;
|
||||
private final int maxPlayers;
|
||||
|
||||
protected static PingResponse fromJson(String jsonString, ServerAddress address) {
|
||||
if (jsonString == null || jsonString.isEmpty()) {
|
||||
logInvalidResponse(jsonString, address);
|
||||
return errorResponse("Invalid ping response (null or empty)");
|
||||
}
|
||||
|
||||
Object jsonObject = JSONValue.parse(jsonString);
|
||||
|
||||
if (!(jsonObject instanceof JSONObject)) {
|
||||
logInvalidResponse(jsonString, address);
|
||||
return errorResponse("Invalid ping response (wrong format)");
|
||||
}
|
||||
|
||||
JSONObject json = (JSONObject) jsonObject;
|
||||
|
||||
Object descriptionObject = json.get("description");
|
||||
|
||||
String motd;
|
||||
int onlinePlayers = 0;
|
||||
int maxPlayers = 0;
|
||||
|
||||
if (descriptionObject == null) {
|
||||
logInvalidResponse(jsonString, address);
|
||||
return errorResponse("Invalid ping response (description not found)");
|
||||
}
|
||||
|
||||
if (descriptionObject instanceof JSONObject) {
|
||||
Object text = ((JSONObject) descriptionObject).get("text");
|
||||
if (text == null) {
|
||||
logInvalidResponse(jsonString, address);
|
||||
return errorResponse("Invalid ping response (text not found)");
|
||||
}
|
||||
motd = text.toString();
|
||||
} else {
|
||||
motd = descriptionObject.toString();
|
||||
}
|
||||
|
||||
Object playersObject = json.get("players");
|
||||
|
||||
if (playersObject instanceof JSONObject) {
|
||||
JSONObject playersJson = (JSONObject) playersObject;
|
||||
|
||||
Object onlineObject = playersJson.get("online");
|
||||
if (onlineObject instanceof Number) {
|
||||
onlinePlayers = ((Number) onlineObject).intValue();
|
||||
}
|
||||
|
||||
Object maxObject = playersJson.get("max");
|
||||
if (maxObject instanceof Number) {
|
||||
maxPlayers = ((Number) maxObject).intValue();
|
||||
}
|
||||
}
|
||||
|
||||
return new PingResponse(motd, onlinePlayers, maxPlayers);
|
||||
}
|
||||
|
||||
private static void logInvalidResponse(String responseJsonString, ServerAddress address) {
|
||||
DebugLogger.warning("Received invalid JSON response from IP \"" + address + "\": " + responseJsonString);
|
||||
}
|
||||
|
||||
private static PingResponse errorResponse(String error) {
|
||||
return new PingResponse(error, 0, 0);
|
||||
}
|
||||
|
||||
private PingResponse(String motd, int onlinePlayers, int maxPlayers) {
|
||||
this.motd = motd;
|
||||
this.onlinePlayers = onlinePlayers;
|
||||
this.maxPlayers = maxPlayers;
|
||||
}
|
||||
|
||||
public String getMotd() {
|
||||
return motd;
|
||||
}
|
||||
|
||||
public int getOnlinePlayers() {
|
||||
return onlinePlayers;
|
||||
}
|
||||
|
||||
public int getMaxPlayers() {
|
||||
return maxPlayers;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.bridge.bungeecord.pinger;
|
||||
|
||||
import me.filoghost.holographicdisplays.disk.ServerAddress;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class ServerPinger {
|
||||
|
||||
public static PingResponse fetchData(final ServerAddress serverAddress, int timeout) throws IOException {
|
||||
try (Socket socket = openSocket(serverAddress)) {
|
||||
socket.setSoTimeout(timeout);
|
||||
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
|
||||
DataInputStream in = new DataInputStream(socket.getInputStream());
|
||||
|
||||
// Handshake packet
|
||||
ByteArrayOutputStream handshakeBytes = new ByteArrayOutputStream();
|
||||
DataOutputStream handshakeOut = new DataOutputStream(handshakeBytes);
|
||||
handshakeOut.writeByte(0x00); // Packet ID
|
||||
writeVarInt(handshakeOut, 4); // Protocol version
|
||||
writeString(handshakeOut, serverAddress.getAddress());
|
||||
handshakeOut.writeShort(serverAddress.getPort());
|
||||
writeVarInt(handshakeOut, 1); // Next state: status request
|
||||
writeByteArray(out, handshakeBytes.toByteArray());
|
||||
|
||||
// Status request packet
|
||||
writeByteArray(out, new byte[]{ 0x00 }); // Packet ID
|
||||
|
||||
// Response packet
|
||||
readVarInt(in); // Packet size
|
||||
readVarInt(in); // Packet ID
|
||||
String responseJson = readString(in);
|
||||
|
||||
return PingResponse.fromJson(responseJson, serverAddress);
|
||||
}
|
||||
}
|
||||
|
||||
private static Socket openSocket(ServerAddress serverAddress) throws IOException {
|
||||
return new Socket(serverAddress.getAddress(), serverAddress.getPort());
|
||||
}
|
||||
|
||||
private static String readString(DataInputStream in) throws IOException {
|
||||
byte[] bytes = readByteArray(in);
|
||||
return new String(bytes, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private static void writeString(DataOutputStream out, String s) throws IOException {
|
||||
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
|
||||
writeByteArray(out, bytes);
|
||||
}
|
||||
|
||||
private static byte[] readByteArray(DataInputStream in) throws IOException {
|
||||
int length = readVarInt(in);
|
||||
byte[] bytes = new byte[length];
|
||||
in.readFully(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private static void writeByteArray(DataOutputStream out, byte[] bytes) throws IOException {
|
||||
writeVarInt(out, bytes.length);
|
||||
out.write(bytes);
|
||||
}
|
||||
|
||||
private static int readVarInt(DataInputStream in) throws IOException {
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
while (true) {
|
||||
int k = in.readByte();
|
||||
i |= (k & 0x7F) << j++ * 7;
|
||||
if (j > 5) {
|
||||
throw new RuntimeException("VarInt too big");
|
||||
}
|
||||
if ((k & 0x80) != 0x80) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeVarInt(DataOutputStream out, int paramInt) throws IOException {
|
||||
while ((paramInt & 0xFFFFFF80) != 0x0) {
|
||||
out.writeByte((paramInt & 0x7F) | 0x80);
|
||||
paramInt >>>= 7;
|
||||
}
|
||||
out.writeByte(paramInt);
|
||||
}
|
||||
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.bridge.bungeecord.serverpinger;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
class PacketUtils {
|
||||
|
||||
public static void writeString(final DataOutputStream out, final String s, final Charset charset) throws IOException {
|
||||
if (charset == StandardCharsets.UTF_8) {
|
||||
writeVarInt(out, s.length());
|
||||
} else {
|
||||
out.writeShort(s.length());
|
||||
}
|
||||
out.write(s.getBytes(charset));
|
||||
}
|
||||
|
||||
public static int readVarInt(final DataInputStream in) throws IOException {
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
while (true) {
|
||||
final int k = in.readByte();
|
||||
i |= (k & 0x7F) << j++ * 7;
|
||||
if (j > 5) {
|
||||
throw new RuntimeException("VarInt too big");
|
||||
}
|
||||
if ((k & 0x80) != 0x80) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeVarInt(final DataOutputStream out, int paramInt) throws IOException {
|
||||
while ((paramInt & 0xFFFFFF80) != 0x0) {
|
||||
out.write((paramInt & 0x7F) | 0x80);
|
||||
paramInt >>>= 7;
|
||||
}
|
||||
out.write(paramInt);
|
||||
}
|
||||
|
||||
public static void closeQuietly(Closeable closeable) {
|
||||
try {
|
||||
if (closeable != null) {
|
||||
closeable.close();
|
||||
}
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.bridge.bungeecord.serverpinger;
|
||||
|
||||
import me.filoghost.holographicdisplays.disk.ServerAddress;
|
||||
import me.filoghost.holographicdisplays.core.DebugLogger;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
|
||||
public class PingResponse
|
||||
{
|
||||
private boolean isOnline;
|
||||
private String motd;
|
||||
private int onlinePlayers;
|
||||
private int maxPlayers;
|
||||
|
||||
public PingResponse(String jsonString, ServerAddress address) {
|
||||
if (jsonString == null || jsonString.isEmpty()) {
|
||||
motd = "Invalid ping response";
|
||||
DebugLogger.warning("Received empty Json response from IP \"" + address.toString() + "\".");
|
||||
return;
|
||||
}
|
||||
|
||||
Object jsonObject = JSONValue.parse(jsonString);
|
||||
|
||||
if (!(jsonObject instanceof JSONObject)) {
|
||||
motd = "Invalid ping response";
|
||||
DebugLogger.warning("Received invalid Json response from IP \"" + address.toString() + "\": " + jsonString);
|
||||
return;
|
||||
}
|
||||
|
||||
JSONObject json = (JSONObject) jsonObject;
|
||||
isOnline = true;
|
||||
|
||||
Object descriptionObject = json.get("description");
|
||||
|
||||
if (descriptionObject != null) {
|
||||
if (descriptionObject instanceof JSONObject) {
|
||||
Object text = ((JSONObject) descriptionObject).get("text");
|
||||
if (text != null) {
|
||||
motd = text.toString();
|
||||
} else {
|
||||
motd = "Invalid ping response (text not found)";
|
||||
}
|
||||
} else {
|
||||
motd = descriptionObject.toString();
|
||||
}
|
||||
} else {
|
||||
motd = "Invalid ping response (description not found)";
|
||||
DebugLogger.warning("Received invalid Json response from IP \"" + address.toString() + "\": " + jsonString);
|
||||
}
|
||||
|
||||
Object playersObject = json.get("players");
|
||||
|
||||
if (playersObject instanceof JSONObject) {
|
||||
JSONObject playersJson = (JSONObject) playersObject;
|
||||
|
||||
Object onlineObject = playersJson.get("online");
|
||||
if (onlineObject instanceof Number) {
|
||||
onlinePlayers = ((Number) onlineObject).intValue();
|
||||
}
|
||||
|
||||
Object maxObject = playersJson.get("max");
|
||||
if (maxObject instanceof Number) {
|
||||
maxPlayers = ((Number) maxObject).intValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOnline() {
|
||||
return isOnline;
|
||||
}
|
||||
|
||||
public String getMotd() {
|
||||
return motd;
|
||||
}
|
||||
|
||||
public int getOnlinePlayers() {
|
||||
return onlinePlayers;
|
||||
}
|
||||
|
||||
public int getMaxPlayers() {
|
||||
return maxPlayers;
|
||||
}
|
||||
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.bridge.bungeecord.serverpinger;
|
||||
|
||||
import me.filoghost.holographicdisplays.disk.ServerAddress;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class ServerPinger {
|
||||
|
||||
public static PingResponse fetchData(final ServerAddress serverAddress, int timeout) throws IOException {
|
||||
Socket socket = null;
|
||||
DataOutputStream dataOut = null;
|
||||
DataInputStream dataIn = null;
|
||||
|
||||
try {
|
||||
socket = new Socket(serverAddress.getAddress(), serverAddress.getPort());
|
||||
socket.setSoTimeout(timeout);
|
||||
dataOut = new DataOutputStream(socket.getOutputStream());
|
||||
dataIn = new DataInputStream(socket.getInputStream());
|
||||
final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
|
||||
final DataOutputStream handshake = new DataOutputStream(byteOut);
|
||||
handshake.write(0);
|
||||
PacketUtils.writeVarInt(handshake, 4);
|
||||
PacketUtils.writeString(handshake, serverAddress.getAddress(), StandardCharsets.UTF_8);
|
||||
handshake.writeShort(serverAddress.getPort());
|
||||
PacketUtils.writeVarInt(handshake, 1);
|
||||
byte[] bytes = byteOut.toByteArray();
|
||||
PacketUtils.writeVarInt(dataOut, bytes.length);
|
||||
dataOut.write(bytes);
|
||||
bytes = new byte[] { 0 };
|
||||
PacketUtils.writeVarInt(dataOut, bytes.length);
|
||||
dataOut.write(bytes);
|
||||
PacketUtils.readVarInt(dataIn);
|
||||
PacketUtils.readVarInt(dataIn);
|
||||
final byte[] responseData = new byte[PacketUtils.readVarInt(dataIn)];
|
||||
dataIn.readFully(responseData);
|
||||
final String jsonString = new String(responseData, StandardCharsets.UTF_8);
|
||||
return new PingResponse(jsonString, serverAddress);
|
||||
} finally {
|
||||
PacketUtils.closeQuietly(dataOut);
|
||||
PacketUtils.closeQuietly(dataIn);
|
||||
PacketUtils.closeQuietly(socket);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -19,8 +19,8 @@ import org.bukkit.ChatColor;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Configuration {
|
||||
|
||||
@ -41,7 +41,7 @@ public class Configuration {
|
||||
public static String pingerStatusOnline;
|
||||
public static String pingerStatusOffline;
|
||||
public static boolean pingerTrimMotd;
|
||||
public static List<ServerAddress> pingerServers;
|
||||
public static Map<String, ServerAddress> pingerServerAddresses;
|
||||
|
||||
public static void load(MainConfigModel config, ErrorCollector errorCollector) {
|
||||
spaceBetweenLines = config.spaceBetweenLines;
|
||||
@ -62,12 +62,12 @@ public class Configuration {
|
||||
pingerStatusOffline = StringConverter.toReadableFormat(config.pingerStatusOffline);
|
||||
pingerTrimMotd = config.pingerTrimMotd;
|
||||
|
||||
pingerServers = new ArrayList<>();
|
||||
pingerServerAddresses = new HashMap<>();
|
||||
if (pingerEnabled) {
|
||||
for (String singleServer : config.pingerServers) {
|
||||
ServerAddress serverAddress = parseServerAddress(singleServer, errorCollector);
|
||||
if (serverAddress != null) {
|
||||
pingerServers.add(serverAddress);
|
||||
pingerServerAddresses.put(serverAddress.getName(), serverAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,12 +5,15 @@
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder;
|
||||
|
||||
import me.filoghost.fcommons.Strings;
|
||||
import me.filoghost.fcommons.logging.Log;
|
||||
import me.filoghost.holographicdisplays.api.placeholder.PlaceholderReplacer;
|
||||
import me.filoghost.holographicdisplays.bridge.bungeecord.ServerInfo;
|
||||
import me.filoghost.holographicdisplays.bridge.bungeecord.BungeeServerTracker;
|
||||
import me.filoghost.holographicdisplays.core.Utils;
|
||||
import me.filoghost.holographicdisplays.core.hologram.StandardTextLine;
|
||||
import me.filoghost.holographicdisplays.core.nms.entity.NMSArmorStand;
|
||||
import me.filoghost.holographicdisplays.disk.Configuration;
|
||||
import me.filoghost.holographicdisplays.task.WorldPlayerCounterTask;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
@ -26,6 +29,8 @@ import java.util.regex.Pattern;
|
||||
|
||||
public class PlaceholdersManager {
|
||||
|
||||
private static final String PINGER_NOT_ENABLED_ERROR = "[Please enable pinger]";
|
||||
|
||||
private static final Pattern BUNGEE_ONLINE_PATTERN = makePlaceholderWithArgsPattern("online");
|
||||
private static final Pattern BUNGEE_MAX_PATTERN = makePlaceholderWithArgsPattern("max_players");
|
||||
private static final Pattern BUNGEE_MOTD_PATTERN = makePlaceholderWithArgsPattern("motd");
|
||||
@ -170,28 +175,22 @@ public class PlaceholdersManager {
|
||||
}
|
||||
|
||||
final String serverName = extractArgumentFromPlaceholder(matcher);
|
||||
bungeeServerTracker.track(serverName); // Track this server.
|
||||
|
||||
if (serverName.contains(",")) {
|
||||
String[] split = serverName.split(",");
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
split[i] = split[i].trim();
|
||||
}
|
||||
|
||||
final String[] serversToTrack = split;
|
||||
String[] serversToTrack = Strings.splitAndTrim(serverName, ",");
|
||||
|
||||
// Add it to tracked servers.
|
||||
bungeeReplacers.put(matcher.group(), () -> {
|
||||
int count = 0;
|
||||
for (String serverToTrack : serversToTrack) {
|
||||
count += bungeeServerTracker.getPlayersOnline(serverToTrack);
|
||||
count += bungeeServerTracker.getCurrentServerInfo(serverToTrack).getOnlinePlayers();
|
||||
}
|
||||
return String.valueOf(count);
|
||||
});
|
||||
} else {
|
||||
// Normal, single tracked server.
|
||||
bungeeReplacers.put(matcher.group(), () -> {
|
||||
return String.valueOf(bungeeServerTracker.getPlayersOnline(serverName));
|
||||
return String.valueOf(bungeeServerTracker.getCurrentServerInfo(serverName).getOnlinePlayers());
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -204,11 +203,14 @@ public class PlaceholdersManager {
|
||||
}
|
||||
|
||||
final String serverName = extractArgumentFromPlaceholder(matcher);
|
||||
bungeeServerTracker.track(serverName); // Track this server.
|
||||
|
||||
// Add it to tracked servers.
|
||||
bungeeReplacers.put(matcher.group(), () -> {
|
||||
return bungeeServerTracker.getMaxPlayers(serverName);
|
||||
if (!Configuration.pingerEnabled) {
|
||||
return PINGER_NOT_ENABLED_ERROR;
|
||||
}
|
||||
|
||||
return String.valueOf(bungeeServerTracker.getCurrentServerInfo(serverName).getMaxPlayers());
|
||||
});
|
||||
}
|
||||
|
||||
@ -220,11 +222,14 @@ public class PlaceholdersManager {
|
||||
}
|
||||
|
||||
final String serverName = extractArgumentFromPlaceholder(matcher);
|
||||
bungeeServerTracker.track(serverName); // Track this server.
|
||||
|
||||
// Add it to tracked servers.
|
||||
bungeeReplacers.put(matcher.group(), () -> {
|
||||
return bungeeServerTracker.getMotd1(serverName);
|
||||
if (!Configuration.pingerEnabled) {
|
||||
return PINGER_NOT_ENABLED_ERROR;
|
||||
}
|
||||
|
||||
return bungeeServerTracker.getCurrentServerInfo(serverName).getMotdLine1();
|
||||
});
|
||||
}
|
||||
|
||||
@ -236,11 +241,14 @@ public class PlaceholdersManager {
|
||||
}
|
||||
|
||||
final String serverName = extractArgumentFromPlaceholder(matcher);
|
||||
bungeeServerTracker.track(serverName); // Track this server.
|
||||
|
||||
// Add it to tracked servers.
|
||||
bungeeReplacers.put(matcher.group(), () -> {
|
||||
return bungeeServerTracker.getMotd2(serverName);
|
||||
if (!Configuration.pingerEnabled) {
|
||||
return PINGER_NOT_ENABLED_ERROR;
|
||||
}
|
||||
|
||||
return bungeeServerTracker.getCurrentServerInfo(serverName).getMotdLine2();
|
||||
});
|
||||
}
|
||||
|
||||
@ -252,11 +260,19 @@ public class PlaceholdersManager {
|
||||
}
|
||||
|
||||
final String serverName = extractArgumentFromPlaceholder(matcher);
|
||||
bungeeServerTracker.track(serverName); // Track this server.
|
||||
|
||||
// Add it to tracked servers.
|
||||
bungeeReplacers.put(matcher.group(), () -> {
|
||||
return bungeeServerTracker.getOnlineStatus(serverName);
|
||||
if (!Configuration.pingerEnabled) {
|
||||
return PINGER_NOT_ENABLED_ERROR;
|
||||
}
|
||||
|
||||
ServerInfo serverInfo = bungeeServerTracker.getCurrentServerInfo(serverName);
|
||||
if (serverInfo.isOnline()) {
|
||||
return Configuration.pingerStatusOnline;
|
||||
} else {
|
||||
return Configuration.pingerStatusOffline;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.task;
|
||||
|
||||
import me.filoghost.holographicdisplays.bridge.bungeecord.BungeeServerInfo;
|
||||
import me.filoghost.holographicdisplays.bridge.bungeecord.BungeeServerTracker;
|
||||
import me.filoghost.holographicdisplays.core.DebugLogger;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* A task to remove unused server data in the server tracker.
|
||||
*/
|
||||
public class BungeeCleanupTask implements Runnable {
|
||||
|
||||
private static final long MAX_INACTIVITY = TimeUnit.MINUTES.toMillis(10);
|
||||
|
||||
private final BungeeServerTracker bungeeServerTracker;
|
||||
|
||||
public BungeeCleanupTask(BungeeServerTracker bungeeServerTracker) {
|
||||
this.bungeeServerTracker = bungeeServerTracker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
long now = System.currentTimeMillis();
|
||||
Iterator<Entry<String, BungeeServerInfo>> iter = bungeeServerTracker.getTrackedServers().entrySet().iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
Entry<String, BungeeServerInfo> next = iter.next();
|
||||
long lastRequest = next.getValue().getLastRequest();
|
||||
|
||||
if (lastRequest != 0 && now - lastRequest > MAX_INACTIVITY) {
|
||||
// Don't track that server anymore.
|
||||
iter.remove();
|
||||
DebugLogger.info("Removed bungee server \"" + next.getKey() + "\" from tracking due to inactivity.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user