15
15
import java .lang .invoke .MethodHandles ;
16
16
import java .lang .reflect .Constructor ;
17
17
import java .lang .reflect .Field ;
18
+ import java .lang .reflect .InvocationTargetException ;
18
19
import java .lang .reflect .Method ;
19
- import java .util .ArrayList ;
20
- import java .util .List ;
21
- import java .util .Objects ;
22
- import java .util .Vector ;
20
+ import java .util .*;
23
21
24
22
/**
25
23
* This is a complete JSON message builder class. To create a new JSONMessage do
26
24
* {@link #create(String)}
27
- *
25
+ *
28
26
* @author Rayzr
29
27
*/
30
28
@ SuppressWarnings ({"WeakerAccess" , "unused" })
@@ -161,6 +159,11 @@ public String toLegacy() {
161
159
* @param players The players you want to send this to
162
160
*/
163
161
public void send (Player ... players ) {
162
+ if (ReflectionHelper .MAJOR_VER >= 16 ) {
163
+ ReflectionHelper .sendTextPacket (toString (), players );
164
+ return ;
165
+ }
166
+
164
167
ReflectionHelper .sendPacket (ReflectionHelper .createTextPacket (toString ()), players );
165
168
}
166
169
@@ -202,10 +205,55 @@ public void actionbar(Player... players) {
202
205
* @return This {@link JSONMessage} instance
203
206
*/
204
207
public JSONMessage color (ChatColor color ) {
208
+ if (!color .isColor ())
209
+ throw new IllegalArgumentException (color .name () + " is not a color." );
210
+ return color (color .name ().toLowerCase (), ChatColor .WHITE );
211
+ }
212
+
213
+ /**
214
+ * Sets the color of the current message part.
215
+ * <br>If the provided color is a hex color ({@code #rrggbb}) but the major version of MC is older than 1.16 will this
216
+ * default to the color WHITE.
217
+ *
218
+ * @param color The color to set
219
+ * @return This {@link JSONMessage} instance
220
+ */
221
+ public JSONMessage color (String color ) {
222
+ return color (color , ChatColor .WHITE );
223
+ }
224
+
225
+ /**
226
+ * Sets the color of the current message part.
227
+ * <br>If the provided color is a hex color ({@code #rrggbb}) but the major version of MC is older than 1.16 will the provided
228
+ * default ChatColor be used instead.
229
+ *
230
+ * @param color The color to set
231
+ * @param def The default ChatColor to use, when MC version is older than 1.16
232
+ * @return This {@link JSONMessage} instance
233
+ */
234
+ public JSONMessage color (String color , ChatColor def ) {
235
+ if (color .startsWith ("#" ) && ReflectionHelper .MAJOR_VER < 16 )
236
+ return color (def );
237
+
205
238
last ().setColor (color );
206
239
return this ;
207
240
}
208
241
242
+ /**
243
+ * Sets the font of the current message part.
244
+ * <br>When this is used on versions older than 1.16 will this do nothing.
245
+ *
246
+ * @param font The font to set
247
+ * @return This {@link JSONMessage} instance
248
+ */
249
+ public JSONMessage font (String font ) {
250
+ if (ReflectionHelper .MAJOR_VER < 16 )
251
+ return this ;
252
+
253
+ last ().setFont (font );
254
+ return this ;
255
+ }
256
+
209
257
/**
210
258
* Adds a style to the current message part.
211
259
*
@@ -250,6 +298,18 @@ public JSONMessage openURL(String url) {
250
298
return this ;
251
299
}
252
300
301
+ /**
302
+ * Copies the provided text to the Clipboard of the player.
303
+ * <br>When this is used on versions older than 1.15 will this default to {@link #suggestCommand(String) suggestCommand(String)}.
304
+ *
305
+ * @param text The text to copy
306
+ * @return This {@link JSONMessage} instance
307
+ */
308
+ public JSONMessage copyText (String text ) {
309
+ last ().setOnClick (ClickEvent .copyText (text ));
310
+ return this ;
311
+ }
312
+
253
313
/**
254
314
* Changes the page of a book. Using this in a non-book context is useless
255
315
* and will probably error.
@@ -421,10 +481,16 @@ public MessageEvent(String action, Object value) {
421
481
public JsonObject toJSON () {
422
482
JsonObject obj = new JsonObject ();
423
483
obj .addProperty ("action" , action );
484
+ /*
485
+ * MC 1.16 changed "value" to "contents", but only for Hover events... Don't ask why.
486
+ * Since this lib only has tooltip and achievement can we simply check if action starts with "show_"
487
+ */
488
+ String valueType = (ReflectionHelper .MAJOR_VER >= 16 && action .startsWith ("show_" )) ? "contents" : "value" ;
489
+
424
490
if (value instanceof JsonElement ) {
425
- obj .add ("value" , (JsonElement ) value );
491
+ obj .add (valueType , (JsonElement ) value );
426
492
} else {
427
- obj .addProperty ("value" , value .toString ());
493
+ obj .addProperty (valueType , value .toString ());
428
494
}
429
495
return obj ;
430
496
}
@@ -472,7 +538,7 @@ public static MessageEvent runCommand(String command) {
472
538
}
473
539
474
540
/**
475
- * Suggests a command by putting inserting it in chat.
541
+ * Suggests a command by inserting it in chat.
476
542
*
477
543
* @param command The command to suggest
478
544
* @return The {@link MessageEvent}
@@ -501,6 +567,20 @@ public static MessageEvent changePage(int page) {
501
567
return new MessageEvent ("change_page" , page );
502
568
}
503
569
570
+ /**
571
+ * Copies the provided text to the clipboard of the player.
572
+ * <br>When used on versions older than 1.15 will this {@link #suggestCommand(String) suggest the text} instead.
573
+ *
574
+ * @param text The text to copy.
575
+ * @return The {@link MessageEvent}
576
+ */
577
+ public static MessageEvent copyText (String text ) {
578
+ if (ReflectionHelper .MAJOR_VER < 15 )
579
+ return suggestCommand (text );
580
+
581
+ return new MessageEvent ("copy_to_clipboard" , text );
582
+ }
583
+
504
584
}
505
585
506
586
public static class HoverEvent {
@@ -674,6 +754,22 @@ static Object createTextPacket(String message) {
674
754
675
755
}
676
756
757
+ static void sendTextPacket (String message , Player ... players ) {
758
+ try {
759
+ for (Player player : players ) {
760
+ Class chatTypeClass = getClass ("{nms}.ChatMessageType" );
761
+ Constructor <?> constructor = packetPlayOutChat .getConstructor (getClass ("{nms}.IChatBaseComponent" ), chatTypeClass , UUID .class );
762
+ Object packet = constructor .newInstance (fromJson (message ), Enum .valueOf (chatTypeClass , "CHAT" ), player .getUniqueId ());
763
+
764
+ Object handler = player .getClass ().getMethod ("getHandle" ).invoke (player );
765
+ Object playerConnection = handler .getClass ().getField ("playerConnection" ).get (handler );
766
+ playerConnection .getClass ().getMethod ("sendPacket" , getClass ("{nms}.Packet" )).invoke (playerConnection , packet );
767
+ }
768
+ } catch (IllegalArgumentException | NoSuchMethodException | NoSuchFieldException | IllegalAccessException | InvocationTargetException | InstantiationException | ClassNotFoundException e ) {
769
+ e .printStackTrace ();
770
+ }
771
+ }
772
+
677
773
static Object createTitlePacket (String message ) {
678
774
if (!SETUP ) {
679
775
throw new IllegalStateException ("ReflectionHelper is not set up!" );
@@ -816,12 +912,13 @@ static int getVersion() {
816
912
*
817
913
* @author Rayzr
818
914
*/
819
- public class MessagePart {
915
+ public static class MessagePart {
820
916
821
917
private final List <ChatColor > styles = new ArrayList <>();
822
918
private MessageEvent onClick ;
823
919
private MessageEvent onHover ;
824
- private ChatColor color ;
920
+ private String color ;
921
+ private String font ;
825
922
private String text ;
826
923
827
924
public MessagePart (String text ) {
@@ -839,8 +936,8 @@ public JsonObject toJSON() {
839
936
JsonObject obj = new JsonObject ();
840
937
obj .addProperty ("text" , text );
841
938
842
- if (color != null ) {
843
- obj .addProperty ("color" , color .name (). toLowerCase ());
939
+ if (color != null && ! color . isEmpty () ) {
940
+ obj .addProperty ("color" , color .toLowerCase ());
844
941
}
845
942
846
943
for (ChatColor style : styles ) {
@@ -855,6 +952,10 @@ public JsonObject toJSON() {
855
952
obj .add ("hoverEvent" , onHover .toJSON ());
856
953
}
857
954
955
+ if (font != null ) {
956
+ obj .addProperty ("font" , font );
957
+ }
958
+
858
959
return obj ;
859
960
860
961
}
@@ -865,7 +966,7 @@ public JsonObject toJSON() {
865
966
public String toLegacy () {
866
967
StringBuilder output = new StringBuilder ();
867
968
if (color != null ) {
868
- output .append (color . toString () );
969
+ output .append (color );
869
970
}
870
971
styles .stream ()
871
972
.map (ChatColor ::toString )
@@ -905,16 +1006,43 @@ public void setOnHover(MessageEvent onHover) {
905
1006
/**
906
1007
* @return The color
907
1008
*/
908
- public ChatColor getColor () {
1009
+ public String getColorValue () {
909
1010
return color ;
910
1011
}
911
1012
1013
+ /**
1014
+ * @return The color
1015
+ *
1016
+ * @deprecated Use {@link #getColorValue()} instead
1017
+ */
1018
+ @ Deprecated
1019
+ public ChatColor getColor () {
1020
+ if (this .color .startsWith ("#" ) && ReflectionHelper .MAJOR_VER < 16 )
1021
+ throw new IllegalStateException ("Custom Hex colors can only be used in Minecraft 1.16 or newer!" );
1022
+
1023
+ try {
1024
+ return ChatColor .valueOf (this .color .toUpperCase ());
1025
+ } catch (Exception ex ) {
1026
+ return null ;
1027
+ }
1028
+ }
1029
+
912
1030
/**
913
1031
* @param color The color to set
1032
+ *
1033
+ * @deprecated Use {@link #setColor(String)} instead
914
1034
*/
1035
+ @ Deprecated
915
1036
public void setColor (ChatColor color ) {
916
- if (!color .isColor ()) {
917
- throw new IllegalArgumentException (color .name () + " is not a color!" );
1037
+ setColor (color .name ().toLowerCase ());
1038
+ }
1039
+
1040
+ /**
1041
+ * @param color The color to set
1042
+ */
1043
+ public void setColor (String color ) {
1044
+ if (color == null || color .isEmpty ()) {
1045
+ throw new IllegalArgumentException ("Color cannot be null!" );
918
1046
}
919
1047
this .color = color ;
920
1048
}
@@ -934,11 +1062,25 @@ public void addStyle(ChatColor style) {
934
1062
throw new IllegalArgumentException ("Style cannot be null!" );
935
1063
}
936
1064
if (!style .isFormat ()) {
937
- throw new IllegalArgumentException (color .name () + " is not a style!" );
1065
+ throw new IllegalArgumentException (style .name () + " is not a style!" );
938
1066
}
939
1067
styles .add (style );
940
1068
}
941
1069
1070
+ /**
1071
+ * @return The font used
1072
+ */
1073
+ public String getFont () {
1074
+ return font ;
1075
+ }
1076
+
1077
+ /**
1078
+ * @param font The font to use
1079
+ */
1080
+ public void setFont (String font ) {
1081
+ this .font = font ;
1082
+ }
1083
+
942
1084
/**
943
1085
* @return The raw text
944
1086
*/
@@ -954,5 +1096,4 @@ public void setText(String text) {
954
1096
}
955
1097
956
1098
}
957
-
958
- }
1099
+ }
0 commit comments