From cfa513a4f8bec1f21628718ef33dfd72573f9116 Mon Sep 17 00:00:00 2001 From: LAX1DUDE Date: Sat, 2 Apr 2022 01:25:36 -0700 Subject: [PATCH] Initial commit (1.0.0) --- .gitignore | 3 + .project | 17 + EaglerMOTD.jar | Bin 0 -> 53868 bytes README.md | 29 ++ src/default_frames.json | 42 ++ src/default_messages.json | 25 ++ src/default_queries.json | 37 ++ .../eaglercraft/eaglermotd/BitmapFile.java | 109 +++++ .../eaglermotd/CommandMOTDReload.java | 26 ++ .../eaglercraft/eaglermotd/EaglerMOTD.java | 396 ++++++++++++++++++ .../eaglermotd/MOTDConnection.java | 285 +++++++++++++ .../eaglercraft/eaglermotd/MessagePool.java | 50 +++ .../eaglermotd/MessagePoolEntry.java | 34 ++ .../eaglercraft/eaglermotd/QueryCache.java | 157 +++++++ .../eaglercraft/eaglermotd/QueryType.java | 109 +++++ src/plugin.yml | 4 + src/server-icons-test.png | Bin 0 -> 27162 bytes 17 files changed, 1323 insertions(+) create mode 100644 .gitignore create mode 100644 .project create mode 100644 EaglerMOTD.jar create mode 100644 README.md create mode 100644 src/default_frames.json create mode 100644 src/default_messages.json create mode 100644 src/default_queries.json create mode 100644 src/net/lax1dude/eaglercraft/eaglermotd/BitmapFile.java create mode 100644 src/net/lax1dude/eaglercraft/eaglermotd/CommandMOTDReload.java create mode 100644 src/net/lax1dude/eaglercraft/eaglermotd/EaglerMOTD.java create mode 100644 src/net/lax1dude/eaglercraft/eaglermotd/MOTDConnection.java create mode 100644 src/net/lax1dude/eaglercraft/eaglermotd/MessagePool.java create mode 100644 src/net/lax1dude/eaglercraft/eaglermotd/MessagePoolEntry.java create mode 100644 src/net/lax1dude/eaglercraft/eaglermotd/QueryCache.java create mode 100644 src/net/lax1dude/eaglercraft/eaglermotd/QueryType.java create mode 100644 src/plugin.yml create mode 100644 src/server-icons-test.png diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9a6133b --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/.settings/ +/bin/ +.classpath \ No newline at end of file diff --git a/.project b/.project new file mode 100644 index 0000000..f1d8b60 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + EaglerMOTD + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/EaglerMOTD.jar b/EaglerMOTD.jar new file mode 100644 index 0000000000000000000000000000000000000000..6afe606f0c96ccc60f465f23ece6c3a74d842ca6 GIT binary patch literal 53868 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 bitmapCache = new HashMap(); + + public static BitmapFile getCachedIcon(String name) { + BitmapFile ret = bitmapCache.get(name); + if(ret == null) { + File f = new File(name); + if(f.exists()) { + try { + BufferedImage img = ImageIO.read(f); + int w = img.getWidth(); + int h = img.getHeight(); + if(w < 64 || h < 64) { + System.err.println("[EaglerMOTD] Icon '" + name + "' must be at least be 64x64 pixels large (it is " + w + "x" + h + ")"); + }else { + int[][] load = new int[w][h]; + for(int y = 0; y < h; ++y) { + for(int x = 0; x < w; ++x) { + load[x][y] = img.getRGB(x, y); + } + } + ret = new BitmapFile(name, load, w, h); + bitmapCache.put(name, ret); + } + } catch (IOException e) { + System.err.println("[EaglerMOTD] Could not load icon file: '" + name + "'"); + System.err.println("[EaglerMOTD] Place the file in the same directory as 'messages.json'"); + e.printStackTrace(); + } + } + } + return ret; + } + + public int[] getSprite(int x, int y) { + if(x < 0 || y < 0) { + return null; + } + int offsetX = x * 64; + int offsetY = y * 64; + if(offsetX + 64 > w || offsetY + 64 > h) { + return null; + } + int[] ret = new int[64 * 64]; + for(int i = 0; i < ret.length; ++i) { + int xx = i % 64; + int yy = i / 64; + ret[i] = frame[offsetX + xx][offsetY + yy]; + } + return ret; + } + + public static int[] makeColor(int[] in, float r, float g, float b, float a) { + int c = ((int)(a*255.0f) << 24) | ((int)(r*255.0f) << 16) | ((int)(g*255.0f) << 8) | (int)(b*255.0f); + for(int i = 0; i < in.length; ++i) { + in[i] = c; + } + return in; + } + + public static int[] applyColor(int[] in, float r, float g, float b, float a) { + for(int i = 0; i < in.length; ++i) { + float rr = ((in[i] >> 16) & 0xFF) / 255.0f; + float gg = ((in[i] >> 8) & 0xFF) / 255.0f; + float bb = (in[i] & 0xFF) / 255.0f; + float aa = ((in[i] >> 24) & 0xFF) / 255.0f; + rr = r * a + rr * (1.0f - a); + gg = g * a + gg * (1.0f - a); + bb = b * a + bb * (1.0f - a); + aa = a + aa * (1.0f - a); + in[i] = ((int)(aa*255.0f) << 24) | ((int)(rr*255.0f) << 16) | ((int)(gg*255.0f) << 8) | (int)(bb*255.0f); + } + return in; + } + + public static int[] applyTint(int[] in, float r, float g, float b, float a) { + for(int i = 0; i < in.length; ++i) { + float rr = ((in[i] >> 16) & 0xFF) / 255.0f * r; + float gg = ((in[i] >> 8) & 0xFF) / 255.0f * g; + float bb = (in[i] & 0xFF) / 255.0f * b; + float aa = ((in[i] >> 24) & 0xFF) / 255.0f * a; + in[i] = ((int)(aa*255.0f) << 24) | ((int)(rr*255.0f) << 16) | ((int)(gg*255.0f) << 8) | (int)(bb*255.0f); + } + return in; + } + +} diff --git a/src/net/lax1dude/eaglercraft/eaglermotd/CommandMOTDReload.java b/src/net/lax1dude/eaglercraft/eaglermotd/CommandMOTDReload.java new file mode 100644 index 0000000..e32be68 --- /dev/null +++ b/src/net/lax1dude/eaglercraft/eaglermotd/CommandMOTDReload.java @@ -0,0 +1,26 @@ +package net.lax1dude.eaglercraft.eaglermotd; + +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.plugin.Command; + +public class CommandMOTDReload extends Command { + + public final EaglerMOTD plugin; + + public CommandMOTDReload(EaglerMOTD plugin) { + super("motd-reload", "eaglermotd.command.reload"); + this.plugin = plugin; + } + + @Override + public void execute(CommandSender paramCommandSender, String[] paramArrayOfString) { + try { + plugin.loadConfiguration(paramCommandSender); + } catch (Exception e) { + paramCommandSender.sendMessage(ChatColor.RED + "[EaglerMOTD] Failed to reload! " + e.toString()); + e.printStackTrace(); + } + } + +} diff --git a/src/net/lax1dude/eaglercraft/eaglermotd/EaglerMOTD.java b/src/net/lax1dude/eaglercraft/eaglermotd/EaglerMOTD.java new file mode 100644 index 0000000..5284cd9 --- /dev/null +++ b/src/net/lax1dude/eaglercraft/eaglermotd/EaglerMOTD.java @@ -0,0 +1,396 @@ +package net.lax1dude.eaglercraft.eaglermotd; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; + +import org.json.JSONArray; +import org.json.JSONObject; + +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.config.ListenerInfo; +import net.md_5.bungee.api.event.WebsocketMOTDEvent; +import net.md_5.bungee.api.event.WebsocketQueryEvent; +import net.md_5.bungee.api.plugin.Listener; +import net.md_5.bungee.api.plugin.Plugin; +import net.md_5.bungee.command.ConsoleCommandSender; +import net.md_5.bungee.eaglercraft.BanList; +import net.md_5.bungee.event.EventHandler; + +public class EaglerMOTD extends Plugin implements Listener { + + public static final Map> messages = new HashMap(); + public static final Map messagePools = new HashMap(); + public static final Map framesCache = new HashMap(); + public static final Map queryTypes = new HashMap(); + public static EaglerMOTD instance = null; + public static int close_socket_after = 1200; + public static int max_sockets_per_ip = 10; + public static int max_total_sockets = 256; + public static boolean allow_banned_ips = false; + + public final Timer tickTimer = new Timer("MOTD Tick Timer"); + public final List motdConnections = new LinkedList(); + + public EaglerMOTD() { + instance = this; + } + + public void loadConfiguration(CommandSender cs) throws Exception { + messages.clear(); + messagePools.clear(); + framesCache.clear(); + queryTypes.clear(); + + BitmapFile.bitmapCache.clear(); + QueryCache.flush(); + + synchronized(motdConnections) { + if(motdConnections.size() > 0) { + for(MOTDConnection con : motdConnections) { + con.close(); + } + motdConnections.clear(); + } + } + + getDataFolder().mkdirs(); + + byte[] damn = new byte[4096]; + int i; + + File msgs = new File(getDataFolder(), "messages.json"); + + if(!msgs.exists()) { + OutputStream msgsNew = new FileOutputStream(msgs); + InputStream msgsDefault = EaglerMOTD.class.getResourceAsStream("/default_messages.json"); + while((i = msgsDefault.read(damn)) != -1) { + msgsNew.write(damn, 0, i); + } + msgsNew.close(); + msgsDefault.close(); + File f2 = new File(getDataFolder(), "frames.json"); + if(!f2.exists()) { + msgsNew = new FileOutputStream(f2); + msgsDefault = EaglerMOTD.class.getResourceAsStream("/default_frames.json"); + while((i = msgsDefault.read(damn)) != -1) { + msgsNew.write(damn, 0, i); + } + msgsNew.close(); + msgsDefault.close(); + } + f2 = new File(getDataFolder(), "queries.json"); + if(!f2.exists()) { + msgsNew = new FileOutputStream(f2); + msgsDefault = EaglerMOTD.class.getResourceAsStream("/default_queries.json"); + while((i = msgsDefault.read(damn)) != -1) { + msgsNew.write(damn, 0, i); + } + msgsNew.close(); + msgsDefault.close(); + } + f2 = new File("server-animation.png"); + if(!f2.exists()) { + msgsNew = new FileOutputStream(f2); + msgsDefault = EaglerMOTD.class.getResourceAsStream("/server-icons-test.png"); + while((i = msgsDefault.read(damn)) != -1) { + msgsNew.write(damn, 0, i); + } + msgsNew.close(); + msgsDefault.close(); + } + } + if(!msgs.exists()) { + throw new NullPointerException("messages.json is missing and could not be created"); + } + + InputStream is = new FileInputStream(msgs); + ByteArrayOutputStream bao = new ByteArrayOutputStream(is.available()); + while((i = is.read(damn)) != -1) { + bao.write(damn, 0, i); + } + is.close(); + + JSONObject msgsObj = new JSONObject(new String(bao.toByteArray(), StandardCharsets.UTF_8)); + framesCache.put("messages", msgsObj); + close_socket_after = msgsObj.optInt("close_socket_after", 1200); + max_sockets_per_ip = msgsObj.optInt("max_sockets_per_ip", 10); + max_total_sockets = msgsObj.optInt("max_total_sockets", 256); + allow_banned_ips = msgsObj.optBoolean("allow_banned_ips", false); + msgsObj = msgsObj.getJSONObject("messages"); + + for(String ss : msgsObj.keySet()) { + try { + List poolEntries = new LinkedList(); + JSONArray arr = msgsObj.getJSONArray(ss); + for(int j = 0, l = arr.length(); j < l; ++j) { + JSONObject entry = arr.getJSONObject(j); + List frames = new LinkedList(); + JSONArray framesJSON = entry.getJSONArray("frames"); + for(int k = 0, l2 = framesJSON.length(); k < l2; ++k) { + JSONObject frame = resolveFrame(framesJSON.getString(k), cs); + if(frame != null) { + frames.add(frame); + } + } + if(frames.size() > 0) { + poolEntries.add(new MessagePoolEntry(entry.optInt("interval", 0), entry.optInt("timeout", 500), + entry.optBoolean("random", false), entry.optBoolean("shuffle", false), entry.optFloat("weight", 1.0f), + entry.optString("next", null), frames, entry.optString("name", null))); + }else { + cs.sendMessage(ChatColor.RED + "[EaglerMOTD] Message '" + ss + "' has no frames!"); + } + } + if(poolEntries.size() > 0) { + List existingList = messages.get(ss); + if(existingList == null) { + existingList = poolEntries; + messages.put(ss, existingList); + }else { + existingList.addAll(poolEntries); + } + } + }catch(Throwable t) { + cs.sendMessage(ChatColor.RED + "[EaglerMOTD] Could not parse messages for '" + ss + "' " + t.toString()); + } + } + + Collection listeners = getProxy().getConfigurationAdapter().getListeners(); + + String flag = null; + for(String s : messages.keySet()) { + if(!s.equals("all")) { + boolean flag2 = false; + for(ListenerInfo l : listeners) { + if(s.equals(makeListenerString(l.getHost()))) { + flag2 = true; + } + } + if(!flag2) { + flag = s; + break; + } + } + } + + if(flag != null) { + cs.sendMessage(ChatColor.RED + "[EaglerMOTD] Listener '" + flag + "' does not exist!"); + String hostsString = ""; + for(ListenerInfo l : listeners) { + if(hostsString.length() > 0) { + hostsString += " "; + } + hostsString += makeListenerString(l.getHost()); + } + cs.sendMessage(ChatColor.RED + "[EaglerMOTD] Listeners configured: " + ChatColor.YELLOW + hostsString); + } + + for(ListenerInfo l : listeners) { + String name = makeListenerString(l.getHost()); + MessagePool m = new MessagePool(name); + List e = messages.get("all"); + if(e != null) { + m.messagePool.addAll(e); + } + e = messages.get(name); + if(e != null) { + m.messagePool.addAll(e); + } + if(m.messagePool.size() > 0) { + cs.sendMessage(ChatColor.GREEN + "[EaglerMOTD] Loaded " + m.messagePool.size() + " messages for " + name); + messagePools.put(name, m); + } + } + + msgs = new File(getDataFolder(), "queries.json"); + if(msgs.exists()) { + try { + is = new FileInputStream(msgs); + bao = new ByteArrayOutputStream(is.available()); + while((i = is.read(damn)) != -1) { + bao.write(damn, 0, i); + } + is.close(); + JSONObject queriesObject = new JSONObject(new String(bao.toByteArray(), StandardCharsets.UTF_8)); + JSONObject queriesQueriesObject = queriesObject.getJSONObject("queries"); + for(String s : queriesQueriesObject.keySet()) { + queryTypes.put(s.toLowerCase(), new QueryType(s, queriesQueriesObject.getJSONObject(s))); + } + if(queryTypes.size() > 0) { + cs.sendMessage(ChatColor.GREEN + "[EaglerMOTD] Loaded " + queryTypes.size() + " query types"); + } + }catch(Throwable t) { + cs.sendMessage(ChatColor.RED + "[EaglerMOTD] Queries were not loaded: " + t.toString()); + } + } + + } + + public static String makeListenerString(InetSocketAddress addr) { + InetAddress addrHost = addr.getAddress(); + if(addrHost instanceof Inet6Address) { + return "[" + addrHost.getHostAddress() + "]:" + addr.getPort(); + }else { + return addrHost.getHostAddress() + ":" + addr.getPort(); + } + } + + public JSONObject resolveFrame(String s, CommandSender cs) { + int i = s.indexOf('.'); + if(i == -1) { + cs.sendMessage(ChatColor.RED + "[EaglerMOTD] Frame '" + s + "' cannot be found! (it does not specify a filename)"); + return null; + } + String f = s.substring(0, i); + JSONObject fc = framesCache.get(f); + if(fc == null) { + File ff = new File(getDataFolder(), f + ".json"); + if(!ff.exists()) { + cs.sendMessage(ChatColor.RED + "[EaglerMOTD] File '" + f + ".json' cannot be found!"); + return null; + } + try { + byte[] damn = new byte[4096]; + InputStream is = new FileInputStream(ff); + ByteArrayOutputStream bao = new ByteArrayOutputStream(is.available()); + int j; + while((j = is.read(damn)) != -1) { + bao.write(damn, 0, j); + } + is.close(); + fc = new JSONObject(new String(bao.toByteArray(), StandardCharsets.UTF_8)); + framesCache.put(f, fc); + }catch(Throwable t) { + cs.sendMessage(ChatColor.RED + "[EaglerMOTD] File '" + f + ".json' could not be loaded: " + t.toString()); + return null; + } + } + f = s.substring(i + 1).trim(); + if(fc.has(f)) { + return fc.getJSONObject(f); + }else { + cs.sendMessage(ChatColor.RED + "[EaglerMOTD] Frame '" + s + "' cannot be found!"); + return null; + } + } + + public void showRunCmd(CommandSender cs) { + cs.sendMessage(ChatColor.YELLOW + "[EaglerMOTD] Use /motd-reload to reload your MOTD config files"); + } + + public void onLoad() { + try { + getProxy().getPluginManager().registerCommand(this, new CommandMOTDReload(this)); + loadConfiguration(ConsoleCommandSender.getInstance()); + } catch (Exception e) { + System.err.println("[EaglerMOTD] Could not load!"); + e.printStackTrace(); + } + } + + public void onEnable() { + getProxy().getPluginManager().registerListener(this, this); + tickTimer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + synchronized(motdConnections) { + Iterator itr = motdConnections.iterator(); + while(itr.hasNext()) { + MOTDConnection c = itr.next(); + try { + if(!c.tick()) { + itr.remove(); + } + }catch(Throwable t) { + System.err.println("Error ticking MOTD '" + (c.currentMessage == null ? "null" : c.currentMessage.name) + "' on listener " + c.listenerName); + t.printStackTrace(); + c.close(); + itr.remove(); + } + } + } + } + + }, 0, 50l); + } + + public void onDisable() { + tickTimer.cancel(); + } + + @EventHandler + public void onMOTD(WebsocketMOTDEvent evt) { + MOTDConnection con = new MOTDConnection(evt.getListener(), evt.getMOTD()); + if(con.execute()) { + synchronized(motdConnections) { + while(motdConnections.size() >= max_total_sockets) { + MOTDConnection c = motdConnections.remove(0); + c.close(); + } + } + InetAddress addr = con.motd.getRemoteAddress(); + boolean flag = false; + for(BanList.IPBan b : BanList.blockedBans) { + if(b.checkBan(addr)) { + flag = true; + break; + } + } + if(flag) { + synchronized(motdConnections) { + motdConnections.add(con); + } + }else { + if(allow_banned_ips || !BanList.checkIpBanned(addr).isBanned()) { + synchronized(motdConnections) { + int i = 0; + int c = 0; + while(i < motdConnections.size()) { + if(motdConnections.get(i).motd.getRemoteAddress().equals(addr)) { + ++c; + if(c >= max_sockets_per_ip) { + motdConnections.remove(i).close(); + --i; + } + } + ++i; + } + motdConnections.add(0, con); + } + }else { + con.motd.keepAlive(false); + } + } + } + } + + @EventHandler + public void onQuery(WebsocketQueryEvent evt) { + if(evt.getQuery().isClosed() || evt.getAccept().equalsIgnoreCase("MOTD")) { + return; + } + QueryType t = queryTypes.get(evt.getAccept().toLowerCase()); + if(t != null) { + t.doQuery(evt.getQuery()); + } + } + +} diff --git a/src/net/lax1dude/eaglercraft/eaglermotd/MOTDConnection.java b/src/net/lax1dude/eaglercraft/eaglermotd/MOTDConnection.java new file mode 100644 index 0000000..bdb35ad --- /dev/null +++ b/src/net/lax1dude/eaglercraft/eaglermotd/MOTDConnection.java @@ -0,0 +1,285 @@ +package net.lax1dude.eaglercraft.eaglermotd; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Random; + +import org.json.JSONArray; +import org.json.JSONObject; + +import net.md_5.bungee.BungeeCord; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.MOTD; +import net.md_5.bungee.api.config.ListenerInfo; +import net.md_5.bungee.api.connection.ProxiedPlayer; + +public class MOTDConnection { + + public final ListenerInfo listener; + public final String listenerName; + public final MOTD motd; + + public MessagePoolEntry currentMessage = null; + public int messageTimeTimer = 0; + public int messageIntervalTimer = 0; + public int currentFrame = 0; + public int ageTimer = 0; + + public BitmapFile bitmap = null; + public int spriteX = 0; + public int spriteY = 0; + public float[] color = new float[] { 0.0f, 0.0f, 0.0f, 0.0f }; + public float[] tint = new float[] { 0.0f, 0.0f, 0.0f, 0.0f }; + + private Random rand = null; + + public MOTDConnection(ListenerInfo l, MOTD m) { + this.motd = m; + this.listener = l; + this.listenerName = EaglerMOTD.makeListenerString(l.getHost()); + } + + public boolean execute() { + MessagePool p = EaglerMOTD.messagePools.get(listenerName); + if(p == null) { + return false; + } + + messageTimeTimer = 0; + messageIntervalTimer = 0; + currentMessage = p.pickDefault(); + if(currentMessage.random || currentMessage.shuffle) { + rand = new Random(); + } + + currentFrame = currentMessage.random ? rand.nextInt(currentMessage.frames.size()) : 0; + + applyFrame(currentMessage.frames.get(currentFrame)); + if(currentMessage.interval > 0 || currentMessage.next != null) { + this.motd.keepAlive(true); + return true; + }else { + this.motd.keepAlive(false); + return false; + } + } + + public boolean tick() { + ageTimer++; + if(this.motd.isClosed()) { + return false; + } + if(ageTimer > EaglerMOTD.close_socket_after) { + this.motd.close(); + return false; + } + messageTimeTimer++; + if(messageTimeTimer >= currentMessage.timeout) { + if(currentMessage.next != null) { + if(currentMessage.next.equalsIgnoreCase("any") || currentMessage.next.equalsIgnoreCase("random")) { + MessagePool p = EaglerMOTD.messagePools.get(listenerName); + if(p == null) { + this.motd.close(); + return false; + } + if(p.messagePool.size() > 1) { + MessagePoolEntry m; + do { + m = p.pickNew(); + }while(m == currentMessage); + currentMessage = m; + } + }else { + if(!changeMessageTo(listenerName, currentMessage.next)) { + boolean flag = false; + for(String s : EaglerMOTD.messages.keySet()) { + if(!s.equalsIgnoreCase(listenerName) && changeMessageTo(s, currentMessage.next)) { + flag = true; + break; + } + } + if(!flag) { + this.motd.close(); + return false; + } + } + } + if(currentMessage == null) { + this.motd.close(); + return false; + } + messageTimeTimer = 0; + messageIntervalTimer = 0; + if(rand == null && (currentMessage.random || currentMessage.shuffle)) { + rand = new Random(); + } + currentFrame = currentMessage.random ? rand.nextInt(currentMessage.frames.size()) : 0; + applyFrame(currentMessage.frames.get(currentFrame)); + motd.sendToUser(); + return true; + }else { + this.motd.close(); + return false; + } + }else { + messageIntervalTimer++; + if(currentMessage.interval > 0 && messageIntervalTimer >= currentMessage.interval) { + messageIntervalTimer = 0; + if(currentMessage.frames.size() > 1) { + if(currentMessage.shuffle) { + int i; + do { + i = rand.nextInt(currentMessage.frames.size()); + }while(i == currentFrame); + currentFrame = i; + }else { + ++currentFrame; + if(currentFrame >= currentMessage.frames.size()) { + currentFrame = 0; + } + } + applyFrame(currentMessage.frames.get(currentFrame)); + motd.sendToUser(); + } + } + return true; + } + } + + private boolean changeMessageTo(String group, String s) { + List lst = EaglerMOTD.messages.get(group); + if(lst == null) { + return false; + } + for(MessagePoolEntry m : lst) { + if(m.name.equalsIgnoreCase(s)) { + currentMessage = m; + return true; + } + } + return false; + } + + public void applyFrame(JSONObject frame) { + boolean shouldPush = false; + Object v = frame.opt("online"); + if(v != null) { + if(v instanceof Number) { + motd.setOnlinePlayers(((Number)v).intValue()); + }else { + motd.setOnlinePlayers(BungeeCord.getInstance().getPlayers().size()); + } + shouldPush = true; + } + v = frame.opt("max"); + if(v != null) { + if(v instanceof Number) { + motd.setMaxPlayers(((Number)v).intValue()); + }else { + motd.setMaxPlayers(listener.getMaxPlayers()); + } + shouldPush = true; + } + v = frame.opt("players"); + if(v != null) { + if(v instanceof JSONArray) { + List players = new ArrayList(); + JSONArray vv = (JSONArray) v; + for(int i = 0, l = vv.length(); i < l; ++i) { + players.add(ChatColor.translateAlternateColorCodes('&', vv.getString(i))); + } + motd.setPlayerList(players); + }else { + List players = new ArrayList(); + Collection ppl = BungeeCord.getInstance().getPlayers(); + for(ProxiedPlayer pp : ppl) { + players.add(pp.getDisplayName()); + if(players.size() >= 9) { + players.add("" + ChatColor.GRAY + ChatColor.ITALIC + "(" + (ppl.size() - players.size()) + " more)"); + break; + } + } + motd.setPlayerList(players); + } + shouldPush = true; + } + String line = frame.optString("text0", frame.optString("text", null)); + if(line != null) { + int ix = line.indexOf('\n'); + if(ix != -1) { + motd.setLine1(ChatColor.translateAlternateColorCodes('&', line.substring(0, ix))); + motd.setLine2(ChatColor.translateAlternateColorCodes('&', line.substring(ix + 1))); + }else { + motd.setLine1(ChatColor.translateAlternateColorCodes('&', line)); + } + line = frame.optString("text1", null); + if(line != null) { + motd.setLine2(ChatColor.translateAlternateColorCodes('&', line)); + } + shouldPush = true; + } + boolean shouldRenderIcon = false; + String icon = frame.optString("icon", null); + if(icon != null) { + shouldRenderIcon = true; + if(icon.equalsIgnoreCase("none") || icon.equalsIgnoreCase("default") || icon.equalsIgnoreCase("null") || icon.equalsIgnoreCase("color")) { + bitmap = null; + }else { + bitmap = BitmapFile.getCachedIcon(icon); + } + spriteX = spriteY = 0; + color = new float[] { 0.0f, 0.0f, 0.0f, 0.0f }; + tint = new float[] { 1.0f, 1.0f, 1.0f, 1.0f }; + } + int sprtX = frame.optInt("icon_spriteX", -1); + if(sprtX >= 0 && sprtX != spriteX) { + shouldRenderIcon = true; + spriteX = sprtX; + } + int sprtY = frame.optInt("icon_spriteY", -1); + if(sprtY >= 0 && sprtY != spriteY) { + shouldRenderIcon = true; + spriteY = sprtY; + } + JSONArray colorF = frame.optJSONArray("icon_color"); + if(colorF != null && colorF.length() > 0) { + shouldRenderIcon = true; + color[0] = colorF.getFloat(0); + color[1] = colorF.length() > 1 ? colorF.getFloat(1) : color[1]; + color[2] = colorF.length() > 2 ? colorF.getFloat(2) : color[2]; + color[3] = colorF.length() > 3 ? colorF.getFloat(3) : 1.0f; + } + colorF = frame.optJSONArray("icon_tint"); + if(colorF != null && colorF.length() > 0) { + shouldRenderIcon = true; + tint[0] = colorF.getFloat(0); + tint[1] = colorF.length() > 1 ? colorF.getFloat(1) : tint[1]; + tint[2] = colorF.length() > 2 ? colorF.getFloat(2) : tint[2]; + tint[3] = colorF.length() > 3 ? colorF.getFloat(3) : 1.0f; + } + if(shouldRenderIcon) { + int[] newIcon = null; + if(bitmap != null) { + newIcon = bitmap.getSprite(sprtX, sprtY); + } + if(newIcon == null) { + newIcon = new int[64*64]; + } + newIcon = BitmapFile.applyTint(newIcon, tint[0], tint[1], tint[2], tint[3]); + if(color[3] > 0.0f) { + newIcon = BitmapFile.applyColor(newIcon, color[0], color[1], color[2], color[3]); + } + motd.setBitmap(newIcon); + shouldPush = true; + } + if(shouldPush) { + motd.sendToUser(); + } + } + + public void close() { + motd.close(); + } + +} diff --git a/src/net/lax1dude/eaglercraft/eaglermotd/MessagePool.java b/src/net/lax1dude/eaglercraft/eaglermotd/MessagePool.java new file mode 100644 index 0000000..aefecb1 --- /dev/null +++ b/src/net/lax1dude/eaglercraft/eaglermotd/MessagePool.java @@ -0,0 +1,50 @@ +package net.lax1dude.eaglercraft.eaglermotd; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; + +public class MessagePool { + + public final String poolName; + public final List messagePool = new LinkedList(); + public final Random random = new Random(); + + public MessagePool(String s) { + this.poolName = s; + } + + public void sort() { + Collections.sort(messagePool); + } + + public MessagePoolEntry pickNew() { + if(messagePool.size() <= 0) { + return null; + } + float f = 0.0f; + for(MessagePoolEntry m : messagePool) { + f += m.weight; + } + f *= random.nextFloat(); + float f2 = 0.0f; + for(MessagePoolEntry m : messagePool) { + f2 += m.weight; + if(f2 >= f) { + return m; + } + } + return messagePool.get(0); + } + + public MessagePoolEntry pickDefault() { + for(MessagePoolEntry m : messagePool) { + if("default".equalsIgnoreCase(m.name)) { + return m; + } + } + return pickNew(); + } + +} diff --git a/src/net/lax1dude/eaglercraft/eaglermotd/MessagePoolEntry.java b/src/net/lax1dude/eaglercraft/eaglermotd/MessagePoolEntry.java new file mode 100644 index 0000000..ba9b7fc --- /dev/null +++ b/src/net/lax1dude/eaglercraft/eaglermotd/MessagePoolEntry.java @@ -0,0 +1,34 @@ +package net.lax1dude.eaglercraft.eaglermotd; + +import java.util.List; + +import org.json.JSONObject; + +public class MessagePoolEntry implements Comparable { + + public final String name; + public final int interval; + public final int timeout; + public final boolean random; + public final boolean shuffle; + public final float weight; + public final String next; + public final List frames; + + public MessagePoolEntry(int interval, int timeout, boolean random, boolean shuffle, float weight, String next, List frames, String name) { + this.interval = interval; + this.timeout = timeout; + this.random = random; + this.shuffle = shuffle; + this.weight = weight; + this.next = next; + this.frames = frames; + this.name = name; + } + + @Override + public int compareTo(MessagePoolEntry o) { + return Float.compare(weight, o.weight); + } + +} diff --git a/src/net/lax1dude/eaglercraft/eaglermotd/QueryCache.java b/src/net/lax1dude/eaglercraft/eaglermotd/QueryCache.java new file mode 100644 index 0000000..cc9190b --- /dev/null +++ b/src/net/lax1dude/eaglercraft/eaglermotd/QueryCache.java @@ -0,0 +1,157 @@ +package net.lax1dude.eaglercraft.eaglermotd; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; + +import org.json.JSONObject; + +public class QueryCache { + + private static class CachedFile { + protected final String name; + protected final File file; + protected long lastReload; + protected long lastRescan; + protected CachedFile(String name, File file) { + this.name = name; + this.file = file; + this.lastReload = this.lastRescan = 0l; + } + protected boolean needsReload() { + long l = System.currentTimeMillis(); + if(l - lastRescan > 5000l) { + lastRescan = l; + return file.exists() && lastReload < file.lastModified(); + }else { + return false; + } + } + } + + private static class CachedFileBinary extends CachedFile { + protected byte[] bytes = null; + protected CachedFileBinary(String name, File file) { + super(name, file); + } + protected byte[] getOrReload() { + if(needsReload()) { + if(file.exists()) { + try(FileInputStream fis = new FileInputStream(file)) { + ByteArrayOutputStream read = new ByteArrayOutputStream(fis.available()); + byte[] d = new byte[8192]; + int i; + while((i = fis.read(d)) != -1) { + read.write(d, 0, i); + } + lastRescan = lastReload = System.currentTimeMillis(); + bytes = read.toByteArray(); + }catch(Throwable t) { + bytes = null; + System.err.println("[EaglerMOTD] Failed to load binary: " + name); + t.printStackTrace(); + } + } + } + return bytes; + } + } + + private static class CachedFileString extends CachedFile { + protected String chars = null; + protected CachedFileString(String name, File file) { + super(name, file); + + } + protected String getOrReload() { + if(needsReload()) { + if(file.exists()) { + try(FileInputStream fis = new FileInputStream(file)) { + ByteArrayOutputStream read = new ByteArrayOutputStream(fis.available()); + byte[] d = new byte[8192]; + int i; + while((i = fis.read(d)) != -1) { + read.write(d, 0, i); + } + lastRescan = lastReload = System.currentTimeMillis(); + chars = new String(read.toByteArray(), StandardCharsets.UTF_8); + }catch(Throwable t) { + chars = null; + System.err.println("[EaglerMOTD] Failed to load text: " + name); + t.printStackTrace(); + } + } + } + return chars; + } + } + + private static class CachedFileJSON extends CachedFile { + protected JSONObject json = null; + protected CachedFileJSON(String name, File file) { + super(name, file); + + } + protected JSONObject getOrReload() { + if(needsReload()) { + if(file.exists()) { + try(FileInputStream fis = new FileInputStream(file)) { + ByteArrayOutputStream read = new ByteArrayOutputStream(fis.available()); + byte[] d = new byte[8192]; + int i; + while((i = fis.read(d)) != -1) { + read.write(d, 0, i); + } + lastRescan = lastReload = System.currentTimeMillis(); + json = new JSONObject(new String(read.toByteArray(), StandardCharsets.UTF_8)); + }catch(Throwable t) { + json = null; + System.err.println("[EaglerMOTD] Failed to load json: " + name); + t.printStackTrace(); + } + } + } + return json; + } + } + + private static final HashMap cachedBinary = new HashMap(); + private static final HashMap cachedString = new HashMap(); + private static final HashMap cachedJSON = new HashMap(); + + public static void flush() { + cachedBinary.clear(); + cachedString.clear(); + cachedJSON.clear(); + } + + public static byte[] getBinaryFile(String s) { + CachedFileBinary fb = cachedBinary.get(s); + if(fb == null) { + fb = new CachedFileBinary(s, new File(s)); + cachedBinary.put(s, fb); + } + return fb.getOrReload(); + } + + public static String getStringFile(String s) { + CachedFileString fb = cachedString.get(s); + if(fb == null) { + fb = new CachedFileString(s, new File(s)); + cachedString.put(s, fb); + } + return fb.getOrReload(); + } + + public static JSONObject getJSONFile(String s) { + CachedFileJSON fb = cachedJSON.get(s); + if(fb == null) { + fb = new CachedFileJSON(s, new File(s)); + cachedJSON.put(s, fb); + } + return fb.getOrReload(); + } + +} diff --git a/src/net/lax1dude/eaglercraft/eaglermotd/QueryType.java b/src/net/lax1dude/eaglercraft/eaglermotd/QueryType.java new file mode 100644 index 0000000..90a6042 --- /dev/null +++ b/src/net/lax1dude/eaglercraft/eaglermotd/QueryType.java @@ -0,0 +1,109 @@ +package net.lax1dude.eaglercraft.eaglermotd; + +import org.json.JSONObject; + +import net.md_5.bungee.api.QueryConnection; + +public class QueryType { + + public final String name; + public final String type; + + public final String dataString; + public final String dataJSONFile; + public final JSONObject dataJSONObject; + public final String dataTextFile; + public final String dataBinaryFile; + + public QueryType(String name, JSONObject tag) { + this.name = name; + this.dataJSONObject = tag.optJSONObject("json", null); + if(this.dataJSONObject == null) { + this.dataJSONFile = tag.optString("json", null); + if(this.dataJSONFile == null) { + this.dataTextFile = tag.optString("txt", null); + if(this.dataTextFile == null) { + this.dataString = tag.optString("string", null); + }else { + this.dataString = null; + } + }else { + this.dataTextFile = null; + this.dataString = null; + } + }else { + this.dataJSONFile = null; + this.dataTextFile = null; + this.dataString = null; + } + this.dataBinaryFile = tag.optString("file", null); + String t = tag.optString("type", null); + if(t == null) { + if(this.dataJSONObject != null || this.dataJSONFile != null) { + t = "json"; + }else if(this.dataString != null || this.dataTextFile != null) { + t = "text"; + }else { + t = "binary"; + } + } + this.type = t; + } + + public void doQuery(QueryConnection query) { + byte[] bin = null; + if(dataBinaryFile != null) { + bin = QueryCache.getBinaryFile(dataBinaryFile); + if(bin == null) { + query.setReturnType("error"); + query.writeResponse("Error: could not load binary file '" + dataBinaryFile + "' for query '" + type + "'"); + return; + } + } + boolean flag = false; + if(dataJSONObject != null) { + query.setReturnType(type); + query.writeResponse(dataJSONObject); + flag = true; + }else if(dataJSONFile != null) { + JSONObject obj = QueryCache.getJSONFile(dataJSONFile); + if(obj == null) { + query.setReturnType("error"); + query.writeResponse("Error: could not load or parse JSON file '" + dataJSONFile + "' for query '" + type + "'"); + return; + }else { + query.setReturnType(type); + query.writeResponse(obj); + flag = true; + } + }else if(dataTextFile != null) { + String txt = QueryCache.getStringFile(dataTextFile); + if(txt == null) { + query.setReturnType("error"); + query.writeResponse("Error: could not load text file '" + dataJSONFile + "' for query '" + type + "'"); + return; + }else { + query.setReturnType(type); + query.writeResponse(txt); + flag = true; + } + }else if(dataString != null) { + query.setReturnType(type); + query.writeResponse(dataString); + flag = true; + } + if(!flag) { + query.setReturnType(type); + if(bin != null) { + query.writeResponse((new JSONObject()).put("binary", true).put("file", dataBinaryFile).put("size", bin.length)); + }else { + query.writeResponse(""); + } + } + if(bin != null) { + query.writeResponseBinary(bin); + } + query.close(); + } + +} diff --git a/src/plugin.yml b/src/plugin.yml new file mode 100644 index 0000000..efe4338 --- /dev/null +++ b/src/plugin.yml @@ -0,0 +1,4 @@ +name: EaglerMOTD +main: net.lax1dude.eaglercraft.eaglermotd.EaglerMOTD +version: 1.0 +author: LAX1DUDE \ No newline at end of file diff --git a/src/server-icons-test.png b/src/server-icons-test.png new file mode 100644 index 0000000000000000000000000000000000000000..54412ce3570d8de226c5c6649452e1373f3fdbb6 GIT binary patch literal 27162 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 literal 0 HcmV?d00001