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); + } +}