commit 792308dacab9df3c8163a3225e13e49a5eb7169e Author: wullie Date: Sun Nov 30 06:45:24 2025 +0000 Upload files to "src/main/java/com/wulliestudio/icon" diff --git a/src/main/java/com/wulliestudio/icon/IconManager.java b/src/main/java/com/wulliestudio/icon/IconManager.java new file mode 100644 index 0000000..03f5cea --- /dev/null +++ b/src/main/java/com/wulliestudio/icon/IconManager.java @@ -0,0 +1,46 @@ +package com.wulliestudio.icon; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class IconManager{ + + private final PluginMain plugin; + private final List icons = new ArrayList<>(); + private final Random random = new Random(); + + // init function + public IconManager(PluginMain plugin){ + this.plugin = plugin; + loadIcons(); + } + + // loads the icons + private void loadIcons(){ + File folder = new File(plugin.getDataFolder(), "images"); + + // checks to see if icon location exists + if(!folder.exists()){ + folder.mkdirs(); + } + File[] files = folder.listFiles((dir, name) -> name.toLowerCase().endsWith(".png")); + + if(files != null){ + for (File f : files) icons.add(f); + } + } + + // gets random icon + public File getRandomIcon(){ + if(icons.isEmpty()) return null; + return icons.get(random.nextInt(icons.size())); + } + + // gets the count of icons + public int getIconCount(){ + return icons.size(); + } + +} diff --git a/src/main/java/com/wulliestudio/icon/MotdManager.java b/src/main/java/com/wulliestudio/icon/MotdManager.java new file mode 100644 index 0000000..87b8cef --- /dev/null +++ b/src/main/java/com/wulliestudio/icon/MotdManager.java @@ -0,0 +1,113 @@ +package com.wulliestudio.icon; + +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +/** + * MotdManager + * + * Loads motd.yml -> key "motd" (List<String>). + * Expected input format in motd.yml: "'your message'" + * The manager will: + * - extract the inner quoted text if present + * - parse MiniMessage tags (, , etc.) + * - convert to legacy text (section codes) which the server MOTD accepts + */ +public class MotdManager { + + private final PluginMain plugin; + private final List motds = new ArrayList<>(); // stores converted (legacy) strings + private final MiniMessage mini = MiniMessage.miniMessage(); + + private final Random random = new Random(); + + public MotdManager(PluginMain plugin) { + this.plugin = plugin; + loadMotdFile(); + } + + private void loadMotdFile() { + File file = new File(plugin.getDataFolder(), "motd.yml"); + + if (!file.exists()) { + plugin.saveResource("motd.yml", false); + } + + FileConfiguration cfg = YamlConfiguration.loadConfiguration(file); + List raw = cfg.getStringList("motd"); + + motds.clear(); + for (String entry : raw) { + if (entry == null) continue; + + // If the entry contains a single-quoted substring like '<...>', + // extract the inner quoted content. Example: + // "'this is a test'" -> "this is a test" + String processed = extractQuotedOrUseWhole(entry); + + // Parse MiniMessage to Component, then serialize to legacy section format (with § codes) + try { + Component comp = mini.deserialize(processed); + String legacy = LegacyComponentSerializer.legacySection().serialize(comp); + motds.add(legacy); + } catch (Exception ex) { + // Fallback: if parsing fails, store the raw processed string (so something still appears) + plugin.getLogger().warning("Failed to parse MOTD entry: " + entry + " — using raw text."); + motds.add(processed); + } + } + + if (motds.isEmpty()) { + // Add a default MOTD (already converted) + Component defaultComp = mini.deserialize("'default motd — no entries found'"); + motds.add(LegacyComponentSerializer.legacySection().serialize(defaultComp)); + } + + plugin.getLogger().info("Loaded " + motds.size() + " MOTD(s)."); + } + + /** + * If the raw string contains an inner single-quoted substring, return that substring + * appended to any leading tags. Otherwise return the original string. + * + * Examples: + * "'hello world'" -> "hello world" + * "noquotes here" -> "noquotes here" + */ + private String extractQuotedOrUseWhole(String raw) { + if (raw == null) return ""; + + // find first single quote and last single quote + int first = raw.indexOf('\''); + int last = raw.lastIndexOf('\''); + + // if there are at least two single quotes and they're not the same position, extract inner + if (first != -1 && last != -1 && last > first) { + String before = raw.substring(0, first); // tags and any text before the quote + String inner = raw.substring(first + 1, last); // text inside quotes + return before + inner; + } + + // otherwise return the whole string unchanged + return raw; + } + + public String getRandomMotd() { + if (motds.isEmpty()) return null; + return motds.get(random.nextInt(motds.size())); + } + + public int getMotdCount() { + return motds.size(); + } +} + diff --git a/src/main/java/com/wulliestudio/icon/PluginMain.java b/src/main/java/com/wulliestudio/icon/PluginMain.java new file mode 100644 index 0000000..c45a41a --- /dev/null +++ b/src/main/java/com/wulliestudio/icon/PluginMain.java @@ -0,0 +1,38 @@ +package com.wulliestudio.icon; + +import org.bukkit.plugin.java.JavaPlugin; + + +// plugin class +public class PluginMain extends JavaPlugin{ + + private IconManager iconManager; + private MotdManager motdManager; + + // handle on enable + @Override + public void onEnable(){ + + iconManager = new IconManager(this); + motdManager = new MotdManager(this); + + getServer().getPluginManager().registerEvents( + new ServerListPingListener(iconManager, motdManager), this + ); + getLogger().info("dynamic server banners Loaded"); + } + + @Override + public void onDisable(){ + + } + + public IconManager getIconManager(){ + return iconManager; + } + + public MotdManager getMotdManager(){ + return motdManager; + } + +} diff --git a/src/main/java/com/wulliestudio/icon/ServerListPingListener.java b/src/main/java/com/wulliestudio/icon/ServerListPingListener.java new file mode 100644 index 0000000..cee59e0 --- /dev/null +++ b/src/main/java/com/wulliestudio/icon/ServerListPingListener.java @@ -0,0 +1,41 @@ +package com.wulliestudio.icon; + +import org.bukkit.Bukkit; // optional - remove if unused +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.server.ServerListPingEvent; +import org.bukkit.map.MapView; +import org.bukkit.util.CachedServerIcon; // note: some APIs use org.bukkit.craftbukkit... but this should be available via API + +import java.io.File; + +public class ServerListPingListener implements Listener { + + private final IconManager iconManager; + private final MotdManager motdManager; + + public ServerListPingListener(IconManager iconManager, MotdManager motdManager) { + this.iconManager = iconManager; + this.motdManager = motdManager; + } + + @EventHandler + public void onPing(ServerListPingEvent event) { + + // MOTD + String motd = motdManager.getRandomMotd(); + if (motd != null) event.setMotd(motd); + + // ICON + File img = iconManager.getRandomIcon(); + if (img != null) { + try { + // loadServerIcon is on the Server (Bukkit.getServer()) + org.bukkit.util.CachedServerIcon icon = Bukkit.getServer().loadServerIcon(img); + event.setServerIcon(icon); + } catch (Exception ignored) { + // image invalid for server-icon; ignore to avoid spam + } + } + } +}