diff --git a/patches/server/Add-support-for-hex-color-codes-in-console.patch b/patches/server/Add-support-for-hex-color-codes-in-console.patch deleted file mode 100644 index 33fa37d21..000000000 --- a/patches/server/Add-support-for-hex-color-codes-in-console.patch +++ /dev/null @@ -1,327 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Josh Roy <10731363+JRoy@users.noreply.github.com> -Date: Sat, 20 Feb 2021 13:09:59 -0500 -Subject: [PATCH] Add support for hex color codes in console - -Converts upstream's hex color code legacy format into actual hex color codes in the console. - -diff --git a/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java -+++ b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java -@@ -0,0 +0,0 @@ - package com.destroystokyo.paper.console; - -+import net.kyori.adventure.audience.MessageType; -+import net.kyori.adventure.identity.Identity; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.logger.slf4j.ComponentLogger; -+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; - import org.apache.logging.log4j.LogManager; --import org.apache.logging.log4j.Logger; - import org.bukkit.craftbukkit.command.CraftConsoleCommandSender; - - public class TerminalConsoleCommandSender extends CraftConsoleCommandSender { - -- private static final Logger LOGGER = LogManager.getRootLogger(); -+ private static final ComponentLogger LOGGER = ComponentLogger.logger(LogManager.getRootLogger().getName()); - - @Override - public void sendRawMessage(String message) { -- // TerminalConsoleAppender supports color codes directly in log messages -+ final Component msg = LegacyComponentSerializer.legacySection().deserialize(message); -+ this.sendMessage(Identity.nil(), msg, MessageType.SYSTEM); -+ } -+ -+ @Override -+ public void sendMessage(Identity identity, Component message, MessageType type) { - LOGGER.info(message); - } - -diff --git a/src/main/java/io/papermc/paper/adventure/providers/ComponentLoggerProviderImpl.java b/src/main/java/io/papermc/paper/adventure/providers/ComponentLoggerProviderImpl.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/io/papermc/paper/adventure/providers/ComponentLoggerProviderImpl.java -+++ b/src/main/java/io/papermc/paper/adventure/providers/ComponentLoggerProviderImpl.java -@@ -0,0 +0,0 @@ - package io.papermc.paper.adventure.providers; - --import io.papermc.paper.adventure.PaperAdventure; -+import io.papermc.paper.console.HexFormattingConverter; -+import java.util.Locale; - import net.kyori.adventure.text.Component; - import net.kyori.adventure.text.logger.slf4j.ComponentLogger; - import net.kyori.adventure.text.logger.slf4j.ComponentLoggerProvider; -+import net.kyori.adventure.translation.GlobalTranslator; - import org.jetbrains.annotations.NotNull; - import org.slf4j.LoggerFactory; - -@@ -0,0 +0,0 @@ public class ComponentLoggerProviderImpl implements ComponentLoggerProvider { - } - - private String serialize(final Component message) { -- return PaperAdventure.asPlain(message, null); -+ return HexFormattingConverter.SERIALIZER.serialize(GlobalTranslator.render(message, Locale.getDefault())); - } - } -diff --git a/src/main/java/io/papermc/paper/console/HexFormattingConverter.java b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.console; -+ -+import io.papermc.paper.configuration.GlobalConfiguration; -+import io.papermc.paper.adventure.PaperAdventure; -+import net.kyori.adventure.text.format.NamedTextColor; -+import net.kyori.adventure.text.format.TextColor; -+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -+import net.minecrell.terminalconsole.TerminalConsoleAppender; -+import org.apache.logging.log4j.core.LogEvent; -+import org.apache.logging.log4j.core.config.Configuration; -+import org.apache.logging.log4j.core.config.plugins.Plugin; -+import org.apache.logging.log4j.core.layout.PatternLayout; -+import org.apache.logging.log4j.core.pattern.ConverterKeys; -+import org.apache.logging.log4j.core.pattern.LogEventPatternConverter; -+import org.apache.logging.log4j.core.pattern.PatternConverter; -+import org.apache.logging.log4j.core.pattern.PatternFormatter; -+import org.apache.logging.log4j.core.pattern.PatternParser; -+import org.apache.logging.log4j.util.PerformanceSensitive; -+import org.apache.logging.log4j.util.PropertiesUtil; -+ -+import java.util.List; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+ -+import static net.minecrell.terminalconsole.MinecraftFormattingConverter.KEEP_FORMATTING_PROPERTY; -+ -+/** -+ * Modified version of -+ * TerminalConsoleAppender's MinecraftFormattingConverter to support hex color codes using the Adventure [char]#rrggbb format. -+ */ -+@Plugin(name = "paperMinecraftFormatting", category = PatternConverter.CATEGORY) -+@ConverterKeys({"paperMinecraftFormatting"}) -+@PerformanceSensitive("allocation") -+public final class HexFormattingConverter extends LogEventPatternConverter { -+ -+ private static final boolean KEEP_FORMATTING = PropertiesUtil.getProperties().getBooleanProperty(KEEP_FORMATTING_PROPERTY); -+ -+ private static final String ANSI_RESET = "\u001B[m"; -+ -+ private static final char COLOR_CHAR = 0x7f; -+ public static final LegacyComponentSerializer SERIALIZER = LegacyComponentSerializer.builder() -+ .hexColors() -+ .flattener(PaperAdventure.FLATTENER) -+ .character(HexFormattingConverter.COLOR_CHAR) -+ .build(); -+ private static final String LOOKUP = "0123456789abcdefklmnor"; -+ -+ private static final String RGB_ANSI = "\u001B[38;2;%d;%d;%dm"; -+ private static final String RESET_RGB_ANSI = ANSI_RESET + RGB_ANSI; -+ private static final Pattern NAMED_PATTERN = Pattern.compile(COLOR_CHAR + "[0-9a-fk-orA-FK-OR]"); -+ private static final Pattern RGB_PATTERN = Pattern.compile(COLOR_CHAR + "#([0-9a-fA-F]){6}"); -+ -+ private static final String[] RGB_ANSI_CODES = new String[]{ -+ formatHexAnsi(NamedTextColor.BLACK), // Black §0 -+ formatHexAnsi(NamedTextColor.DARK_BLUE), // Dark Blue §1 -+ formatHexAnsi(NamedTextColor.DARK_GREEN), // Dark Green §2 -+ formatHexAnsi(NamedTextColor.DARK_AQUA), // Dark Aqua §3 -+ formatHexAnsi(NamedTextColor.DARK_RED), // Dark Red §4 -+ formatHexAnsi(NamedTextColor.DARK_PURPLE), // Dark Purple §5 -+ formatHexAnsi(NamedTextColor.GOLD), // Gold §6 -+ formatHexAnsi(NamedTextColor.GRAY), // Gray §7 -+ formatHexAnsi(NamedTextColor.DARK_GRAY), // Dark Gray §8 -+ formatHexAnsi(NamedTextColor.BLUE), // Blue §9 -+ formatHexAnsi(NamedTextColor.GREEN), // Green §a -+ formatHexAnsi(NamedTextColor.AQUA), // Aqua §b -+ formatHexAnsi(NamedTextColor.RED), // Red §c -+ formatHexAnsi(NamedTextColor.LIGHT_PURPLE), // Light Purple §d -+ formatHexAnsi(NamedTextColor.YELLOW), // Yellow §e -+ formatHexAnsi(NamedTextColor.WHITE), // White §f -+ "\u001B[5m", // Obfuscated §k -+ "\u001B[1m", // Bold §l -+ "\u001B[9m", // Strikethrough §m -+ "\u001B[4m", // Underline §n -+ "\u001B[3m", // Italic §o -+ ANSI_RESET, // Reset §r -+ }; -+ private static final String[] ANSI_ANSI_CODES = new String[]{ -+ ANSI_RESET + "\u001B[0;30m", // Black §0 -+ ANSI_RESET + "\u001B[0;34m", // Dark Blue §1 -+ ANSI_RESET + "\u001B[0;32m", // Dark Green §2 -+ ANSI_RESET + "\u001B[0;36m", // Dark Aqua §3 -+ ANSI_RESET + "\u001B[0;31m", // Dark Red §4 -+ ANSI_RESET + "\u001B[0;35m", // Dark Purple §5 -+ ANSI_RESET + "\u001B[0;33m", // Gold §6 -+ ANSI_RESET + "\u001B[0;37m", // Gray §7 -+ ANSI_RESET + "\u001B[0;30;1m", // Dark Gray §8 -+ ANSI_RESET + "\u001B[0;34;1m", // Blue §9 -+ ANSI_RESET + "\u001B[0;32;1m", // Green §a -+ ANSI_RESET + "\u001B[0;36;1m", // Aqua §b -+ ANSI_RESET + "\u001B[0;31;1m", // Red §c -+ ANSI_RESET + "\u001B[0;35;1m", // Light Purple §d -+ ANSI_RESET + "\u001B[0;33;1m", // Yellow §e -+ ANSI_RESET + "\u001B[0;37;1m", // White §f -+ "\u001B[5m", // Obfuscated §k -+ "\u001B[1m", // Bold §l -+ "\u001B[9m", // Strikethrough §m -+ "\u001B[4m", // Underline §n -+ "\u001B[3m", // Italic §o -+ ANSI_RESET, // Reset §r -+ }; -+ -+ private final boolean ansi; -+ private final List formatters; -+ -+ /** -+ * Construct the converter. -+ * -+ * @param formatters The pattern formatters to generate the text to manipulate -+ * @param strip If true, the converter will strip all formatting codes -+ */ -+ protected HexFormattingConverter(List formatters, boolean strip) { -+ super("paperMinecraftFormatting", null); -+ this.formatters = formatters; -+ this.ansi = !strip; -+ } -+ -+ @Override -+ public void format(LogEvent event, StringBuilder toAppendTo) { -+ int start = toAppendTo.length(); -+ //noinspection ForLoopReplaceableByForEach -+ for (int i = 0, size = formatters.size(); i < size; i++) { -+ formatters.get(i).format(event, toAppendTo); -+ } -+ -+ if (KEEP_FORMATTING || toAppendTo.length() == start) { -+ // Skip replacement if disabled or if the content is empty -+ return; -+ } -+ -+ boolean useAnsi = ansi && TerminalConsoleAppender.isAnsiSupported(); -+ String content = toAppendTo.substring(start); -+ content = useAnsi ? convertRGBColors(content) : stripRGBColors(content); -+ format(content, toAppendTo, start, useAnsi); -+ } -+ -+ private static String convertRGBColors(final String input) { -+ return RGB_PATTERN.matcher(input).replaceAll(result -> { -+ final int hex = Integer.decode(result.group().substring(1)); -+ return formatHexAnsi(hex); -+ }); -+ } -+ -+ private static String formatHexAnsi(final TextColor color) { -+ return formatHexAnsi(color.value()); -+ } -+ -+ private static String formatHexAnsi(final int color) { -+ final int red = color >> 16 & 0xFF; -+ final int green = color >> 8 & 0xFF; -+ final int blue = color & 0xFF; -+ return String.format(RESET_RGB_ANSI, red, green, blue); -+ } -+ -+ private static String stripRGBColors(final String input) { -+ return RGB_PATTERN.matcher(input).replaceAll(""); -+ } -+ -+ static void format(String content, StringBuilder result, int start, boolean ansi) { -+ int next = content.indexOf(COLOR_CHAR); -+ int last = content.length() - 1; -+ if (next == -1 || next == last) { -+ result.setLength(start); -+ result.append(content); -+ if (ansi) { -+ result.append(ANSI_RESET); -+ } -+ return; -+ } -+ -+ Matcher matcher = NAMED_PATTERN.matcher(content); -+ StringBuilder buffer = new StringBuilder(); -+ final String[] ansiCodes = GlobalConfiguration.get().logging.useRgbForNamedTextColors ? RGB_ANSI_CODES : ANSI_ANSI_CODES; -+ while (matcher.find()) { -+ int format = LOOKUP.indexOf(Character.toLowerCase(matcher.group().charAt(1))); -+ if (format != -1) { -+ matcher.appendReplacement(buffer, ansi ? ansiCodes[format] : ""); -+ } -+ } -+ matcher.appendTail(buffer); -+ -+ result.setLength(start); -+ result.append(buffer); -+ if (ansi) { -+ result.append(ANSI_RESET); -+ } -+ } -+ -+ /** -+ * Gets a new instance of the {@link HexFormattingConverter} with the -+ * specified options. -+ * -+ * @param config The current configuration -+ * @param options The pattern options -+ * @return The new instance -+ * @see HexFormattingConverter -+ */ -+ public static HexFormattingConverter newInstance(Configuration config, String[] options) { -+ if (options.length < 1 || options.length > 2) { -+ LOGGER.error("Incorrect number of options on paperMinecraftFormatting. Expected at least 1, max 2 received " + options.length); -+ return null; -+ } -+ if (options[0] == null) { -+ LOGGER.error("No pattern supplied on paperMinecraftFormatting"); -+ return null; -+ } -+ -+ PatternParser parser = PatternLayout.createPatternParser(config); -+ List formatters = parser.parse(options[0]); -+ boolean strip = options.length > 1 && "strip".equals(options[1]); -+ return new HexFormattingConverter(formatters, strip); -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop - - -- -+ - - - -+ pattern="%highlightError{[%d{HH:mm:ss} %level]: %paperMinecraftFormatting{%msg}%n%xEx{full}}" /> - - - - - -- -+ - - - -+ pattern="[%d{HH:mm:ss}] [%t/%level]: %paperMinecraftFormatting{%msg}{strip}%n%xEx{full}" /> - - - diff --git a/patches/server/Deobfuscate-stacktraces-in-log-messages-crash-report.patch b/patches/server/Deobfuscate-stacktraces-in-log-messages-crash-report.patch index 0d9b3a069..6d4ff62ae 100644 --- a/patches/server/Deobfuscate-stacktraces-in-log-messages-crash-report.patch +++ b/patches/server/Deobfuscate-stacktraces-in-log-messages-crash-report.patch @@ -9,14 +9,6 @@ diff --git a/build.gradle.kts b/build.gradle.kts index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -0,0 +0,0 @@ dependencies { - Scanning takes about 1-2 seconds so adding this speeds up the server start. - */ - implementation("org.apache.logging.log4j:log4j-core:2.14.1") // Paper - implementation -+ annotationProcessor("org.apache.logging.log4j:log4j-core:2.14.1") // Paper - Needed to generate meta for our Log4j plugins - // Paper end - implementation("org.apache.logging.log4j:log4j-iostreams:2.19.0") // Paper - remove exclusion - implementation("org.ow2.asm:asm:9.4") @@ -0,0 +0,0 @@ dependencies { testImplementation("org.mockito:mockito-core:4.9.0") // Paper - switch to mockito implementation("org.spongepowered:configurate-yaml:4.1.2") // Paper - config files diff --git a/patches/server/Handle-plugin-prefixes-using-Log4J-configuration.patch b/patches/server/Handle-plugin-prefixes-using-Log4J-configuration.patch index 150d84a27..cf13c857c 100644 --- a/patches/server/Handle-plugin-prefixes-using-Log4J-configuration.patch +++ b/patches/server/Handle-plugin-prefixes-using-Log4J-configuration.patch @@ -24,9 +24,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 */ - runtimeOnly("org.apache.logging.log4j:log4j-core:2.14.1") + implementation("org.apache.logging.log4j:log4j-core:2.14.1") // Paper - implementation + annotationProcessor("org.apache.logging.log4j:log4j-core:2.14.1") // Paper - Needed to generate meta for our Log4j plugins // Paper end implementation("org.apache.logging.log4j:log4j-iostreams:2.19.0") // Paper - remove exclusion - implementation("org.ow2.asm:asm:9.4") diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/spigotmc/SpigotConfig.java @@ -48,22 +48,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 -- +- + -+ ++ + + ++ pattern="%highlightError{[%d{HH:mm:ss} %level]: %msg%n%xEx}" /> + + -- +- + -+ ++ + + ++ pattern="[%d{HH:mm:ss}] [%t/%level]: %stripAnsi{%msg}%n" /> + + diff --git a/patches/server/Improve-Log4J-Configuration-Plugin-Loggers.patch b/patches/server/Improve-Log4J-Configuration-Plugin-Loggers.patch index 4258e756b..4cd4de018 100644 --- a/patches/server/Improve-Log4J-Configuration-Plugin-Loggers.patch +++ b/patches/server/Improve-Log4J-Configuration-Plugin-Loggers.patch @@ -21,27 +21,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 -- -+ +- ++ - +- pattern="%highlightError{[%d{HH:mm:ss} %level]: %msg%n%xEx}" /> + + ++ pattern="%highlightError{[%d{HH:mm:ss} %level]: %msg%n%xEx{full}}" /> -- -+ +- ++ - +- pattern="[%d{HH:mm:ss}] [%t/%level]: %stripAnsi{%msg}%n" /> + + ++ pattern="[%d{HH:mm:ss}] [%t/%level]: %stripAnsi{%msg}%n%xEx{full}" /> diff --git a/patches/server/Paper-config-files.patch b/patches/server/Paper-config-files.patch index 7657bb6be..387d8beb5 100644 --- a/patches/server/Paper-config-files.patch +++ b/patches/server/Paper-config-files.patch @@ -604,7 +604,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public class Logging extends ConfigurationPart { + public boolean logPlayerIpAddresses = true; + public boolean deobfuscateStacktraces = true; -+ public boolean useRgbForNamedTextColors = true; + } + + public Scoreboards scoreboards; @@ -1442,7 +1441,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + path("commandErrorMessage"), + path("baby-zombie-movement-speed"), + path("limit-player-interactions"), -+ path("warnWhenSettingExcessiveVelocity") ++ path("warnWhenSettingExcessiveVelocity"), ++ path("logging", "use-rgb-for-named-text-colors") + }; + +} diff --git a/patches/server/Use-TerminalConsoleAppender-for-console-improvements.patch b/patches/server/Use-TerminalConsoleAppender-for-console-improvements.patch index 3f2fd691d..597f10fe6 100644 --- a/patches/server/Use-TerminalConsoleAppender-for-console-improvements.patch +++ b/patches/server/Use-TerminalConsoleAppender-for-console-improvements.patch @@ -6,6 +6,10 @@ Subject: [PATCH] Use TerminalConsoleAppender for console improvements Rewrite console improvements (console colors, tab completion, persistent input line, ...) using JLine 3.x and TerminalConsoleAppender. +Also uses the new ANSIComponentSerializer to serialize components when +logging them via the ComponentLogger, or when sending messages to the +console, for hex color support. + New features: - Support console colors for Vanilla commands - Add console colors for warnings and errors @@ -18,6 +22,8 @@ Other changes: - Server starts 1-2 seconds faster thanks to optimizations in Log4j configuration +Co-Authored-By: Emilia Kond + diff --git a/build.gradle.kts b/build.gradle.kts index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/build.gradle.kts @@ -30,6 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start + implementation("org.jline:jline-terminal-jansi:3.21.0") + implementation("net.minecrell:terminalconsoleappender:1.3.0") ++ implementation("net.kyori:adventure-text-serializer-ansi") + /* + Required to add the missing Log4j2Plugins.dat file from log4j-core + which has been removed by Mojang. Without it, log4j has to classload @@ -37,6 +44,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + Scanning takes about 1-2 seconds so adding this speeds up the server start. + */ + runtimeOnly("org.apache.logging.log4j:log4j-core:2.14.1") ++ annotationProcessor("org.apache.logging.log4j:log4j-core:2.14.1") // Paper - Needed to generate meta for our Log4j plugins + // Paper end implementation("org.apache.logging.log4j:log4j-iostreams:2.19.0") // Paper - remove exclusion implementation("org.ow2.asm:asm:9.4") @@ -96,21 +104,133 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package com.destroystokyo.paper.console; + ++import net.kyori.adventure.audience.MessageType; ++import net.kyori.adventure.identity.Identity; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.logger.slf4j.ComponentLogger; ++import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.apache.logging.log4j.LogManager; -+import org.apache.logging.log4j.Logger; +import org.bukkit.craftbukkit.command.CraftConsoleCommandSender; + +public class TerminalConsoleCommandSender extends CraftConsoleCommandSender { + -+ private static final Logger LOGGER = LogManager.getRootLogger(); ++ private static final ComponentLogger LOGGER = ComponentLogger.logger(LogManager.getRootLogger().getName()); + + @Override + public void sendRawMessage(String message) { -+ // TerminalConsoleAppender supports color codes directly in log messages ++ final Component msg = LegacyComponentSerializer.legacySection().deserialize(message); ++ this.sendMessage(Identity.nil(), msg, MessageType.SYSTEM); ++ } ++ ++ @Override ++ public void sendMessage(Identity identity, Component message, MessageType type) { + LOGGER.info(message); + } + +} +diff --git a/src/main/java/io/papermc/paper/adventure/PaperAdventure.java b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/io/papermc/paper/adventure/PaperAdventure.java ++++ b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java +@@ -0,0 +0,0 @@ import net.kyori.adventure.text.TranslatableComponent; + import net.kyori.adventure.text.flattener.ComponentFlattener; + import net.kyori.adventure.text.format.TextColor; + import net.kyori.adventure.text.serializer.ComponentSerializer; ++import net.kyori.adventure.text.serializer.ansi.ANSIComponentSerializer; + import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; + import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; + import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +@@ -0,0 +0,0 @@ public final class PaperAdventure { + public static final AttributeKey LOCALE_ATTRIBUTE = AttributeKey.valueOf("adventure:locale"); // init after FLATTENER because classloading triggered here might create a logger + @Deprecated + public static final PlainComponentSerializer PLAIN = PlainComponentSerializer.builder().flattener(FLATTENER).build(); ++ ++ public static final ANSIComponentSerializer ANSI_SERIALIZER = ANSIComponentSerializer.builder().flattener(FLATTENER).build(); ++ + private static final Codec NBT_CODEC = new Codec() { + @Override + public @NotNull CompoundTag decode(final @NotNull String encoded) throws IOException { +diff --git a/src/main/java/io/papermc/paper/adventure/providers/ComponentLoggerProviderImpl.java b/src/main/java/io/papermc/paper/adventure/providers/ComponentLoggerProviderImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/io/papermc/paper/adventure/providers/ComponentLoggerProviderImpl.java ++++ b/src/main/java/io/papermc/paper/adventure/providers/ComponentLoggerProviderImpl.java +@@ -0,0 +0,0 @@ + package io.papermc.paper.adventure.providers; + + import io.papermc.paper.adventure.PaperAdventure; ++import java.util.Locale; + import net.kyori.adventure.text.Component; + import net.kyori.adventure.text.logger.slf4j.ComponentLogger; + import net.kyori.adventure.text.logger.slf4j.ComponentLoggerProvider; ++import net.kyori.adventure.translation.GlobalTranslator; + import org.jetbrains.annotations.NotNull; + import org.slf4j.LoggerFactory; + +@@ -0,0 +0,0 @@ public class ComponentLoggerProviderImpl implements ComponentLoggerProvider { + } + + private String serialize(final Component message) { +- return PaperAdventure.asPlain(message, null); ++ return PaperAdventure.ANSI_SERIALIZER.serialize(GlobalTranslator.render(message, Locale.getDefault())); + } + } +diff --git a/src/main/java/io/papermc/paper/console/StripANSIConverter.java b/src/main/java/io/papermc/paper/console/StripANSIConverter.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/console/StripANSIConverter.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.console; ++ ++import org.apache.logging.log4j.core.LogEvent; ++import org.apache.logging.log4j.core.config.Configuration; ++import org.apache.logging.log4j.core.config.plugins.Plugin; ++import org.apache.logging.log4j.core.layout.PatternLayout; ++import org.apache.logging.log4j.core.pattern.ConverterKeys; ++import org.apache.logging.log4j.core.pattern.LogEventPatternConverter; ++import org.apache.logging.log4j.core.pattern.PatternConverter; ++import org.apache.logging.log4j.core.pattern.PatternFormatter; ++import org.apache.logging.log4j.core.pattern.PatternParser; ++ ++import java.util.List; ++import java.util.regex.Pattern; ++ ++@Plugin(name = "stripAnsi", category = PatternConverter.CATEGORY) ++@ConverterKeys({"stripAnsi"}) ++public final class StripANSIConverter extends LogEventPatternConverter { ++ final private Pattern ANSI_PATTERN = Pattern.compile("\\e\\[[\\d;]*[^\\d;]"); ++ ++ private final List formatters; ++ ++ private StripANSIConverter(List formatters) { ++ super("stripAnsi", null); ++ this.formatters = formatters; ++ } ++ ++ @Override ++ public void format(LogEvent event, StringBuilder toAppendTo) { ++ int start = toAppendTo.length(); ++ for (PatternFormatter formatter : formatters) { ++ formatter.format(event, toAppendTo); ++ } ++ String content = toAppendTo.substring(start); ++ content = ANSI_PATTERN.matcher(content).replaceAll(""); ++ ++ toAppendTo.setLength(start); ++ toAppendTo.append(content); ++ } ++ ++ public static StripANSIConverter newInstance(Configuration config, String[] options) { ++ if (options.length != 1) { ++ LOGGER.error("Incorrect number of options on stripAnsi. Expected exactly 1, received " + options.length); ++ return null; ++ } ++ ++ PatternParser parser = PatternLayout.createPatternParser(config); ++ List formatters = parser.parse(options[0]); ++ return new StripANSIConverter(formatters); ++ } ++} diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java @@ -166,7 +286,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public void sendSystemMessage(Component message) { - MinecraftServer.LOGGER.info(message.getString()); -+ MinecraftServer.LOGGER.info(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(io.papermc.paper.adventure.PaperAdventure.asAdventure(message))); // Paper - Log message with colors ++ MinecraftServer.LOGGER.info(io.papermc.paper.adventure.PaperAdventure.ANSI_SERIALIZER.serialize(io.papermc.paper.adventure.PaperAdventure.asAdventure(message))); // Paper - Log message with colors } public KeyPair getKeyPair() { @@ -221,6 +341,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 System.setOut(IoBuilder.forLogger(logger).setLevel(Level.INFO).buildPrintStream()); System.setErr(IoBuilder.forLogger(logger).setLevel(Level.WARN).buildPrintStream()); +diff --git a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java ++++ b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java +@@ -0,0 +0,0 @@ public class MinecraftServerGui extends JComponent { + this.finalizers.forEach(Runnable::run); + } + +- private static final java.util.regex.Pattern ANSI = java.util.regex.Pattern.compile("\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})*)?[m|K]"); // CraftBukkit ++ private static final java.util.regex.Pattern ANSI = java.util.regex.Pattern.compile("\\e\\[[\\d;]*[^\\d;]"); // CraftBukkit // Paper + public void print(JTextArea textArea, JScrollPane scrollPane, String message) { + if (!SwingUtilities.isEventDispatchThread()) { + SwingUtilities.invokeLater(() -> { diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java @@ -495,11 +628,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - - + -+ ++ + - -+ ++