From 9e994347a3968b74d0909013f3190d236afafb2e Mon Sep 17 00:00:00 2001 From: Patbox <39821509+Patbox@users.noreply.github.com> Date: Wed, 2 Nov 2022 16:05:47 +0100 Subject: [PATCH 1/2] Tweak order of link parsing --- gradle.properties | 2 +- .../eu/pb4/styledchat/StyledChatUtils.java | 70 +++++------------- .../eu/pb4/styledchat/parser/LinkParser.java | 73 +++++++++++++++++++ 3 files changed, 94 insertions(+), 51 deletions(-) create mode 100644 src/main/java/eu/pb4/styledchat/parser/LinkParser.java diff --git a/gradle.properties b/gradle.properties index 6792218..3bbcb3d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ loader_version=0.14.8 fabric_version=0.59.0+1.19.2 # Mod Properties - mod_version = 2.0.1+1.19.2 + mod_version = 2.0.2+1.19.2 maven_group = eu.pb4 archives_base_name = styled-chat diff --git a/src/main/java/eu/pb4/styledchat/StyledChatUtils.java b/src/main/java/eu/pb4/styledchat/StyledChatUtils.java index 9a7f829..6352947 100644 --- a/src/main/java/eu/pb4/styledchat/StyledChatUtils.java +++ b/src/main/java/eu/pb4/styledchat/StyledChatUtils.java @@ -23,6 +23,7 @@ import eu.pb4.styledchat.config.data.VersionedChatStyleData; import eu.pb4.styledchat.ducks.ExtPlayNetworkHandler; import eu.pb4.styledchat.ducks.ExtSignedMessage; +import eu.pb4.styledchat.parser.LinkParser; import eu.pb4.styledchat.parser.SpoilerNode; import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.command.EntitySelector; @@ -75,11 +76,20 @@ public static TextNode parseText(String input) { } public static NodeParser createParser(ServerCommandSource source) { + return createParser(PlaceholderContext.of(source)); + } + + public static NodeParser createParser(PlaceholderContext context) { var config = ConfigManager.getConfig(); var list = new ArrayList(); - var base = createTextParserV1(source); + var base = createTextParserV1(context.source()); + list.add(base); + if (config.configData.formatting.parseLinksInChat) { + list.add(new LinkParser(ConfigManager.getConfig().getLinkStyle(context))); + } + if (config.configData.formatting.markdown) { var form = new ArrayList(); @@ -127,7 +137,7 @@ public static NodeParser createParser(ServerCommandSource source) { } - public static TextParserV1 createTextParserV1(ServerCommandSource source) { + public static TextParserV1 createTextParserV1(ServerCommandSource source) { var parser = new TextParserV1(); Config config = ConfigManager.getConfig(); @@ -157,7 +167,7 @@ public static Map getEmotes(PlaceholderContext context) { } public static Text formatFor(PlaceholderContext context, String input) { - var parser = createParser(context.hasPlayer() ? context.player().getCommandSource() : context.server().getCommandSource()); + var parser = createParser(context); var config = ConfigManager.getConfig(); if (StyledChatMod.USE_FABRIC_API) { input = StyledChatEvents.PRE_MESSAGE_CONTENT.invoker().onPreMessage(input, context); @@ -165,7 +175,7 @@ public static Text formatFor(PlaceholderContext context, String input) { var emotes = getEmotes(context); - var value = additionalParsing(new ParentNode(parser.parseNodes(new LiteralNode(input))), context); + var value = TextNode.asSingle(parser.parseNodes(new LiteralNode(input))); if (StyledChatMod.USE_FABRIC_API) { value = StyledChatEvents.MESSAGE_CONTENT.invoker().onMessage(value, context); @@ -287,59 +297,19 @@ public static MessageDecorator getCommandDecorator(String context, ServerCom }); }; } + + @Deprecated public static TextNode additionalParsing(TextNode node, PlaceholderContext context) { - var config = ConfigManager.getConfig(); - if (config.configData.formatting.parseLinksInChat) { + + if (ConfigManager.getConfig().configData.formatting.parseLinksInChat) { node = parseLinks(node, context); } return node; } + @Deprecated public static TextNode parseLinks(TextNode node, PlaceholderContext context) { - if (node instanceof LiteralNode literalNode) { - var style = ConfigManager.getConfig().getLinkStyle(context); - var input = literalNode.value(); - var list = new ArrayList(); - - Matcher matcher = URL_REGEX.matcher(input); - int currentPos = 0; - int currentEnd = input.length(); - - while (matcher.find()) { - if (currentEnd <= matcher.start()) { - break; - } - - String betweenText = input.substring(currentPos, matcher.start()); - - if (betweenText.length() != 0) { - list.add(new LiteralNode(betweenText)); - } - - list.add(new ClickActionNode(Placeholders.parseNodes(style, Placeholders.PREDEFINED_PLACEHOLDER_PATTERN, Map.of("link", Text.literal(matcher.group()))).getChildren(), ClickEvent.Action.OPEN_URL, new LiteralNode(matcher.group()))); - - currentPos = matcher.end(); - } - - if (currentPos < currentEnd) { - String restOfText = input.substring(currentPos, currentEnd); - if (restOfText.length() != 0) { - list.add(new LiteralNode(restOfText)); - } - } - - return list.size() == 1 ? list.get(0) : new ParentNode(list.toArray(new TextNode[0])); - } else if (node instanceof ParentTextNode parentTextNode) { - var list = new ArrayList(); - - for (var child : parentTextNode.getChildren()) { - list.add(parseLinks(child, context)); - } - - return parentTextNode.copyWith(list.toArray(new TextNode[0])); - } - - return node; + return TextNode.asSingle(LinkParser.parse(node, context)); } public static boolean isHandledByMod(RegistryKey typeKey) { diff --git a/src/main/java/eu/pb4/styledchat/parser/LinkParser.java b/src/main/java/eu/pb4/styledchat/parser/LinkParser.java new file mode 100644 index 0000000..6907e3c --- /dev/null +++ b/src/main/java/eu/pb4/styledchat/parser/LinkParser.java @@ -0,0 +1,73 @@ +package eu.pb4.styledchat.parser; + +import eu.pb4.placeholders.api.PlaceholderContext; +import eu.pb4.placeholders.api.Placeholders; +import eu.pb4.placeholders.api.node.LiteralNode; +import eu.pb4.placeholders.api.node.TextNode; +import eu.pb4.placeholders.api.node.parent.ClickActionNode; +import eu.pb4.placeholders.api.node.parent.ParentTextNode; +import eu.pb4.placeholders.api.parsers.NodeParser; +import eu.pb4.styledchat.config.ConfigManager; +import net.minecraft.text.ClickEvent; +import net.minecraft.text.Text; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; + +import static eu.pb4.styledchat.StyledChatUtils.URL_REGEX; + +public record LinkParser(TextNode style) implements NodeParser { + + @Override + public TextNode[] parseNodes(TextNode node) { + if (node instanceof LiteralNode literalNode) { + var input = literalNode.value(); + var list = new ArrayList(); + + Matcher matcher = URL_REGEX.matcher(input); + int currentPos = 0; + int currentEnd = input.length(); + + while (matcher.find()) { + if (currentEnd <= matcher.start()) { + break; + } + + String betweenText = input.substring(currentPos, matcher.start()); + + if (betweenText.length() != 0) { + list.add(new LiteralNode(betweenText)); + } + + list.add(new ClickActionNode(Placeholders.parseNodes(style, Placeholders.PREDEFINED_PLACEHOLDER_PATTERN, Map.of("link", Text.literal(matcher.group()))).getChildren(), ClickEvent.Action.OPEN_URL, new LiteralNode(matcher.group()))); + + currentPos = matcher.end(); + } + + if (currentPos < currentEnd) { + String restOfText = input.substring(currentPos, currentEnd); + if (restOfText.length() != 0) { + list.add(new LiteralNode(restOfText)); + } + } + + return list.toArray(new TextNode[0]); + } else if (node instanceof ParentTextNode parentTextNode) { + var list = new ArrayList(); + + for (var child : parentTextNode.getChildren()) { + list.addAll(List.of(this.parseNodes(child))); + } + + return new TextNode[] { parentTextNode.copyWith(list.toArray(new TextNode[0])) }; + } + + return new TextNode[] { node }; + } + + public static TextNode[] parse(TextNode node, PlaceholderContext context) { + return new LinkParser(ConfigManager.getConfig().getLinkStyle(context)).parseNodes(node); + } +} From b8f3a8be081cc4014c95dec76f6ce0672e9e79f2 Mon Sep 17 00:00:00 2001 From: Patbox <39821509+Patbox@users.noreply.github.com> Date: Sun, 9 Apr 2023 19:50:12 +0200 Subject: [PATCH 2/2] Minimise recalculation of player display name within single tick to improve performance --- gradle.properties | 2 +- .../styledchat/mixin/PlayerEntityMixin.java | 27 ++++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/gradle.properties b/gradle.properties index 3bbcb3d..bb773f0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ loader_version=0.14.8 fabric_version=0.59.0+1.19.2 # Mod Properties - mod_version = 2.0.2+1.19.2 + mod_version = 2.0.3+1.19.2 maven_group = eu.pb4 archives_base_name = styled-chat diff --git a/src/main/java/eu/pb4/styledchat/mixin/PlayerEntityMixin.java b/src/main/java/eu/pb4/styledchat/mixin/PlayerEntityMixin.java index f23fa89..937af7b 100644 --- a/src/main/java/eu/pb4/styledchat/mixin/PlayerEntityMixin.java +++ b/src/main/java/eu/pb4/styledchat/mixin/PlayerEntityMixin.java @@ -1,6 +1,7 @@ package eu.pb4.styledchat.mixin; import eu.pb4.styledchat.StyledChatStyles; +import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; @@ -11,16 +12,30 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(PlayerEntity.class) -public class PlayerEntityMixin { +public abstract class PlayerEntityMixin { @Unique - private boolean ignoreNextCalls = false; + private Text styledChat$cachedName = Text.empty(); + + @Unique + private int styledChat$cachedAge = -1234568; + + @Unique + private boolean styledChat$ignoreNextCalls = false; @Inject(method = "getDisplayName", at = @At("RETURN"), cancellable = true) private void styledChat_replaceDisplayName(CallbackInfoReturnable cir) { - if (!this.ignoreNextCalls && ((Object) this) instanceof ServerPlayerEntity player) { - this.ignoreNextCalls = true; - cir.setReturnValue(StyledChatStyles.getDisplayName(player, cir.getReturnValue())); - this.ignoreNextCalls = false; + if (!this.styledChat$ignoreNextCalls && ((Object) this).getClass() == ServerPlayerEntity.class) { + if (this.styledChat$cachedAge == ((Entity) (Object) this).age) { + cir.setReturnValue(this.styledChat$cachedName); + return; + } + + this.styledChat$ignoreNextCalls = true; + var name = StyledChatStyles.getDisplayName((ServerPlayerEntity) (Object) this, cir.getReturnValue()); + this.styledChat$ignoreNextCalls = false; + this.styledChat$cachedName = name; + this.styledChat$cachedAge = ((Entity) (Object) this).age; + cir.setReturnValue(name); } } }