mirror of
https://github.com/filoghost/HolographicDisplays.git
synced 2024-12-24 17:57:36 +01:00
Added the ability to ping any server (online status, motd, max players)
+ smaller tweaks.
This commit is contained in:
parent
896609d046
commit
782e83be5d
@ -38,6 +38,9 @@ public class HolographicDisplays extends JavaPlugin {
|
||||
// Since 1.8 we use armor stands instead of wither skulls.
|
||||
private static boolean is1_8;
|
||||
|
||||
// Used for the server pinger.
|
||||
private static boolean isPreNetty;
|
||||
|
||||
// True if ProtocolLib is installed and successfully loaded.
|
||||
private static boolean useProtocolLib;
|
||||
|
||||
@ -83,6 +86,7 @@ public class HolographicDisplays extends JavaPlugin {
|
||||
|
||||
if ("1.6.4".equals(version)) {
|
||||
version = "v1_6_R3";
|
||||
isPreNetty = true;
|
||||
} else if ("1.7.2".equals(version)) {
|
||||
version = "v1_7_R1";
|
||||
} else if ("1.7.5".equals(version)) {
|
||||
@ -222,6 +226,10 @@ public class HolographicDisplays extends JavaPlugin {
|
||||
return is1_8;
|
||||
}
|
||||
|
||||
public static boolean isPreNetty() {
|
||||
return isPreNetty;
|
||||
}
|
||||
|
||||
private static void printWarnAndDisable(String... messages) {
|
||||
StringBuffer buffer = new StringBuffer("\n ");
|
||||
for (String message : messages) {
|
||||
|
@ -50,7 +50,9 @@ public class BungeeChannel implements PluginMessageListener {
|
||||
|
||||
if (in.available() > 0) {
|
||||
int online = in.readInt();
|
||||
BungeeServerTracker.handlePing(server, online);
|
||||
|
||||
BungeeServerInfo serverInfo = BungeeServerTracker.getOrCreateServerInfo(server);
|
||||
serverInfo.setOnlinePlayers(online);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,24 @@ package com.gmail.filoghost.holographicdisplays.bridge.bungeecord;
|
||||
|
||||
public class BungeeServerInfo {
|
||||
|
||||
private boolean isOnline;
|
||||
private int onlinePlayers;
|
||||
private int maxPlayers;
|
||||
private String motd; // Should never be null
|
||||
private long lastRequest;
|
||||
|
||||
protected BungeeServerInfo(int onlinePlayers, long lastRequest) {
|
||||
this.onlinePlayers = onlinePlayers;
|
||||
this.lastRequest = lastRequest;
|
||||
protected BungeeServerInfo() {
|
||||
isOnline = true;
|
||||
this.motd = "";
|
||||
updateLastRequest();
|
||||
}
|
||||
|
||||
public boolean isOnline() {
|
||||
return isOnline;
|
||||
}
|
||||
|
||||
public void setOnline(boolean isOnline) {
|
||||
this.isOnline = isOnline;
|
||||
}
|
||||
|
||||
public int getOnlinePlayers() {
|
||||
@ -17,13 +29,33 @@ public class BungeeServerInfo {
|
||||
public void setOnlinePlayers(int onlinePlayers) {
|
||||
this.onlinePlayers = onlinePlayers;
|
||||
}
|
||||
|
||||
public int getMaxPlayers() {
|
||||
return maxPlayers;
|
||||
}
|
||||
|
||||
public void setMaxPlayers(int maxPlayers) {
|
||||
this.maxPlayers = maxPlayers;
|
||||
}
|
||||
|
||||
public String getMotd() {
|
||||
return motd;
|
||||
}
|
||||
|
||||
public void setMotd(String motd) {
|
||||
if (motd == null) {
|
||||
motd = "";
|
||||
}
|
||||
|
||||
this.motd = motd;
|
||||
}
|
||||
|
||||
public long getLastRequest() {
|
||||
return lastRequest;
|
||||
}
|
||||
|
||||
public void setLastRequest(long lastRequest) {
|
||||
this.lastRequest = lastRequest;
|
||||
public void updateLastRequest() {
|
||||
this.lastRequest = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,16 +1,28 @@
|
||||
package com.gmail.filoghost.holographicdisplays.bridge.bungeecord;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.io.IOException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import com.gmail.filoghost.holographicdisplays.HolographicDisplays;
|
||||
import com.gmail.filoghost.holographicdisplays.bridge.bungeecord.serverpinger.ServerAddress;
|
||||
import com.gmail.filoghost.holographicdisplays.bridge.bungeecord.serverpinger.ServerPinger;
|
||||
import com.gmail.filoghost.holographicdisplays.bridge.bungeecord.serverpinger.ServerStatus;
|
||||
import com.gmail.filoghost.holographicdisplays.disk.Configuration;
|
||||
import com.gmail.filoghost.holographicdisplays.util.DebugHandler;
|
||||
|
||||
public class BungeeServerTracker {
|
||||
|
||||
private static Map<String, BungeeServerInfo> trackedServers = new HashMap<String, BungeeServerInfo>();
|
||||
private static Map<String, BungeeServerInfo> trackedServers = new ConcurrentHashMap<String, BungeeServerInfo>();
|
||||
private static int taskID = -1;
|
||||
|
||||
private static ServerPinger pinger = HolographicDisplays.isPreNetty() ? ServerPinger.PRE_NETTY_REWRITE : ServerPinger.POST_NETTY_REWRITE;
|
||||
|
||||
public static void resetTrackedServers() {
|
||||
trackedServers.clear();
|
||||
@ -18,9 +30,12 @@ public class BungeeServerTracker {
|
||||
|
||||
public static void track(String server) {
|
||||
if (!trackedServers.containsKey(server)) {
|
||||
BungeeServerInfo info = new BungeeServerInfo(0, System.currentTimeMillis());
|
||||
BungeeServerInfo info = new BungeeServerInfo();
|
||||
trackedServers.put(server, info);
|
||||
BungeeChannel.getInstance().askPlayerCount(server);
|
||||
|
||||
if (!Configuration.pingerEnable) {
|
||||
BungeeChannel.getInstance().askPlayerCount(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,26 +43,76 @@ public class BungeeServerTracker {
|
||||
trackedServers.remove(server);
|
||||
}
|
||||
|
||||
// Handle a successful ping.
|
||||
protected static void handlePing(String server, int online) {
|
||||
protected static BungeeServerInfo getOrCreateServerInfo(String server) {
|
||||
BungeeServerInfo info = trackedServers.get(server);
|
||||
if (info == null) {
|
||||
info = new BungeeServerInfo(online, System.currentTimeMillis());
|
||||
info = new BungeeServerInfo();
|
||||
trackedServers.put(server, info);
|
||||
} else {
|
||||
info.setOnlinePlayers(online);
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
public static int getPlayersOnline(String server) {
|
||||
|
||||
public static String getPlayersOnline(String server) {
|
||||
BungeeServerInfo info = trackedServers.get(server);
|
||||
if (info != null) {
|
||||
info.setLastRequest(System.currentTimeMillis());
|
||||
return info.getOnlinePlayers();
|
||||
info.updateLastRequest();
|
||||
return String.valueOf(info.getOnlinePlayers());
|
||||
} else {
|
||||
// It was not tracked, add it.
|
||||
track(server);
|
||||
return 0;
|
||||
return "[Loading...]";
|
||||
}
|
||||
}
|
||||
|
||||
public static String getMaxPlayers(String server) {
|
||||
|
||||
if (!Configuration.pingerEnable) {
|
||||
return "[Please enable pinger]";
|
||||
}
|
||||
|
||||
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 "[Loading...]";
|
||||
}
|
||||
}
|
||||
|
||||
public static String getMotd(String server) {
|
||||
|
||||
if (!Configuration.pingerEnable) {
|
||||
return "[Please enable pinger]";
|
||||
}
|
||||
|
||||
BungeeServerInfo info = trackedServers.get(server);
|
||||
if (info != null) {
|
||||
info.updateLastRequest();
|
||||
return info.getMotd();
|
||||
} else {
|
||||
// It was not tracked, add it.
|
||||
track(server);
|
||||
return "[Loading...]";
|
||||
}
|
||||
}
|
||||
|
||||
public static String getOnlineStatus(String server) {
|
||||
|
||||
if (!Configuration.pingerEnable) {
|
||||
return "[Please enable pinger]";
|
||||
}
|
||||
|
||||
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 "[Loading...]";
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,10 +127,59 @@ public class BungeeServerTracker {
|
||||
}
|
||||
|
||||
taskID = Bukkit.getScheduler().scheduleSyncRepeatingTask(HolographicDisplays.getInstance(), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (String server : trackedServers.keySet()) {
|
||||
BungeeChannel.getInstance().askPlayerCount(server);
|
||||
|
||||
if (Configuration.pingerEnable) {
|
||||
new BukkitRunnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (Entry<String, ServerAddress> entry : Configuration.pingerServers.entrySet()) {
|
||||
|
||||
BungeeServerInfo serverInfo = getOrCreateServerInfo(entry.getKey());
|
||||
boolean displayOffline = false;
|
||||
|
||||
try {
|
||||
ServerStatus data = pinger.fetchData(entry.getValue(), Configuration.pingerTimeout);
|
||||
if (data.isOnline()) {
|
||||
serverInfo.setOnline(true);
|
||||
serverInfo.setOnlinePlayers(data.getOnlinePlayers());
|
||||
serverInfo.setMaxPlayers(data.getMaxPlayers());
|
||||
serverInfo.setMotd(data.getMotd());
|
||||
} else {
|
||||
displayOffline = true;
|
||||
}
|
||||
} catch (SocketTimeoutException e) {
|
||||
displayOffline = true;
|
||||
} catch (UnknownHostException e) {
|
||||
HolographicDisplays.getInstance().getLogger().warning("Couldn't fetch data from " + entry.getKey() + "(" + entry.getValue().toString() + "): unknown host address.");
|
||||
displayOffline = true;
|
||||
} catch (IOException e) {
|
||||
displayOffline = true;
|
||||
} catch (Exception e) {
|
||||
displayOffline = true;
|
||||
HolographicDisplays.getInstance().getLogger().warning("Couldn't fetch data from " + entry.getKey() + "(" + entry.getValue().toString() + "), unhandled exception: " + e.toString());
|
||||
DebugHandler.handleDebugException(e);
|
||||
}
|
||||
|
||||
if (displayOffline) {
|
||||
serverInfo.setOnline(false);
|
||||
serverInfo.setOnlinePlayers(0);
|
||||
serverInfo.setMaxPlayers(0);
|
||||
serverInfo.setMotd(Configuration.pingerOfflineMotd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.runTaskAsynchronously(HolographicDisplays.getInstance());
|
||||
|
||||
} else {
|
||||
for (String server : trackedServers.keySet()) {
|
||||
BungeeChannel.getInstance().askPlayerCount(server);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}, 0, refreshSeconds * 20);
|
||||
}
|
||||
|
@ -0,0 +1,67 @@
|
||||
package com.gmail.filoghost.holographicdisplays.bridge.bungeecord.serverpinger;
|
||||
|
||||
import java.lang.RuntimeException;
|
||||
import java.io.Closeable;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.Character;
|
||||
import java.lang.String;
|
||||
import java.io.DataOutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
class PacketUtils
|
||||
{
|
||||
public static final Charset UTF16BE = Charset.forName("UTF-16BE");;
|
||||
public static final Charset UTF8 = Charset.forName("UTF-8");
|
||||
|
||||
public static void a(final DataOutputStream out, final String s) throws IOException {
|
||||
final int len = s.length();
|
||||
final byte[] data = new byte[len / 2];
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
data[i / 2] = (byte)((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
|
||||
}
|
||||
out.write(data);
|
||||
}
|
||||
|
||||
public static void writeString(final DataOutputStream out, final String s, final Charset charset) throws IOException {
|
||||
if (charset == PacketUtils.UTF8) {
|
||||
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 e) { }
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package com.gmail.filoghost.holographicdisplays.bridge.bungeecord.serverpinger;
|
||||
|
||||
public class ServerAddress {
|
||||
|
||||
private String ip;
|
||||
private int port;
|
||||
|
||||
public ServerAddress(String ip, int port) {
|
||||
this.ip = ip;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.gmail.filoghost.holographicdisplays.bridge.bungeecord.serverpinger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
|
||||
public abstract class ServerPinger {
|
||||
|
||||
// For 1.7 and higher
|
||||
public static final ServerPinger POST_NETTY_REWRITE = new ServerPingerPostNetty();
|
||||
|
||||
// For 1.6 and lower
|
||||
public static final ServerPinger PRE_NETTY_REWRITE = new ServerPingerPreNetty();
|
||||
|
||||
public abstract ServerStatus fetchData(final ServerAddress serverAddress, int timeout) throws SocketTimeoutException, UnknownHostException, IOException, Exception;
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package com.gmail.filoghost.holographicdisplays.bridge.bungeecord.serverpinger;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
|
||||
final class ServerPingerPostNetty extends ServerPinger {
|
||||
|
||||
@Override
|
||||
public ServerStatus fetchData(final ServerAddress serverAddress, int timeout) throws SocketTimeoutException, UnknownHostException, IOException, Exception {
|
||||
|
||||
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(), PacketUtils.UTF8);
|
||||
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, PacketUtils.UTF8);
|
||||
return new ServerStatus((JSONObject) JSONValue.parse(jsonString));
|
||||
}
|
||||
finally {
|
||||
PacketUtils.closeQuietly(dataOut);
|
||||
PacketUtils.closeQuietly(dataIn);
|
||||
PacketUtils.closeQuietly(socket);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package com.gmail.filoghost.holographicdisplays.bridge.bungeecord.serverpinger;
|
||||
|
||||
import java.lang.Override;
|
||||
import java.io.IOException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.lang.Integer;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.net.Socket;
|
||||
import java.lang.String;
|
||||
|
||||
final class ServerPingerPreNetty extends ServerPinger {
|
||||
|
||||
@Override
|
||||
public ServerStatus fetchData(final ServerAddress serverAddress, int timeout) throws SocketTimeoutException, UnknownHostException, IOException, Exception {
|
||||
|
||||
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());
|
||||
PacketUtils.a(dataOut, "FE");
|
||||
PacketUtils.a(dataOut, "01");
|
||||
dataIn.readByte();
|
||||
dataIn.readByte();
|
||||
final int length = dataIn.readByte() * 2;
|
||||
final byte[] bytes = new byte[length];
|
||||
dataIn.readFully(bytes);
|
||||
socket.close();
|
||||
final String[] info = new String(bytes, PacketUtils.UTF16BE).split(String.valueOf('\0'));
|
||||
final ServerStatus response = new ServerStatus(true, info[3], Integer.parseInt(info[4]), Integer.parseInt(info[5]));
|
||||
// String versionName = info[2];
|
||||
// String protocol = info[1];
|
||||
return response;
|
||||
}
|
||||
finally {
|
||||
PacketUtils.closeQuietly(dataIn);
|
||||
PacketUtils.closeQuietly(dataOut);
|
||||
PacketUtils.closeQuietly(socket);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package com.gmail.filoghost.holographicdisplays.bridge.bungeecord.serverpinger;
|
||||
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class ServerStatus
|
||||
{
|
||||
private boolean isOnline;
|
||||
private String motd;
|
||||
private int onlinePlayers;
|
||||
private int maxPlayers;
|
||||
|
||||
public ServerStatus(boolean isOnline, String motd, int onlinePlayers, int maxPlayers) {
|
||||
this.isOnline = isOnline;
|
||||
this.motd = motd;
|
||||
this.onlinePlayers = onlinePlayers;
|
||||
this.maxPlayers = maxPlayers;
|
||||
}
|
||||
|
||||
public ServerStatus(JSONObject json) {
|
||||
isOnline = true;
|
||||
motd = ((String) json.get("description")).replace("\n", "");
|
||||
|
||||
JSONObject playersJson = (JSONObject) json.get("players");
|
||||
onlinePlayers = ((Long) playersJson.get("online")).intValue();
|
||||
maxPlayers = ((Long) playersJson.get("max")).intValue();
|
||||
}
|
||||
|
||||
public boolean isOnline() {
|
||||
return isOnline;
|
||||
}
|
||||
|
||||
public String getMotd() {
|
||||
return motd;
|
||||
}
|
||||
|
||||
public int getOnlinePlayers() {
|
||||
return onlinePlayers;
|
||||
}
|
||||
|
||||
public int getMaxPlayers() {
|
||||
return maxPlayers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ServerStatus [motd=" + motd + ", onlinePlayers=" + onlinePlayers + ", maxPlayers=" + maxPlayers + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -49,9 +49,9 @@ public class ReloadCommand extends HologramSubCommand {
|
||||
|
||||
long startMillis = System.currentTimeMillis();
|
||||
|
||||
UnicodeSymbols.load(HolographicDisplays.getInstance());
|
||||
Configuration.load(HolographicDisplays.getInstance());
|
||||
BungeeServerTracker.startTask(Configuration.bungeeRefreshSeconds);
|
||||
UnicodeSymbols.load(HolographicDisplays.getInstance());
|
||||
HologramDatabase.loadYamlFile(HolographicDisplays.getInstance());
|
||||
AnimationsRegister.loadAnimations(HolographicDisplays.getInstance());
|
||||
PlaceholdersManager.untrackAll();
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.gmail.filoghost.holographicdisplays.disk;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public enum ConfigNode {
|
||||
|
||||
SPACE_BETWEEN_LINES("space-between-lines", 0.02),
|
||||
@ -9,6 +11,12 @@ public enum ConfigNode {
|
||||
UPDATE_NOTIFICATION("update-notification", true),
|
||||
BUNGEE_REFRESH_SECONDS("bungee.refresh-seconds", 3),
|
||||
BUNGEE_USE_REDIS_BUNGEE("bungee.use-RedisBungee", false),
|
||||
BUNGEE_USE_FULL_PINGER("bungee.pinger.enable", false),
|
||||
BUNGEE_PINGER_TIMEOUT("bungee.pinger.timeout", 2000),
|
||||
BUNGEE_PINGER_OFFLINE_MOTD("bungee.pinger.offline-motd", "&cOffline, couldn't get the MOTD."),
|
||||
BUNGEE_PINGER_ONLINE_FORMAT("bungee.pinger.status.online", "&aOnline"),
|
||||
BUNGEE_PINGER_OFFLINE_FORMAT("bungee.pinger.status.offline", "&cOffline"),
|
||||
BUNGEE_PINGER_SERVERS("bungee.pinger.servers", Arrays.asList("hub: 127.0.0.1:25565", "survival: 127.0.0.1:25566", "minigames: 127.0.0.1:25567")),
|
||||
TIME_FORMAT("time.format", "H:mm"),
|
||||
TIME_ZONE("time.zone", "GMT+1"),
|
||||
DEBUG("debug", false);
|
||||
|
@ -5,6 +5,7 @@ import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
@ -12,6 +13,7 @@ import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.gmail.filoghost.holographicdisplays.bridge.bungeecord.serverpinger.ServerAddress;
|
||||
import com.gmail.filoghost.holographicdisplays.util.Utils;
|
||||
|
||||
/**
|
||||
@ -29,10 +31,15 @@ public class Configuration {
|
||||
public static SimpleDateFormat timeFormat;
|
||||
|
||||
public static int bungeeRefreshSeconds;
|
||||
public static String bungeeOnlineFormat;
|
||||
public static String bungeeOfflineFormat;
|
||||
public static boolean useRedisBungee;
|
||||
|
||||
public static boolean pingerEnable;
|
||||
public static int pingerTimeout;
|
||||
public static Map<String, ServerAddress> pingerServers;
|
||||
public static String pingerOfflineMotd;
|
||||
public static String pingerStatusOnline;
|
||||
public static String pingerStatusOffline;
|
||||
|
||||
public static boolean debug;
|
||||
|
||||
|
||||
@ -112,6 +119,50 @@ public class Configuration {
|
||||
transparencySymbol = StringConverter.toReadableFormat(config.getString(ConfigNode.TRANSPARENCY_SPACE.getPath()));
|
||||
bungeeRefreshSeconds = config.getInt(ConfigNode.BUNGEE_REFRESH_SECONDS.getPath());
|
||||
useRedisBungee = config.getBoolean(ConfigNode.BUNGEE_USE_REDIS_BUNGEE.getPath());
|
||||
pingerEnable = config.getBoolean(ConfigNode.BUNGEE_USE_FULL_PINGER.getPath());
|
||||
pingerTimeout = config.getInt(ConfigNode.BUNGEE_PINGER_TIMEOUT.getPath());
|
||||
|
||||
pingerOfflineMotd = StringConverter.toReadableFormat(config.getString(ConfigNode.BUNGEE_PINGER_OFFLINE_MOTD.getPath()));
|
||||
pingerStatusOnline = StringConverter.toReadableFormat(config.getString(ConfigNode.BUNGEE_PINGER_ONLINE_FORMAT.getPath()));
|
||||
pingerStatusOffline = StringConverter.toReadableFormat(config.getString(ConfigNode.BUNGEE_PINGER_OFFLINE_FORMAT.getPath()));
|
||||
|
||||
if (pingerTimeout <= 0) {
|
||||
pingerTimeout = 1;
|
||||
}
|
||||
|
||||
pingerServers = Utils.newMap();
|
||||
|
||||
if (pingerEnable) {
|
||||
for (String singleServer : config.getStringList(ConfigNode.BUNGEE_PINGER_SERVERS.getPath())) {
|
||||
String[] nameAndAddress = singleServer.split(":", 2);
|
||||
if (nameAndAddress.length < 2) {
|
||||
plugin.getLogger().warning("The server info \"" + singleServer + "\" is not valid. There should be a name and an address, separated by a colon.");
|
||||
continue;
|
||||
}
|
||||
|
||||
String name = nameAndAddress[0].trim();
|
||||
String address = nameAndAddress[1].replace(" ", "");
|
||||
|
||||
String ip;
|
||||
int port;
|
||||
|
||||
if (address.contains(":")) {
|
||||
String[] ipAndPort = address.split(":", 2);
|
||||
ip = ipAndPort[0];
|
||||
try {
|
||||
port = Integer.parseInt(ipAndPort[1]);
|
||||
} catch (NumberFormatException e) {
|
||||
plugin.getLogger().warning("Invalid port number in the server info \"" + singleServer + "\".");
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
ip = address;
|
||||
port = 25565; // The default Minecraft port.
|
||||
}
|
||||
|
||||
pingerServers.put(name, new ServerAddress(ip, port));
|
||||
}
|
||||
}
|
||||
|
||||
debug = config.getBoolean(ConfigNode.DEBUG.getPath());
|
||||
|
||||
|
@ -23,6 +23,9 @@ public class PlaceholdersManager {
|
||||
protected static Set<DynamicLineData> linesToUpdate = Utils.newSet();
|
||||
|
||||
private static final Pattern BUNGEE_ONLINE_PATTERN = makePlaceholderWithArgsPattern("online");
|
||||
private static final Pattern BUNGEE_MAX_PATTERN = makePlaceholderWithArgsPattern("max");
|
||||
private static final Pattern BUNGEE_MOTD_PATTERN = makePlaceholderWithArgsPattern("motd");
|
||||
private static final Pattern BUNGEE_STATUS_PATTERN = makePlaceholderWithArgsPattern("status");
|
||||
private static final Pattern ANIMATION_PATTERN = makePlaceholderWithArgsPattern("animation");
|
||||
private static final Pattern WORLD_PATTERN = makePlaceholderWithArgsPattern("world");
|
||||
|
||||
@ -113,6 +116,10 @@ public class PlaceholdersManager {
|
||||
Set<Placeholder> normalPlaceholders = null;
|
||||
|
||||
Map<String, PlaceholderReplacer> bungeeOnlinePlayersReplacers = null;
|
||||
Map<String, PlaceholderReplacer> bungeeMaxPlayersReplacers = null;
|
||||
Map<String, PlaceholderReplacer> bungeeStatusReplacers = null;
|
||||
Map<String, PlaceholderReplacer> bungeeMotdReplacers = null;
|
||||
|
||||
Map<String, PlaceholderReplacer> worldsOnlinePlayersReplacers = null;
|
||||
Map<String, Placeholder> animationsPlaceholders = null;
|
||||
|
||||
@ -165,11 +172,75 @@ public class PlaceholdersManager {
|
||||
|
||||
@Override
|
||||
public String update() {
|
||||
return String.valueOf(BungeeServerTracker.getPlayersOnline(serverName));
|
||||
return BungeeServerTracker.getPlayersOnline(serverName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// BungeeCord max players pattern.
|
||||
matcher = BUNGEE_MAX_PATTERN.matcher(name);
|
||||
while (matcher.find()) {
|
||||
|
||||
if (bungeeMaxPlayersReplacers == null) {
|
||||
bungeeMaxPlayersReplacers = Utils.newMap();
|
||||
}
|
||||
|
||||
final String serverName = extractArgumentFromPlaceholder(matcher);
|
||||
BungeeServerTracker.track(serverName); // Track this server.
|
||||
|
||||
// Add it to tracked servers.
|
||||
bungeeMaxPlayersReplacers.put(matcher.group(), new PlaceholderReplacer() {
|
||||
|
||||
@Override
|
||||
public String update() {
|
||||
return BungeeServerTracker.getMaxPlayers(serverName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// BungeeCord motd pattern.
|
||||
matcher = BUNGEE_MOTD_PATTERN.matcher(name);
|
||||
while (matcher.find()) {
|
||||
|
||||
if (bungeeMotdReplacers == null) {
|
||||
bungeeMotdReplacers = Utils.newMap();
|
||||
}
|
||||
|
||||
final String serverName = extractArgumentFromPlaceholder(matcher);
|
||||
BungeeServerTracker.track(serverName); // Track this server.
|
||||
|
||||
// Add it to tracked servers.
|
||||
bungeeMotdReplacers.put(matcher.group(), new PlaceholderReplacer() {
|
||||
|
||||
@Override
|
||||
public String update() {
|
||||
return BungeeServerTracker.getMotd(serverName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// BungeeCord status pattern.
|
||||
matcher = BUNGEE_STATUS_PATTERN.matcher(name);
|
||||
while (matcher.find()) {
|
||||
|
||||
if (bungeeStatusReplacers == null) {
|
||||
bungeeStatusReplacers = Utils.newMap();
|
||||
}
|
||||
|
||||
final String serverName = extractArgumentFromPlaceholder(matcher);
|
||||
BungeeServerTracker.track(serverName); // Track this server.
|
||||
|
||||
// Add it to tracked servers.
|
||||
bungeeStatusReplacers.put(matcher.group(), new PlaceholderReplacer() {
|
||||
|
||||
@Override
|
||||
public String update() {
|
||||
return BungeeServerTracker.getOnlineStatus(serverName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Animation pattern.
|
||||
matcher = ANIMATION_PATTERN.matcher(name);
|
||||
while (matcher.find()) {
|
||||
@ -192,7 +263,8 @@ public class PlaceholdersManager {
|
||||
}
|
||||
}
|
||||
|
||||
if (normalPlaceholders != null || bungeeOnlinePlayersReplacers != null || worldsOnlinePlayersReplacers != null || animationsPlaceholders != null) {
|
||||
if (Utils.isThereNonNull(normalPlaceholders, bungeeOnlinePlayersReplacers, bungeeMaxPlayersReplacers, bungeeMotdReplacers, bungeeStatusReplacers, worldsOnlinePlayersReplacers, animationsPlaceholders)) {
|
||||
|
||||
DynamicLineData lineData = new DynamicLineData(nameableEntity, name);
|
||||
|
||||
if (normalPlaceholders != null) {
|
||||
@ -203,6 +275,18 @@ public class PlaceholdersManager {
|
||||
lineData.getReplacers().putAll(bungeeOnlinePlayersReplacers);
|
||||
}
|
||||
|
||||
if (bungeeMaxPlayersReplacers != null) {
|
||||
lineData.getReplacers().putAll(bungeeMaxPlayersReplacers);
|
||||
}
|
||||
|
||||
if (bungeeMotdReplacers != null) {
|
||||
lineData.getReplacers().putAll(bungeeMotdReplacers);
|
||||
}
|
||||
|
||||
if (bungeeStatusReplacers != null) {
|
||||
lineData.getReplacers().putAll(bungeeStatusReplacers);
|
||||
}
|
||||
|
||||
if (worldsOnlinePlayersReplacers != null) {
|
||||
lineData.getReplacers().putAll(worldsOnlinePlayersReplacers);
|
||||
}
|
||||
@ -236,19 +320,19 @@ public class PlaceholdersManager {
|
||||
|
||||
if (!lineData.getPlaceholders().isEmpty()) {
|
||||
for (Placeholder placeholder : lineData.getPlaceholders()) {
|
||||
newCustomName = newCustomName.replace(placeholder.getTextPlaceholder(), placeholder.getCurrentReplacement());
|
||||
newCustomName = newCustomName.replace(placeholder.getTextPlaceholder(), Utils.sanitize(placeholder.getCurrentReplacement()));
|
||||
}
|
||||
}
|
||||
|
||||
if (!lineData.getReplacers().isEmpty()) {
|
||||
for (Entry<String, PlaceholderReplacer> entry : lineData.getReplacers().entrySet()) {
|
||||
newCustomName = newCustomName.replace(entry.getKey(), entry.getValue().update());
|
||||
newCustomName = newCustomName.replace(entry.getKey(), Utils.sanitize(entry.getValue().update()));
|
||||
}
|
||||
}
|
||||
|
||||
if (!lineData.getAnimations().isEmpty()) {
|
||||
for (Entry<String, Placeholder> entry : lineData.getAnimations().entrySet()) {
|
||||
newCustomName = newCustomName.replace(entry.getKey(), entry.getValue().getCurrentReplacement());
|
||||
newCustomName = newCustomName.replace(entry.getKey(), Utils.sanitize(entry.getValue().getCurrentReplacement()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import java.util.Map.Entry;
|
||||
|
||||
import com.gmail.filoghost.holographicdisplays.bridge.bungeecord.BungeeServerInfo;
|
||||
import com.gmail.filoghost.holographicdisplays.bridge.bungeecord.BungeeServerTracker;
|
||||
import com.gmail.filoghost.holographicdisplays.util.DebugHandler;
|
||||
|
||||
/**
|
||||
* A task to remove unused server data in the server tracker.
|
||||
@ -16,12 +17,14 @@ public class BungeeCleanupTask implements Runnable {
|
||||
|
||||
Iterator<Entry<String, BungeeServerInfo>> iter = BungeeServerTracker.getTrackedServers().entrySet().iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
long lastRequest = iter.next().getValue().getLastRequest();
|
||||
while (iter.hasNext()) {
|
||||
Entry<String, BungeeServerInfo> next = iter.next();
|
||||
long lastRequest = next.getValue().getLastRequest();
|
||||
|
||||
if (lastRequest != 0 && System.currentTimeMillis() - lastRequest > 600000) { // 10 * 60 * 1000 = 10 minutes.
|
||||
// Don't track that server anymore.
|
||||
iter.remove();
|
||||
DebugHandler.logToConsole("Untracked bungee server \"" + next.getKey() + "\" due to inactivity.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,15 +6,25 @@ import com.gmail.filoghost.holographicdisplays.disk.Configuration;
|
||||
|
||||
public class DebugHandler {
|
||||
|
||||
public static void handleSpawnFail(HologramLine parentPiece) {
|
||||
public static void logToConsole(String msg) {
|
||||
if (Configuration.debug) {
|
||||
HolographicDisplays.getInstance().getLogger().warning("[Debug] Coulnd't spawn entity for this hologram: " + parentPiece.getParent().toString());
|
||||
HolographicDisplays.getInstance().getLogger().info("[Debug] " + msg);
|
||||
}
|
||||
}
|
||||
|
||||
public static void handleAnimationLoadSuccess(String name, double speed) {
|
||||
logToConsole("Successfully loaded animation '" + name + "', speed = " + speed + ".");
|
||||
}
|
||||
|
||||
public static void handleSpawnFail(HologramLine parentPiece) {
|
||||
if (Configuration.debug) {
|
||||
HolographicDisplays.getInstance().getLogger().info("[Debug] Successfully loaded animation '" + name + "', speed = " + speed + ".");
|
||||
HolographicDisplays.getInstance().getLogger().severe("[Debug] Coulnd't spawn entity for this hologram: " + parentPiece.getParent().toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static void handleDebugException(Exception e) {
|
||||
if (Configuration.debug) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,4 +106,22 @@ public class Utils extends Object {
|
||||
public static String join(List<String> elements, String separator) {
|
||||
return join(elements, separator, 0, elements.size());
|
||||
}
|
||||
|
||||
public static String sanitize(String s) {
|
||||
return s != null ? s : "null";
|
||||
}
|
||||
|
||||
public static boolean isThereNonNull(Object... objects) {
|
||||
if (objects == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
if (objects[i] != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user