Skip to content

Instantly share code, notes, and snippets.

@BomBardyGamer
Created August 27, 2023 13:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BomBardyGamer/a751baaf013b314a3924d4097ec95792 to your computer and use it in GitHub Desktop.
Save BomBardyGamer/a751baaf013b314a3924d4097ec95792 to your computer and use it in GitHub Desktop.
MiniMessage vs text replacement parser
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