diff --git a/src/main/java/me/braydon/mc/common/ColorUtils.java b/src/main/java/me/braydon/mc/common/ColorUtils.java new file mode 100644 index 0000000..1e56d99 --- /dev/null +++ b/src/main/java/me/braydon/mc/common/ColorUtils.java @@ -0,0 +1,81 @@ +package me.braydon.mc.common; + +import lombok.NonNull; +import lombok.experimental.UtilityClass; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; + +/** + * @author Braydon + */ +@UtilityClass +public final class ColorUtils { + private static final Pattern STRIP_COLOR_PATTERN = Pattern.compile("(?i)§[0-9A-FK-OR]"); + private static final Map COLOR_MAP = new HashMap<>(); + static { + // Map each color to its corresponding hex code + COLOR_MAP.put('0', "#000000"); // Black + COLOR_MAP.put('1', "#0000AA"); // Dark Blue + COLOR_MAP.put('2', "#00AA00"); // Dark Green + COLOR_MAP.put('3', "#00AAAA"); // Dark Aqua + COLOR_MAP.put('4', "#AA0000"); // Dark Red + COLOR_MAP.put('5', "#AA00AA"); // Dark Purple + COLOR_MAP.put('6', "#FFAA00"); // Gold + COLOR_MAP.put('7', "#AAAAAA"); // Gray + COLOR_MAP.put('8', "#555555"); // Dark Gray + COLOR_MAP.put('9', "#5555FF"); // Blue + COLOR_MAP.put('a', "#55FF55"); // Green + COLOR_MAP.put('b', "#55FFFF"); // Aqua + COLOR_MAP.put('c', "#FF5555"); // Red + COLOR_MAP.put('d', "#FF55FF"); // Light Purple + COLOR_MAP.put('e', "#FFFF55"); // Yellow + COLOR_MAP.put('f', "#FFFFFF"); // White + } + + /** + * Strip the color codes + * from the given input. + * + * @param input the input to strip + * @return the stripped input + */ + @NonNull + public static String stripColor(@NonNull String input) { + return STRIP_COLOR_PATTERN.matcher(input).replaceAll(""); + } + + /** + * Convert the given input into HTML format. + *

+ * This will replace each color code with + * a span tag with the respective color in + * hex format. + *

+ * + * @param input the input to convert + * @return the converted input + */ + @NonNull + public static String toHTML(@NonNull String input) { + StringBuilder builder = new StringBuilder(); + boolean nextIsColor = false; // Is the next char a color code? + + for (char character : input.toCharArray()) { + // Found color symbol, next color is the color + if (character == '§') { + nextIsColor = true; + continue; + } + if (nextIsColor) { // Map the current color to its hex code + String color = COLOR_MAP.getOrDefault(Character.toLowerCase(character), ""); + builder.append(""); + nextIsColor = false; + continue; + } + builder.append(character); // Append the char... + } + return builder.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/me/braydon/mc/model/MinecraftServer.java b/src/main/java/me/braydon/mc/model/MinecraftServer.java index 358542d..5aba99b 100644 --- a/src/main/java/me/braydon/mc/model/MinecraftServer.java +++ b/src/main/java/me/braydon/mc/model/MinecraftServer.java @@ -1,10 +1,14 @@ package me.braydon.mc.model; import lombok.*; +import me.braydon.mc.common.ColorUtils; +import me.braydon.mc.model.token.JavaServerStatusToken; import me.braydon.mc.service.pinger.MinecraftServerPinger; import me.braydon.mc.service.pinger.impl.BedrockMinecraftServerPinger; import me.braydon.mc.service.pinger.impl.JavaMinecraftServerPinger; +import java.util.Arrays; + /** * A model representing a Minecraft server. * @@ -37,6 +41,24 @@ public class MinecraftServer { */ @NonNull private final Players players; + /** + * The MOTD of this server. + */ + @NonNull private final MOTD motd; + + /** + * The Base64 encoded icon of this server. + */ + @NonNull private final String icon; + + /** + * Is this server on the list + * of blocked servers by Mojang? + * + * @see Mojang API + */ + private final boolean mojangBanned; + /** * Version information for a server. */ @@ -69,6 +91,43 @@ public class MinecraftServer { private final int max; } + /** + * The MOTD for a server. + */ + @AllArgsConstructor @Getter @ToString + public static class MOTD { + /** + * The raw MOTD lines, taken directly from the {@link JavaServerStatusToken}. + */ + @NonNull private final String[] raw; + + /** + * The clean MOTD lines (no color codes). + */ + @NonNull private final String[] clean; + + /** + * The HTML MOTD lines. + */ + @NonNull private final String[] html; + + /** + * Create a new MOTD from a raw string. + * + * @param raw the raw motd string + * @return the new motd + */ + @NonNull + public static MOTD create(@NonNull String raw) { + String[] rawLines = raw.split("\n"); // The raw lines + return new MOTD( + rawLines, + Arrays.stream(rawLines).map(ColorUtils::stripColor).toArray(String[]::new), + Arrays.stream(rawLines).map(ColorUtils::toHTML).toArray(String[]::new) + ); + } + } + /** * A platform a Minecraft * server can operate on. diff --git a/src/main/java/me/braydon/mc/model/server/BedrockMinecraftServer.java b/src/main/java/me/braydon/mc/model/server/BedrockMinecraftServer.java index 3561e91..84c3484 100644 --- a/src/main/java/me/braydon/mc/model/server/BedrockMinecraftServer.java +++ b/src/main/java/me/braydon/mc/model/server/BedrockMinecraftServer.java @@ -9,7 +9,8 @@ import me.braydon.mc.model.MinecraftServer; * @author Braydon */ public final class BedrockMinecraftServer extends MinecraftServer { - private BedrockMinecraftServer(@NonNull String hostname, String ip, int port, @NonNull Version version, @NonNull Players players) { - super(hostname, ip, port, version, players); + private BedrockMinecraftServer(@NonNull String hostname, String ip, int port, @NonNull Version version, + @NonNull Players players, @NonNull MOTD motd, @NonNull String icon, boolean mojangBanned) { + super(hostname, ip, port, version, players, motd, icon, mojangBanned); } } \ No newline at end of file diff --git a/src/main/java/me/braydon/mc/model/server/JavaMinecraftServer.java b/src/main/java/me/braydon/mc/model/server/JavaMinecraftServer.java index 1f8f7b8..56717f9 100644 --- a/src/main/java/me/braydon/mc/model/server/JavaMinecraftServer.java +++ b/src/main/java/me/braydon/mc/model/server/JavaMinecraftServer.java @@ -10,8 +10,9 @@ import me.braydon.mc.model.token.JavaServerStatusToken; * @author Braydon */ public final class JavaMinecraftServer extends MinecraftServer { - private JavaMinecraftServer(@NonNull String hostname, String ip, int port, @NonNull Version version, @NonNull Players players) { - super(hostname, ip, port, version, players); + private JavaMinecraftServer(@NonNull String hostname, String ip, int port, @NonNull Version version, + @NonNull Players players, @NonNull MOTD motd, @NonNull String icon, boolean mojangBanned) { + super(hostname, ip, port, version, players, motd, icon, mojangBanned); } /** @@ -25,6 +26,8 @@ public final class JavaMinecraftServer extends MinecraftServer { */ @NonNull public static JavaMinecraftServer create(@NonNull String hostname, String ip, int port, @NonNull JavaServerStatusToken token) { - return new JavaMinecraftServer(hostname, ip, port, token.getVersion(), token.getPlayers()); + return new JavaMinecraftServer(hostname, ip, port, token.getVersion(), token.getPlayers(), + MOTD.create(token.getDescription()), token.getFavicon(), false + ); } } \ No newline at end of file diff --git a/src/main/java/me/braydon/mc/service/pinger/impl/JavaMinecraftServerPinger.java b/src/main/java/me/braydon/mc/service/pinger/impl/JavaMinecraftServerPinger.java index 756d2ab..9ea74bf 100644 --- a/src/main/java/me/braydon/mc/service/pinger/impl/JavaMinecraftServerPinger.java +++ b/src/main/java/me/braydon/mc/service/pinger/impl/JavaMinecraftServerPinger.java @@ -39,7 +39,7 @@ public final class JavaMinecraftServerPinger implements MinecraftServerPinger {}", hostname, ip); } log.info("Pinging {}:{}...", hostname, port); long before = System.currentTimeMillis(); // Timestamp before pinging