diff --git a/proxy/build.gradle.kts b/proxy/build.gradle.kts
index 14eb4b19d..643689d40 100644
--- a/proxy/build.gradle.kts
+++ b/proxy/build.gradle.kts
@@ -96,6 +96,7 @@ tasks {
dependencies {
implementation(project(":velocity-api"))
implementation(project(":velocity-native"))
+ implementation(project(":velocity-proxy-log4j2-plugin"))
implementation(libs.bundles.log4j)
implementation(libs.kyori.ansi)
diff --git a/proxy/log4j2-plugin/build.gradle.kts b/proxy/log4j2-plugin/build.gradle.kts
new file mode 100644
index 000000000..0a193944a
--- /dev/null
+++ b/proxy/log4j2-plugin/build.gradle.kts
@@ -0,0 +1,4 @@
+dependencies {
+ implementation(libs.bundles.log4j)
+ annotationProcessor(libs.log4j.core)
+}
\ No newline at end of file
diff --git a/proxy/log4j2-plugin/src/main/java/com/velocitypowered/proxy/util/StripAnsiConverter.java b/proxy/log4j2-plugin/src/main/java/com/velocitypowered/proxy/util/StripAnsiConverter.java
new file mode 100644
index 000000000..f3722ffaa
--- /dev/null
+++ b/proxy/log4j2-plugin/src/main/java/com/velocitypowered/proxy/util/StripAnsiConverter.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2023 Velocity Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.velocitypowered.proxy.util;
+
+import java.util.List;
+import java.util.regex.Pattern;
+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;
+
+/**
+ * Strip Format Converter.
+ * Based on Paper's patch
+ */
+@Plugin(name = "stripAnsi", category = PatternConverter.CATEGORY)
+@ConverterKeys("stripAnsi")
+public class StripAnsiConverter extends LogEventPatternConverter {
+ private static final Pattern ANSI_PATTERN = Pattern.compile("\u001B\\[[;\\d]*m");
+ private final List formatters;
+
+ /**
+ * Constructs an instance of StripAnsiConverter.
+ */
+ protected StripAnsiConverter(List formatters) {
+ super("stripAnsi", null);
+ this.formatters = formatters;
+ }
+
+ @Override
+ public void format(final LogEvent event, final StringBuilder toAppendTo) {
+ int start = toAppendTo.length();
+ for (final PatternFormatter formatter : formatters) {
+ formatter.format(event, toAppendTo);
+ }
+ String content = toAppendTo.substring(start);
+ content = ANSI_PATTERN.matcher(content).replaceAll("");
+
+ toAppendTo.setLength(start);
+ toAppendTo.append(content);
+ }
+
+ /**
+ * Creates a new Instance of this Converter.
+ *
+ * @param config the configuration
+ * @param options the options
+ * @return a new instance
+ */
+ public static StripAnsiConverter newInstance(Configuration config, String[] options) {
+ if (options.length != 1) {
+ LOGGER.error("Incorrect number of options on stripFormat. Expected 1 received "
+ + options.length);
+ return null;
+ }
+ PatternParser parser = PatternLayout.createPatternParser(config);
+ List formatters = parser.parse(options[0]);
+ return new StripAnsiConverter(formatters);
+ }
+}
\ No newline at end of file
diff --git a/proxy/src/main/java/com/velocitypowered/proxy/util/TranslatableMapper.java b/proxy/src/main/java/com/velocitypowered/proxy/util/TranslatableMapper.java
index c2ca2366f..a7b9ad4b6 100644
--- a/proxy/src/main/java/com/velocitypowered/proxy/util/TranslatableMapper.java
+++ b/proxy/src/main/java/com/velocitypowered/proxy/util/TranslatableMapper.java
@@ -28,7 +28,6 @@ import net.kyori.adventure.translation.TranslationRegistry;
import net.kyori.adventure.translation.Translator;
import org.jetbrains.annotations.Nullable;
-
/**
* Velocity Translation Mapper.
*/
diff --git a/proxy/src/main/resources/log4j2.xml b/proxy/src/main/resources/log4j2.xml
index b93b9a7a1..ebf86e2fc 100644
--- a/proxy/src/main/resources/log4j2.xml
+++ b/proxy/src/main/resources/log4j2.xml
@@ -22,10 +22,10 @@
+ defaultPattern="%highlightError{[%d{HH:mm:ss} %level] [%logger]: %msg%n%xEx}">
+ pattern="%highlightError{[%d{HH:mm:ss} %level]: %msg%n%xEx}"/>
@@ -33,7 +33,7 @@
filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz"
immediateFlush="false">
+ pattern="[%d{HH:mm:ss}] [%t/%level] [%logger]: %stripAnsi{%msg}%n"/>
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 7b375a6f9..aa2367be0 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -33,6 +33,12 @@ sequenceOf(
project(project).projectDir = file(it)
}
+// Include Configurate 3
val deprecatedConfigurateModule = ":deprecated-configurate3"
include(deprecatedConfigurateModule)
project(deprecatedConfigurateModule).projectDir = file("proxy/deprecated/configurate3")
+
+// Log4J2 plugin
+val log4j2ProxyPlugin = ":velocity-proxy-log4j2-plugin"
+include(log4j2ProxyPlugin)
+project(log4j2ProxyPlugin).projectDir = file("proxy/log4j2-plugin")