diff --git a/build-number.txt b/build-number.txt index c5e035ca..dba60802 100644 --- a/build-number.txt +++ b/build-number.txt @@ -1 +1 @@ -2021 \ No newline at end of file +2024 \ No newline at end of file diff --git a/src/main/java/me/chayapak1/chomens_bot/Configuration.java b/src/main/java/me/chayapak1/chomens_bot/Configuration.java index 185f5bd1..ee6b65d3 100644 --- a/src/main/java/me/chayapak1/chomens_bot/Configuration.java +++ b/src/main/java/me/chayapak1/chomens_bot/Configuration.java @@ -32,6 +32,8 @@ public class Configuration { public String ownerName = "chayapak"; // mabe mabe + public String consoleChatFormat = "{\"translate\":\"chat.type.text\",\"with\":[\"OWNER_NAME\",\"MESSAGE\"]}"; + public ImposterFormatChecker imposterFormatChecker = new ImposterFormatChecker(); public OwnerAuthentication ownerAuthentication = new OwnerAuthentication(); diff --git a/src/main/java/me/chayapak1/chomens_bot/Main.java b/src/main/java/me/chayapak1/chomens_bot/Main.java index 0aeb1d5a..efb9a3cd 100644 --- a/src/main/java/me/chayapak1/chomens_bot/Main.java +++ b/src/main/java/me/chayapak1/chomens_bot/Main.java @@ -131,7 +131,7 @@ public class Main { } // initialize plugins - console = new ConsolePlugin(); + console = new ConsolePlugin(config); LoggerPlugin.init(); if (config.database.enabled) database = new DatabasePlugin(config); if (config.discord.enabled) discord = new DiscordPlugin(config); diff --git a/src/main/java/me/chayapak1/chomens_bot/plugins/ConsolePlugin.java b/src/main/java/me/chayapak1/chomens_bot/plugins/ConsolePlugin.java index 65b92d9e..f642257c 100644 --- a/src/main/java/me/chayapak1/chomens_bot/plugins/ConsolePlugin.java +++ b/src/main/java/me/chayapak1/chomens_bot/plugins/ConsolePlugin.java @@ -1,27 +1,43 @@ package me.chayapak1.chomens_bot.plugins; import me.chayapak1.chomens_bot.Bot; +import me.chayapak1.chomens_bot.Configuration; import me.chayapak1.chomens_bot.Main; import me.chayapak1.chomens_bot.command.Command; import me.chayapak1.chomens_bot.command.ConsoleCommandContext; -import me.chayapak1.chomens_bot.util.ColorUtilities; import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.ComponentBuilder; +import net.kyori.adventure.text.SelectorComponent; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.renderer.TranslatableComponentRenderer; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.jetbrains.annotations.NotNull; import org.jline.reader.*; import java.util.List; +import java.util.Map; public class ConsolePlugin implements Completer { + private static final ConsoleFormatRenderer RENDERER = new ConsoleFormatRenderer(); + private static final LegacyComponentSerializer LEGACY = LegacyComponentSerializer.legacyAmpersand(); + private final List allBots; public final LineReader reader; public String consoleServer = "all"; - private String prefix; + private final String prefix; - public ConsolePlugin () { + private final Component format; + + public ConsolePlugin (Configuration config) { this.allBots = Main.bots; + this.format = GsonComponentSerializer.gson().deserialize(config.consoleChatFormat); + this.prefix = config.consoleCommandPrefix; this.reader = LineReaderBuilder .builder() .completer(this) @@ -29,11 +45,7 @@ public class ConsolePlugin implements Completer { reader.option(LineReader.Option.DISABLE_EVENT_EXPANSION, true); - for (Bot bot : allBots) { - prefix = bot.config.consoleCommandPrefix; - - bot.console = this; - } + for (Bot bot : allBots) bot.console = this; final String prompt = "> "; @@ -56,7 +68,7 @@ public class ConsolePlugin implements Completer { @Override public void complete(LineReader reader, ParsedLine line, List candidates) { - if (!line.line().startsWith(".")) return; + if (!line.line().startsWith(prefix)) return; final String command = line.line().substring(prefix.length()); @@ -93,14 +105,98 @@ public class ConsolePlugin implements Completer { continue; } - bot.chat.tellraw( - Component.translatable( - "[%s] %s › %s", - Component.text(bot.username + " Console").color(NamedTextColor.GRAY), - Component.text(bot.config.ownerName).color(ColorUtilities.getColorByString(bot.config.colorPalette.ownerName)), - Component.text(line).color(NamedTextColor.GRAY) - ).color(NamedTextColor.DARK_GRAY) + final Component stylizedMessage = LEGACY.deserialize(line); + + final Component rendered = RENDERER.render( + format, + new ConsoleFormatContext( + bot.profile.getIdAsString(), + stylizedMessage, + Map.of( + "MESSAGE", line, + "USERNAME", bot.profile.getName(), + "OWNER_NAME", bot.config.ownerName + ) + ) ); + + bot.chat.tellraw(rendered); + } + } + + // Everything below is from https://code.chipmunk.land/ChomeNS/chipmunkmod/src/branch/1.21.4/src/main/java/land/chipmunk/chipmunkmod/modules/custom_chat + // Thank you, Amy! + private record ConsoleFormatContext (String uuid, Component message, Map args) {} + + private final static class ConsoleFormatRenderer extends TranslatableComponentRenderer { + @Override + protected @NotNull Component renderSelector (final @NotNull SelectorComponent component, + final @NotNull ConsoleFormatContext context) { + final String pattern = component.pattern(); + if (pattern.equals("@s")) { + final SelectorComponent.Builder builder = Component.selector() + .pattern(context.uuid()); + + return this.mergeStyleAndOptionallyDeepRender(component, builder, context); + } + + return super.renderSelector(component, context); + } + + @Override + protected @NotNull Component renderText (final @NotNull TextComponent component, + final @NotNull ConsoleFormatContext context) { + final String content = component.content(); + if (content.equals("MESSAGE")) { + return this.mergeMessage(component, context.message(), context); + } + + final String arg = context.args().get(component.content()); + if (arg != null) { + final TextComponent.Builder builder = Component.text() + .content(arg); + + return this.mergeStyleAndOptionallyDeepRender(component, builder, context); + } + + return super.renderText(component, context); + } + + @SuppressWarnings("NonExtendableApiUsage") // Windows XP + @Override + protected > void mergeStyle (final Component component, final B builder, + final ConsoleFormatContext context) { + super.mergeStyle(component, builder, context); + + // render clickEvent that may contain something like "MESSAGE" + // HoverEvent already handled by super + builder.clickEvent(this.mergeClickEvent(component.clickEvent(), context)); + } + + private Component mergeMessage (final Component root, final Component msg, final ConsoleFormatContext context) { + Component result = msg.applyFallbackStyle(root.style()); // applyFallbackStyle will apply everything that isn't content + + final ClickEvent clickEvent = result.clickEvent(); + if (clickEvent != null) { + result = result.clickEvent(mergeClickEvent(clickEvent, context)); + } + + final HoverEvent hoverEvent = result.hoverEvent(); + if (hoverEvent != null) { + result = result.hoverEvent(hoverEvent.withRenderedValue(this, context)); + } + + return result; + } + + private ClickEvent mergeClickEvent (final ClickEvent clickEvent, final ConsoleFormatContext context) { + if (clickEvent == null) return null; + + final String value = clickEvent.value(); + final String arg = context.args().get(value); + if (arg == null) return clickEvent; + + return ClickEvent.clickEvent(clickEvent.action(), arg); } } } diff --git a/src/main/resources/default-config.yml b/src/main/resources/default-config.yml index b7054f4a..6e9ad746 100644 --- a/src/main/resources/default-config.yml +++ b/src/main/resources/default-config.yml @@ -69,6 +69,8 @@ colorPalette: # you HAVE TO CHANGE THIS if you are hosting another instance of my bot. ownerName: 'XxChange_mexX' +consoleChatFormat: '{"translate":"chat.type.text","with":["OWNER_NAME","MESSAGE"]}' + imposterFormatChecker: enabled: false key: ''