@@ -5,20 +5,82 @@ Subject: [PATCH] Add support for hex color codes in console
5
5
6
6
Converts upstream's hex color code legacy format into actual hex color codes in the console.
7
7
8
+ diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
9
+ index a0a3cec47c8f9e379a5bc1d43eeda5eb9d81f814..23d849872109e43d6e22a953d3a4298565d4621d 100644
10
+ --- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
11
+ +++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
12
+ @@ -454,8 +454,10 @@ public class PaperConfig {
13
+ }
14
+
15
+ public static boolean deobfuscateStacktraces = true;
16
+ + public static boolean useRgbForNamedTextColors = true;
17
+ private static void loggerSettings() {
18
+ deobfuscateStacktraces = getBoolean("settings.loggers.deobfuscate-stacktraces", deobfuscateStacktraces);
19
+ + useRgbForNamedTextColors = getBoolean("settings.loggers.use-rgb-for-named-text-colors", useRgbForNamedTextColors);
20
+ }
21
+
22
+ public static boolean allowBlockPermanentBreakingExploits = false;
23
+ diff --git a/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java
24
+ index 685deaa0e5d1ddc13e3a7c0471b1cfcf1710c869..aa574c646ee9c9951d183c80e1a0fe10c21850a0 100644
25
+ --- a/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java
26
+ +++ b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java
27
+ @@ -1,5 +1,11 @@
28
+ package com.destroystokyo.paper.console;
29
+
30
+ + import io.papermc.paper.adventure.PaperAdventure;
31
+ + import io.papermc.paper.console.HexFormattingConverter;
32
+ + import net.kyori.adventure.audience.MessageType;
33
+ + import net.kyori.adventure.identity.Identity;
34
+ + import net.kyori.adventure.text.Component;
35
+ + import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
36
+ import org.apache.logging.log4j.LogManager;
37
+ import org.apache.logging.log4j.Logger;
38
+ import org.bukkit.craftbukkit.command.CraftConsoleCommandSender;
39
+ @@ -7,11 +13,21 @@ import org.bukkit.craftbukkit.command.CraftConsoleCommandSender;
40
+ public class TerminalConsoleCommandSender extends CraftConsoleCommandSender {
41
+
42
+ private static final Logger LOGGER = LogManager.getRootLogger();
43
+ + private static final LegacyComponentSerializer SERIALIZER = LegacyComponentSerializer.builder()
44
+ + .hexColors()
45
+ + .flattener(PaperAdventure.FLATTENER)
46
+ + .character(HexFormattingConverter.COLOR_CHAR)
47
+ + .build();
48
+
49
+ @Override
50
+ public void sendRawMessage(String message) {
51
+ - // TerminalConsoleAppender supports color codes directly in log messages
52
+ - LOGGER.info(message);
53
+ + final Component msg = PaperAdventure.LEGACY_SECTION_UXRC.deserialize(message);
54
+ + this.sendMessage(Identity.nil(), msg, MessageType.SYSTEM);
55
+ + }
56
+ +
57
+ + @Override
58
+ + public void sendMessage(Identity identity, Component message, MessageType type) {
59
+ + LOGGER.info(SERIALIZER.serialize(message));
60
+ }
61
+
62
+ }
8
63
diff --git a/src/main/java/io/papermc/paper/console/HexFormattingConverter.java b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java
9
64
new file mode 100644
10
- index 0000000000000000000000000000000000000000..a4315961b7a465fb4872a4d67e7c26d4b4ed1fb9
65
+ index 0000000000000000000000000000000000000000..7800125d0ce59547b9a12b74b9de851ce2ee2f92
11
66
--- /dev/null
12
67
+++ b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java
13
- @@ -0,0 +1,178 @@
68
+ @@ -0,0 +1,205 @@
14
69
+ package io.papermc.paper.console;
15
70
+
71
+ + import com.destroystokyo.paper.PaperConfig;
72
+ + import net.kyori.adventure.text.format.NamedTextColor;
73
+ + import net.kyori.adventure.text.format.TextColor;
16
74
+ import net.minecrell.terminalconsole.TerminalConsoleAppender;
17
75
+ import org.apache.logging.log4j.core.LogEvent;
18
76
+ import org.apache.logging.log4j.core.config.Configuration;
19
77
+ import org.apache.logging.log4j.core.config.plugins.Plugin;
20
78
+ import org.apache.logging.log4j.core.layout.PatternLayout;
21
- + import org.apache.logging.log4j.core.pattern.*;
79
+ + import org.apache.logging.log4j.core.pattern.ConverterKeys;
80
+ + import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
81
+ + import org.apache.logging.log4j.core.pattern.PatternConverter;
82
+ + import org.apache.logging.log4j.core.pattern.PatternFormatter;
83
+ + import org.apache.logging.log4j.core.pattern.PatternParser;
22
84
+ import org.apache.logging.log4j.util.PerformanceSensitive;
23
85
+ import org.apache.logging.log4j.util.PropertiesUtil;
24
86
+
@@ -30,25 +92,49 @@ index 0000000000000000000000000000000000000000..a4315961b7a465fb4872a4d67e7c26d4
30
92
+
31
93
+ /**
32
94
+ * Modified version of <a href="https://github.com/Minecrell/TerminalConsoleAppender/blob/master/src/main/java/net/minecrell/terminalconsole/MinecraftFormattingConverter.java">
33
- + * TerminalConsoleAppender's MinecraftFormattingConverter</a> to support hex color codes using the md_5 &x&r&r&g&g&b&b format.
95
+ + * TerminalConsoleAppender's MinecraftFormattingConverter</a> to support hex color codes using the Adventure [char]#rrggbb format.
34
96
+ */
35
97
+ @Plugin(name = "paperMinecraftFormatting", category = PatternConverter.CATEGORY)
36
- + @ConverterKeys({ "paperMinecraftFormatting" })
98
+ + @ConverterKeys({"paperMinecraftFormatting"})
37
99
+ @PerformanceSensitive("allocation")
38
100
+ public final class HexFormattingConverter extends LogEventPatternConverter {
39
101
+
40
102
+ private static final boolean KEEP_FORMATTING = PropertiesUtil.getProperties().getBooleanProperty(KEEP_FORMATTING_PROPERTY);
41
103
+
42
104
+ private static final String ANSI_RESET = "\u001B[m";
43
105
+
44
- + private static final char COLOR_CHAR = '§' ;
106
+ + public static final char COLOR_CHAR = 0x7f ;
45
107
+ private static final String LOOKUP = "0123456789abcdefklmnor";
46
108
+
47
109
+ private static final String RGB_ANSI = "\u001B[38;2;%d;%d;%dm";
48
110
+ private static final Pattern NAMED_PATTERN = Pattern.compile(COLOR_CHAR + "[0-9a-fk-orA-FK-OR]");
49
- + private static final Pattern RGB_PATTERN = Pattern.compile(COLOR_CHAR + "x(" + COLOR_CHAR + " [0-9a-fA-F]){6}");
111
+ + private static final Pattern RGB_PATTERN = Pattern.compile(COLOR_CHAR + "#( [0-9a-fA-F]){6}");
50
112
+
51
- + private static final String[] ansiCodes = new String[] {
113
+ + private static final String[] RGB_ANSI_CODES = new String[]{
114
+ + formatHexAnsi(NamedTextColor.BLACK), // Black §0
115
+ + formatHexAnsi(NamedTextColor.DARK_BLUE), // Dark Blue §1
116
+ + formatHexAnsi(NamedTextColor.DARK_GREEN), // Dark Green §2
117
+ + formatHexAnsi(NamedTextColor.DARK_AQUA), // Dark Aqua §3
118
+ + formatHexAnsi(NamedTextColor.DARK_RED), // Dark Red §4
119
+ + formatHexAnsi(NamedTextColor.DARK_PURPLE), // Dark Purple §5
120
+ + formatHexAnsi(NamedTextColor.GOLD), // Gold §6
121
+ + formatHexAnsi(NamedTextColor.GRAY), // Gray §7
122
+ + formatHexAnsi(NamedTextColor.DARK_GRAY), // Dark Gray §8
123
+ + formatHexAnsi(NamedTextColor.BLUE), // Blue §9
124
+ + formatHexAnsi(NamedTextColor.GREEN), // Green §a
125
+ + formatHexAnsi(NamedTextColor.AQUA), // Aqua §b
126
+ + formatHexAnsi(NamedTextColor.RED), // Red §c
127
+ + formatHexAnsi(NamedTextColor.LIGHT_PURPLE), // Light Purple §d
128
+ + formatHexAnsi(NamedTextColor.YELLOW), // Yellow §e
129
+ + formatHexAnsi(NamedTextColor.WHITE), // White §f
130
+ + "\u001B[5m", // Obfuscated §k
131
+ + "\u001B[21m", // Bold §l
132
+ + "\u001B[9m", // Strikethrough §m
133
+ + "\u001B[4m", // Underline §n
134
+ + "\u001B[3m", // Italic §o
135
+ + ANSI_RESET, // Reset §r
136
+ + };
137
+ + private static final String[] ANSI_ANSI_CODES = new String[]{
52
138
+ "\u001B[0;30m", // Black §0
53
139
+ "\u001B[0;34m", // Dark Blue §1
54
140
+ "\u001B[0;32m", // Dark Green §2
@@ -107,30 +193,26 @@ index 0000000000000000000000000000000000000000..a4315961b7a465fb4872a4d67e7c26d4
107
193
+ format(content, toAppendTo, start, useAnsi);
108
194
+ }
109
195
+
110
- + private static String convertRGBColors(String input) {
111
- + Matcher matcher = RGB_PATTERN.matcher(input);
112
- + StringBuffer buffer = new StringBuffer();
113
- + while (matcher.find()) {
114
- + String s = matcher.group().replace(String.valueOf(COLOR_CHAR), "").replace('x', '#');
115
- + int hex = Integer.decode(s);
116
- + int red = (hex >> 16) & 0xFF;
117
- + int green = (hex >> 8) & 0xFF;
118
- + int blue = hex & 0xFF;
119
- + String replacement = String.format(RGB_ANSI, red, green, blue);
120
- + matcher.appendReplacement(buffer, replacement);
121
- + }
122
- + matcher.appendTail(buffer);
123
- + return buffer.toString();
196
+ + private static String convertRGBColors(final String input) {
197
+ + return RGB_PATTERN.matcher(input).replaceAll(result -> {
198
+ + final int hex = Integer.decode(result.group().substring(1));
199
+ + return formatHexAnsi(hex);
200
+ + });
124
201
+ }
125
202
+
126
- + private static String stripRGBColors(String input) {
127
- + Matcher matcher = RGB_PATTERN.matcher(input);
128
- + StringBuffer buffer = new StringBuffer();
129
- + while (matcher.find()) {
130
- + matcher.appendReplacement(buffer, "");
131
- + }
132
- + matcher.appendTail(buffer);
133
- + return buffer.toString();
203
+ + private static String formatHexAnsi(final TextColor color) {
204
+ + return formatHexAnsi(color.value());
205
+ + }
206
+ +
207
+ + private static String formatHexAnsi(final int color) {
208
+ + final int red = color >> 16 & 0xFF;
209
+ + final int green = color >> 8 & 0xFF;
210
+ + final int blue = color & 0xFF;
211
+ + return String.format(RGB_ANSI, red, green, blue);
212
+ + }
213
+ +
214
+ + private static String stripRGBColors(final String input) {
215
+ + return RGB_PATTERN.matcher(input).replaceAll("");
134
216
+ }
135
217
+
136
218
+ static void format(String content, StringBuilder result, int start, boolean ansi) {
@@ -146,7 +228,8 @@ index 0000000000000000000000000000000000000000..a4315961b7a465fb4872a4d67e7c26d4
146
228
+ }
147
229
+
148
230
+ Matcher matcher = NAMED_PATTERN.matcher(content);
149
- + StringBuffer buffer = new StringBuffer();
231
+ + StringBuilder buffer = new StringBuilder();
232
+ + final String[] ansiCodes = PaperConfig.useRgbForNamedTextColors ? RGB_ANSI_CODES : ANSI_ANSI_CODES;
150
233
+ while (matcher.find()) {
151
234
+ int format = LOOKUP.indexOf(Character.toLowerCase(matcher.group().charAt(1)));
152
235
+ if (format != -1) {
@@ -156,7 +239,7 @@ index 0000000000000000000000000000000000000000..a4315961b7a465fb4872a4d67e7c26d4
156
239
+ matcher.appendTail(buffer);
157
240
+
158
241
+ result.setLength(start);
159
- + result.append(buffer.toString() );
242
+ + result.append(buffer);
160
243
+ if (ansi) {
161
244
+ result.append(ANSI_RESET);
162
245
+ }
@@ -169,7 +252,6 @@ index 0000000000000000000000000000000000000000..a4315961b7a465fb4872a4d67e7c26d4
169
252
+ * @param config The current configuration
170
253
+ * @param options The pattern options
171
254
+ * @return The new instance
172
- + *
173
255
+ * @see HexFormattingConverter
174
256
+ */
175
257
+ public static HexFormattingConverter newInstance(Configuration config, String[] options) {
0 commit comments