55import me .shedaniel .autoconfig .serializer .Toml4jConfigSerializer ;
66import net .fabricmc .api .ClientModInitializer ;
77import net .fabricmc .fabric .api .client .command .v2 .ClientCommandRegistrationCallback ;
8+ import net .minecraft .text .HoverEvent ;
89import net .minecraft .text .MutableText ;
910import net .minecraft .text .Style ;
1011import net .minecraft .text .Text ;
@@ -30,12 +31,56 @@ public class SpooncraftNameLinkClient implements ClientModInitializer {
3031 // List of mappings for replacement and optional color changes
3132 private static List <DisplayMapping > mappings = new ArrayList <>();
3233
34+ /**
35+ * Applies the mapping to a given message. It optionally replaces the Minecraft name with
36+ * the Discord nickname and applies the colour styling.
37+ *
38+ * @param message The original in-game message or name
39+ * @param mapping The {@code DisplayMapping} object containing the name and color mapping
40+ * details
41+ * @param replaceName Whether to replace the name with the name defined in the mapping
42+ * @param replaceColour Whether to replace the colour with the colour defined in the mapping
43+ * @return A new MutableText object with the mapping applied (replacements and color changes)
44+ */
45+ static MutableText applyMapping (Text message , DisplayMapping mapping ,
46+ boolean replaceName , boolean replaceColour ) {
47+ if (message == null || message .getString ().isEmpty () || mapping == null ) {
48+ return Text .empty ();
49+ }
50+
51+ MutableText outputMessage = Text .empty ();
52+ message .visit ((style , text ) -> {
53+ String replacedText = text ;
54+ Style replacedStyle = style ;
55+
56+ // Apply the mapping
57+ if (replacedText .contains (mapping .mc_name )) {
58+ // Replace the string
59+ if (mapping .discord_nick != null && replaceName ) {
60+ replacedText = replacedText .replace (mapping .mc_name , mapping .discord_nick );
61+ }
62+ // Apply color if specified
63+ if (mapping .colour != null && replaceColour ) {
64+ replacedStyle = replacedStyle .withColor (Integer .parseInt (mapping .colour , 16 ));
65+ }
66+ }
67+
68+ // Create new MutableText with the display string and style
69+ MutableText newText = (MutableText ) Text .of (replacedText );
70+ newText .setStyle (replacedStyle );
71+ outputMessage .append (newText );
72+
73+ return Optional .empty (); // Continue visiting
74+ }, Style .EMPTY );
75+
76+ return outputMessage ;
77+ }
3378
3479 /**
3580 * Retrieves and applies the correct name mapping (if any) for a given Minecraft username or
3681 * UUID.
37- * This method checks the mappings list to see if the provided displayName or uuid has a
38- * corresponding mapping, and if found, applies it by optionally altering the name and color.
82+ * Checks the mappings list to see if the provided displayName or uuid has a corresponding
83+ * mapping, and if found, applies it by optionally altering the name and color.
3984 *
4085 * @param displayName The original in-game name to be displayed
4186 * @param uuid The UUID of the Minecraft player
@@ -46,28 +91,18 @@ public class SpooncraftNameLinkClient implements ClientModInitializer {
4691 */
4792 public static Text getStyledName (Text displayName , UUID uuid , String name , boolean replaceName ,
4893 boolean replaceColour ) {
49- DisplayMapping correctMapping = null ;
50-
5194 // Iterate over the mappings to find the correct match based on UUID or Minecraft name
5295 for (DisplayMapping mapping : mappings ) {
53- // If the UUID matches or the name matches, select the mapping and break
96+ // If the UUID matches or the name matches, apply the mapping and return it
5497 if (Objects .equals (mapping .mc_uuid , uuid ) || Objects .equals (mapping .mc_name , name )) {
55- correctMapping = mapping ;
56- break ;
98+ return applyMapping (displayName , mapping , replaceName , replaceColour );
5799 }
58100 }
59-
60- // If a matching mapping is found, apply it; otherwise, return the original displayName
61- if (correctMapping != null ) { // If a mapping could be found.
62- return applyMapping (displayName , correctMapping , replaceName , replaceColour );
63- }
64- // If the mapping couldn't be found, simply return what we got.
65101 return displayName ;
66102 }
67103
68104 /**
69- * Retrieves and applies the correct name mapping (if any) for a given Minecraft username or
70- * UUID.
105+ * Retrieves and applies the correct name mapping (if any) for a given Minecraft username.
71106 *
72107 * @param displayName The original in-game name to be displayed
73108 * @param name The in-game name as a Text object
@@ -78,78 +113,43 @@ public static Text getStyledName(Text displayName, UUID uuid, String name, boole
78113 */
79114 public static Text getStyledName (Text displayName , String name , boolean replaceName ,
80115 boolean replaceColour ) {
81- return getStyledName (displayName , new UUID ( 0 , 0 ), name , replaceName , replaceColour );
116+ return getStyledName (displayName , UUID . fromString ( "00000000-0000-0000-0000-000000000000" ), name , replaceName , replaceColour );
82117 }
83118
84119 /**
85- * Applies the mapping to a given message. It optionally replaces the Minecraft name with
86- * the Discord nickname and applies the colour styling .
120+ * Styles the chat message by replacing the name and colour if specified.
121+ * Only styles the name if the text has a {@code HoverEvent} component .
87122 *
88123 * @param message The original in-game message or name
89- * @param mapping The {@code DisplayMapping} object containing the name and color mapping
90- * details
91124 * @param replaceName Whether to replace the name with the name defined in the mapping
92125 * @param replaceColour Whether to replace the colour with the colour defined in the mapping
93126 * @return A new MutableText object with the mapping applied (replacements and color changes)
94127 */
95- public static MutableText applyMapping (Text message , DisplayMapping mapping ,
96- boolean replaceName , boolean replaceColour ) {
97- MutableText outputMessage = Text .empty ();
98-
99- if (message == null || message .getString ().isEmpty () || mapping == null ) {
100- return outputMessage ;
128+ public static Text getStyledChat (Text message , boolean replaceName , boolean replaceColour ) {
129+ if (message == null || message .getString ().isEmpty ()) {
130+ return Text .empty ();
101131 }
102132
133+ MutableText outputMessage = Text .empty ();
103134 message .visit ((style , text ) -> {
104- Style replacedStyle = style ;
105- String replacedText = text ;
106-
107- // Apply the mapping
108- if (replacedText .contains (mapping .mc_name )) {
109- // Replace the string
110- if (mapping .discord_nick != null && replaceName ) {
111- replacedText = replacedText .replace (mapping .mc_name , mapping .discord_nick );
112- }
113- // Apply color if specified
114- if (mapping .colour != null && replaceColour ) {
115- replacedStyle = replacedStyle .withColor (Integer .parseInt (mapping .colour , 16 ));
135+ MutableText newText = Text .literal (text ).setStyle (style );
136+
137+ HoverEvent event = style .getHoverEvent ();
138+ if (event != null ) {
139+ HoverEvent .EntityContent value = event .getValue (HoverEvent .Action .SHOW_ENTITY );
140+ if (value != null && value .name .isPresent ()) {
141+ newText = (MutableText ) getStyledName (newText , value .uuid , String .valueOf (value .name ), replaceName , replaceColour )
142+ .setStyle (newText .getStyle ().withHoverEvent (event ));
116143 }
117144 }
118145
119- // Create new MutableText with the display string and style
120- MutableText newText = (MutableText ) Text .of (replacedText );
121- newText .setStyle (replacedStyle );
122146 outputMessage .append (newText );
123-
124- return Optional .empty (); // Continue visiting
147+ return Optional .empty ();
125148 }, Style .EMPTY );
126149
127150 return outputMessage ;
128151 }
129152
130- /**
131- * Naively applies styling and replacements to a given message.
132- * This method applies every name mapping in the mappings list to the message, regardless of
133- * context.
134- *
135- * @param message The original message to which mappings will be applied
136- * @param replaceName Whether to replace the name with the name defined in the mapping
137- * @param replaceColour Whether to replace the colour with the colour defined in the mapping
138- * @return A new Text object with all applicable mappings and styles applied
139- */
140- public static Text naivelyStyleText (Text message , boolean replaceName , boolean replaceColour ) {
141- MutableText outputMessage = (MutableText ) message ;
142-
143- // Apply each mapping sequentially to the message
144- for (DisplayMapping mapping : mappings ) {
145- outputMessage = applyMapping (outputMessage , mapping , replaceName , replaceColour );
146- }
147-
148- // Return the final styled message
149- return outputMessage ;
150- }
151-
152-
153153 /**
154154 * Retrieves the mappings from the specified source URL or the default URL if none is provided.
155155 * If the mod is disabled in the configuration, it disables the mod and logs a warning.
@@ -159,26 +159,23 @@ public static Text naivelyStyleText(Text message, boolean replaceName, boolean r
159159 * @return The number of mappings retrieved.
160160 */
161161 public static int getMappings (String source ) {
162- String s = source ;
163- if (s == null || s .isEmpty ())
164- s = "https://gwaff.uqcloud.net/api/spooncraft" ;
165-
162+ String s = (source == null || source .isEmpty ()) ? "https://gwaff.uqcloud.net/api/spooncraft" : source ;
166163 mappings = NameLinkAPI .getMappings (s );
167-
168164 return mappings .size ();
169165 }
170166
167+ /**
168+ * Retrieves a Text object detailing the status of the mod.
169+ *
170+ * @return A Text object containing the status of the mod
171+ */
171172 public static Text getStatusString () {
172173 String status = NameLinkAPI .getStatus ();
173174 return switch (status ) {
174- case "Success" ->
175- Text .translatable ("text.scnamelink.status.success" ).formatted (Formatting .WHITE );
176- case "Working" ->
177- Text .translatable ("text.scnamelink.status.working" ).formatted (Formatting .YELLOW );
178- case "Fallback" ->
179- Text .translatable ("text.scnamelink.status.fallback" ).formatted (Formatting .RED );
180- case "Failure" ->
181- Text .translatable ("text.scnamelink.status.failure" ).formatted (Formatting .RED , Formatting .BOLD );
175+ case "Success" -> Text .translatable ("text.scnamelink.status.success" ).formatted (Formatting .WHITE );
176+ case "Working" -> Text .translatable ("text.scnamelink.status.working" ).formatted (Formatting .YELLOW );
177+ case "Fallback" -> Text .translatable ("text.scnamelink.status.fallback" ).formatted (Formatting .RED );
178+ case "Failure" -> Text .translatable ("text.scnamelink.status.failure" ).formatted (Formatting .RED , Formatting .BOLD );
182179 default -> Text .of (NameLinkAPI .getStatus ());
183180 };
184181 }
@@ -189,9 +186,11 @@ public void onInitializeClient() {
189186 config = AutoConfig .getConfigHolder (SCNameLinkConfig .class ).getConfig ();
190187
191188 final int count = getMappings (config .apiLink );
192- if (count > 0 )
189+ if (count > 0 ) {
193190 LOGGER .info ("{} initialised with {} mappings" , MOD_ID , mappings .size ());
194- else LOGGER .warn ("{} initialised with NO mappings found" , MOD_ID );
191+ } else {
192+ LOGGER .warn ("{} initialised with NO mappings found" , MOD_ID );
193+ }
195194
196195 if (!config .enableMod ) {
197196 NameLinkAPI .disableMod ();
0 commit comments