From 2d0a1f760854b6203e8bf17b56e4c4ce6f0c8aab Mon Sep 17 00:00:00 2001 From: ChomeNS <95471003+ChomeNS@users.noreply.github.com> Date: Fri, 3 Nov 2023 17:41:20 +0700 Subject: [PATCH] round hex colors --- .../chomens_bot/plugins/DiscordPlugin.java | 4 +- .../chomens_bot/util/ColorUtilities.java | 63 ++++++++++++++++++ .../chomens_bot/util/ComponentUtilities.java | 65 +++++++++++-------- 3 files changed, 103 insertions(+), 29 deletions(-) diff --git a/src/main/java/land/chipmunk/chayapak/chomens_bot/plugins/DiscordPlugin.java b/src/main/java/land/chipmunk/chayapak/chomens_bot/plugins/DiscordPlugin.java index 530a9c5..223dc04 100644 --- a/src/main/java/land/chipmunk/chayapak/chomens_bot/plugins/DiscordPlugin.java +++ b/src/main/java/land/chipmunk/chayapak/chomens_bot/plugins/DiscordPlugin.java @@ -80,10 +80,12 @@ public class DiscordPlugin { bot.chat.addListener(new ChatPlugin.Listener() { @Override - public boolean systemMessageReceived (Component component, String string, String ansi) { + public boolean systemMessageReceived (Component component, String string, String _ansi) { if (string.length() > 2048) { sendMessage(CodeBlockUtilities.escape(string), channelId); } else { + final String ansi = ComponentUtilities.stringifyAnsi(component, true); + sendMessage( CodeBlockUtilities.escape( ansi diff --git a/src/main/java/land/chipmunk/chayapak/chomens_bot/util/ColorUtilities.java b/src/main/java/land/chipmunk/chayapak/chomens_bot/util/ColorUtilities.java index 5447a03..339a418 100644 --- a/src/main/java/land/chipmunk/chayapak/chomens_bot/util/ColorUtilities.java +++ b/src/main/java/land/chipmunk/chayapak/chomens_bot/util/ColorUtilities.java @@ -38,4 +38,67 @@ public class ColorUtilities { Color color = Color.getHSBColor(hue / 360.0f, saturation / 100.0f, value / 100.0f); return color.getRGB() & 0xFFFFFF; } + + private static final ChatColor[] COLORS = { + new ChatColor("0", 0x000000), + new ChatColor("1", 0x0000aa), + new ChatColor("2", 0x00aa00), + new ChatColor("3", 0x00aaaa), + new ChatColor("4", 0xaa0000), + new ChatColor("5", 0xaa00aa), + new ChatColor("6", 0xffaa00), + new ChatColor("7", 0xaaaaaa), + new ChatColor("8", 0x555555), + new ChatColor("9", 0x5555ff), + new ChatColor("a", 0x55ff55), + new ChatColor("b", 0x55ffff), + new ChatColor("c", 0xff5555), + new ChatColor("d", 0xff55ff), + new ChatColor("e", 0xffff55), + new ChatColor("f", 0xffffff) + }; + + public static String getClosestChatColor(int rgb) { + int r = (rgb >> 16) & 0xFF; + int g = (rgb >> 8) & 0xFF; + int b = rgb & 0xFF; + + ChatColor closest = null; + int smallestDiff = 0; + + for (ChatColor color : COLORS) { + if (color.rgb == rgb) { + return color.colorName; + } + + // Check by the greatest diff of the 3 values + int rAverage = (color.r + r) / 2; + int rDiff = color.r - r; + int gDiff = color.g - g; + int bDiff = color.b - b; + int diff = ((2 + (rAverage >> 8)) * rDiff * rDiff) + + (4 * gDiff * gDiff) + + ((2 + ((255 - rAverage) >> 8)) * bDiff * bDiff); + if (closest == null || diff < smallestDiff) { + closest = color; + smallestDiff = diff; + } + } + return closest.colorName; + } + + public static final class ChatColor { + + private final String colorName; + private final int rgb; + private final int r, g, b; + + public ChatColor(String colorName, int rgb) { + this.colorName = colorName; + this.rgb = rgb; + r = (rgb >> 16) & 0xFF; + g = (rgb >> 8) & 0xFF; + b = rgb & 0xFF; + } + } } diff --git a/src/main/java/land/chipmunk/chayapak/chomens_bot/util/ComponentUtilities.java b/src/main/java/land/chipmunk/chayapak/chomens_bot/util/ComponentUtilities.java index 5b4d1d9..73abda1 100644 --- a/src/main/java/land/chipmunk/chayapak/chomens_bot/util/ComponentUtilities.java +++ b/src/main/java/land/chipmunk/chayapak/chomens_bot/util/ComponentUtilities.java @@ -59,7 +59,7 @@ public class ComponentUtilities { ansiMap.put("r", "\u001b[0m"); } - private record PartiallyStringified( + public record PartiallyStringified( String output, String lastColor ) {} @@ -95,7 +95,7 @@ public class ComponentUtilities { try { final StringBuilder builder = new StringBuilder(); - final PartiallyStringified output = stringifyPartially(message, false, false, lastColor); + final PartiallyStringified output = stringifyPartially(message, false, false, lastColor, false); builder.append(output.output); @@ -112,7 +112,7 @@ public class ComponentUtilities { try { final StringBuilder builder = new StringBuilder(); - final PartiallyStringified output = stringifyPartially(message, true, false, lastColor); + final PartiallyStringified output = stringifyPartially(message, true, false, lastColor, false); builder.append(output.output); @@ -124,16 +124,17 @@ public class ComponentUtilities { } } - public static String stringifyAnsi (Component message) { return stringifyAnsi(message, null); } - private static String stringifyAnsi (Component message, String lastColor) { + public static String stringifyAnsi (Component message) { return stringifyAnsi(message, null, false); } + public static String stringifyAnsi (Component message, boolean noHex) { return stringifyAnsi(message, null, noHex); } + private static String stringifyAnsi (Component message, String lastColor, boolean noHex) { try { final StringBuilder builder = new StringBuilder(); - final PartiallyStringified output = stringifyPartially(message, false, true, lastColor); + final PartiallyStringified output = stringifyPartially(message, false, true, lastColor, noHex); builder.append(output.output); - for (Component child : message.children()) builder.append(stringifyAnsi(child, output.lastColor)); + for (Component child : message.children()) builder.append(stringifyAnsi(child, output.lastColor, noHex)); return builder.toString(); } catch (Exception e) { @@ -141,11 +142,11 @@ public class ComponentUtilities { } } - public static PartiallyStringified stringifyPartially (Component message, boolean motd, boolean ansi, String lastColor) { - if (message instanceof TextComponent) return stringifyPartially((TextComponent) message, motd, ansi, lastColor); - else if (message instanceof TranslatableComponent) return stringifyPartially((TranslatableComponent) message, motd, ansi, lastColor); - else if (message instanceof SelectorComponent) return stringifyPartially((SelectorComponent) message, motd, ansi, lastColor); - else if (message instanceof KeybindComponent) return stringifyPartially((KeybindComponent) message, motd, ansi, lastColor); + public static PartiallyStringified stringifyPartially (Component message, boolean motd, boolean ansi, String lastColor, boolean noHex) { + if (message instanceof TextComponent) return stringifyPartially((TextComponent) message, motd, ansi, lastColor, noHex); + else if (message instanceof TranslatableComponent) return stringifyPartially((TranslatableComponent) message, motd, ansi, lastColor, noHex); + else if (message instanceof SelectorComponent) return stringifyPartially((SelectorComponent) message, motd, ansi, lastColor, noHex); + else if (message instanceof KeybindComponent) return stringifyPartially((KeybindComponent) message, motd, ansi, lastColor, noHex); return new PartiallyStringified("", null); } @@ -183,7 +184,7 @@ public class ComponentUtilities { return style.toString(); } - public static String getColor (TextColor color, boolean motd, boolean ansi) { + public static String getColor (TextColor color, boolean motd, boolean ansi, boolean noHex) { if (color == null) return null; // map totallynotskidded™ too from https://github.com/PrismarineJS/prismarine-chat/blob/master/index.js#L299 @@ -217,22 +218,30 @@ public class ComponentUtilities { } else if (ansi) { String ansiCode = ansiMap.get(code); if (ansiCode == null) { - ansiCode = "\u001b[38;2;" + - color.red() + - ";" + - color.green() + - ";" + - color.blue() + - "m"; + if (noHex) { + final int rgb = Integer.parseInt(code.substring(1), 16); + + final String chatColor = ColorUtilities.getClosestChatColor(rgb); + + ansiCode = ansiMap.get(chatColor); + } else { + ansiCode = "\u001b[38;2;" + + color.red() + + ";" + + color.green() + + ";" + + color.blue() + + "m"; + } } return ansiCode; } else return null; } - public static PartiallyStringified stringifyPartially (TextComponent message, boolean motd, boolean ansi, String lastColor) { + public static PartiallyStringified stringifyPartially (TextComponent message, boolean motd, boolean ansi, String lastColor, boolean noHex) { if ((motd || ansi) && /* don't color big messages -> */ message.content().length() < 25_000) { - final String color = getColor(message.color(), motd, ansi); + final String color = getColor(message.color(), motd, ansi, noHex); final String style = getStyle(message.style(), motd); String replacedContent = message.content(); @@ -254,7 +263,7 @@ public class ComponentUtilities { return new PartiallyStringified(message.content(), null); } - public static PartiallyStringified stringifyPartially (TranslatableComponent message, boolean motd, boolean ansi, String lastColor) { + public static PartiallyStringified stringifyPartially (TranslatableComponent message, boolean motd, boolean ansi, String lastColor, boolean noHex) { String format = getOrReturnKey(message.key()); // totallynotskidded™️ from HBot (and changed a bit) @@ -262,7 +271,7 @@ public class ComponentUtilities { StringBuilder sb = new StringBuilder(); final String style = getStyle(message.style(), motd); - final String _color = getColor(message.color(), motd, ansi); + final String _color = getColor(message.color(), motd, ansi, noHex); String color; if (_color == null) color = ""; else color = _color; @@ -297,18 +306,18 @@ public class ComponentUtilities { return new PartiallyStringified((lastColor != null ? lastColor : "") + color + (style != null && ansi ? style : "") + sb + (ansi ? ansiMap.get("r") : ""), _color); } - public static PartiallyStringified stringifyPartially (SelectorComponent message, boolean motd, boolean ansi, String lastColor) { + public static PartiallyStringified stringifyPartially (SelectorComponent message, boolean motd, boolean ansi, String lastColor, boolean noHex) { final String style = getStyle(message.style(), motd); - final String _color = getColor(message.color(), motd, ansi); + final String _color = getColor(message.color(), motd, ansi, noHex); String color; if (_color == null) color = ""; else color = _color; return new PartiallyStringified((lastColor != null ? lastColor : "") + color + (style != null && ansi ? style : "") + message.pattern(), _color); // * Client-side selector components are equivalent to text ones, and do NOT list entities. } - public static PartiallyStringified stringifyPartially (KeybindComponent message, boolean motd, boolean ansi, String lastColor) { + public static PartiallyStringified stringifyPartially (KeybindComponent message, boolean motd, boolean ansi, String lastColor, boolean noHex) { String keybind = message.keybind(); Component component = keybinds.containsKey(keybind) ? Component.translatable(keybind) : Component.text(keybind); // TODO: Fix some keys like `key.keyboard.a` - return stringifyPartially(component, motd, ansi, lastColor); + return stringifyPartially(component, motd, ansi, lastColor, noHex); } }