Created
August 27, 2023 13:30
-
-
Save BomBardyGamer/a751baaf013b314a3924d4097ec95792 to your computer and use it in GitHub Desktop.
MiniMessage vs text replacement parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public final class Main { | |
private static final String PURE_MINI_MESSAGE = "<click:run_command:'/party join <username>'><color:#3db83d>You have been invited to join <green><username>'s</green> party. <b><gradient:light_purple:gold>Click to accept</gradient></b></click>"; | |
private static final String MINI_AND_PARSE = "<click:run_command:'/party join {0}'><color:#3db83d>You have been invited to join <green>{0}'s</green> party. <b><gradient:light_purple:gold>Click to accept</gradient></b></click>"; | |
private static final TagResolver PLACEHOLDER = Placeholder.parsed("username", "Bardy"); | |
private static final List<Component> ARGS = List.of(Component.text("Bardy")); | |
public static void main(String[] ignored) { | |
// Try to pre-initialise everything so that doesn't affect the results | |
MiniMessage miniMessage = MiniMessage.miniMessage(); | |
miniMessage.deserialize(PURE_MINI_MESSAGE, PLACEHOLDER); | |
Translator.translate(miniMessage.deserialize(MINI_AND_PARSE), ARGS); | |
Component simpleMini = miniMessage.deserialize(MINI_AND_PARSE); | |
Component result = Component.empty(); | |
for (int i = 0; i < 5; i++) { | |
result = doIterations(miniMessage, simpleMini); | |
System.out.println(); | |
} | |
} | |
private static @NotNull Component doIterations(@NotNull MiniMessage miniMessage, @NotNull Component simpleMini) { | |
BigInteger pureMiniMessageTime = BigInteger.ZERO; | |
BigInteger miniAndParseTime = BigInteger.ZERO; | |
BigInteger preParsedTime = BigInteger.ZERO; | |
for (int i = 0; i < 1010; i++) { | |
long pureMini = time(() -> translatePureMiniMessage(miniMessage)); | |
long miniAndParse = time(() -> translateMiniAndParse(miniMessage)); | |
long preParsed = time(() -> translatePreParsed(simpleMini)); | |
if (i >= 10) continue; | |
pureMiniMessageTime = pureMiniMessageTime.add(BigInteger.valueOf(pureMini)); | |
miniAndParseTime = miniAndParseTime.add(BigInteger.valueOf(miniAndParse)); | |
preParsedTime = preParsedTime.add(BigInteger.valueOf(preParsed)); | |
} | |
System.out.println("Pure MiniMessage time for 10000 iterations: " + formatTime(pureMiniMessageTime) + "ns"); | |
System.out.println("Mini and parse time for 10000 iterations: " + formatTime(miniAndParseTime) + "ns"); | |
System.out.println("Pre-parsed time for 10000 iterations: " + formatTime(preParsedTime) + "ns"); | |
} | |
private static long time(@NotNull Runnable code) { | |
long start = System.nanoTime(); | |
code.run(); | |
long end = System.nanoTime(); | |
return end - start; | |
} | |
private static @NotNull String formatTime(@NotNull BigInteger time) { | |
return String.format("%,d", time); | |
} | |
private static void translatePureMiniMessage(@NotNull MiniMessage miniMessage) { | |
miniMessage.deserialize(PURE_MINI_MESSAGE, PLACEHOLDER); | |
} | |
private static void translateMiniAndParse(@NotNull MiniMessage miniMessage) { | |
Translator.translate(miniMessage.deserialize(MINI_AND_PARSE), ARGS); | |
} | |
private static void translatePreParsed(@NotNull Component preParsed) { | |
Translator.translate(preParsed, ARGS); | |
} | |
private static final class Translator { | |
private static final Pattern ARG_PATTERN = Pattern.compile("\\{[0-9]+}"); | |
static @NotNull Component translate(@NotNull Component input, @NotNull List<Component> args) { | |
Component output = input; | |
if (!args.isEmpty()) { | |
output = output.replaceText(TextReplacementConfig.builder() | |
.match(ARG_PATTERN) | |
.replacement((result, builder) -> doReplacement(result, args)) | |
.build()); | |
output = translateClickEvent(output, args); | |
} | |
return translateChildren(output, args); | |
} | |
private static @NotNull Component translateChildren(@NotNull Component input, @NotNull List<Component> args) { | |
List<Component> children = new ArrayList<>(); | |
for (Component component : input.children()) { | |
Component output = translate(component, args); | |
children.add(translateChildren(output, args)); | |
} | |
return input.children(children); | |
} | |
private static @NotNull Component translateClickEvent(@NotNull Component input, @NotNull List<Component> args) { | |
ClickEvent event = input.clickEvent(); | |
if (event == null) return input; | |
String value = event.value(); | |
Matcher matcher = ARG_PATTERN.matcher(value); | |
String result = matcher.replaceAll(match -> doTextReplacement(match, args)); | |
return input.clickEvent(ClickEvent.clickEvent(event.action(), result)); | |
} | |
private static @NotNull Component doReplacement(@NotNull MatchResult match, @NotNull List<Component> args) { | |
String group = match.group(); | |
int index = Integer.parseInt(group.substring(1, group.length() - 1)); | |
return index < args.size() ? args.get(index) : Component.text("$$" + index); | |
} | |
private static @NotNull String doTextReplacement(@NotNull MatchResult match, @NotNull List<Component> args) { | |
return PlainTextComponentSerializer.plainText().serialize(doReplacement(match, args)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment