7
7
import com .google .gson .JsonElement ;
8
8
import com .google .gson .JsonObject ;
9
9
import com .google .gson .JsonPrimitive ;
10
+
10
11
import org .bukkit .Bukkit ;
11
12
import org .bukkit .ChatColor ;
12
13
import org .bukkit .entity .Player ;
15
16
import java .lang .invoke .MethodHandles ;
16
17
import java .lang .reflect .Constructor ;
17
18
import java .lang .reflect .Field ;
18
- import java .lang .reflect .InvocationTargetException ;
19
19
import java .lang .reflect .Method ;
20
- import java .util .*;
20
+ import java .util .ArrayList ;
21
+ import java .util .List ;
22
+ import java .util .Objects ;
23
+ import java .util .UUID ;
24
+ import java .util .Vector ;
21
25
22
26
/**
23
27
* This is a complete JSON message builder class. To create a new JSONMessage do
24
28
* {@link #create(String)}
25
- *
29
+ *
26
30
* @author Rayzr
27
31
*/
28
32
@ SuppressWarnings ({"WeakerAccess" , "unused" })
@@ -160,8 +164,8 @@ public String toLegacy() {
160
164
*/
161
165
public void send (Player ... players ) {
162
166
if (ReflectionHelper .MAJOR_VER >= 16 ) {
163
- ReflectionHelper .sendTextPacket (toString (), players );
164
- return ;
167
+ // ReflectionHelper.sendTextPacket(toString(), players);
168
+ // return;
165
169
}
166
170
167
171
ReflectionHelper .sendPacket (ReflectionHelper .createTextPacket (toString ()), players );
@@ -226,9 +230,9 @@ public JSONMessage color(String color) {
226
230
* Sets the color of the current message part.
227
231
* <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
232
* default ChatColor be used instead.
229
- *
233
+ *
230
234
* @param color The color to set
231
- * @param def The default ChatColor to use, when MC version is older than 1.16
235
+ * @param def The default ChatColor to use, when MC version is older than 1.16
232
236
* @return This {@link JSONMessage} instance
233
237
*/
234
238
public JSONMessage color (String color , ChatColor def ) {
@@ -242,14 +246,14 @@ public JSONMessage color(String color, ChatColor def) {
242
246
/**
243
247
* Sets the font of the current message part.
244
248
* <br>When this is used on versions older than 1.16 will this do nothing.
245
- *
249
+ *
246
250
* @param font The font to set
247
251
* @return This {@link JSONMessage} instance
248
252
*/
249
253
public JSONMessage font (String font ) {
250
254
if (ReflectionHelper .MAJOR_VER < 16 )
251
255
return this ;
252
-
256
+
253
257
last ().setFont (font );
254
258
return this ;
255
259
}
@@ -627,6 +631,9 @@ private static class ReflectionHelper {
627
631
private static Class <?> craftPlayer ;
628
632
private static Constructor <?> chatComponentText ;
629
633
private static Class <?> packetPlayOutChat ;
634
+ private static Field packetPlayOutChatComponent ;
635
+ private static Field packetPlayOutChatMessageType ;
636
+ private static Field packetPlayOutChatUuid ;
630
637
private static Class <?> packetPlayOutTitle ;
631
638
private static Class <?> iChatBaseComponent ;
632
639
private static Class <?> titleAction ;
@@ -646,9 +653,7 @@ private static class ReflectionHelper {
646
653
version = split [split .length - 1 ];
647
654
648
655
try {
649
- SETUP = true ;
650
-
651
- MAJOR_VER = getVersion ();
656
+ MAJOR_VER = Integer .parseInt (version .split ("_" )[1 ]);
652
657
653
658
craftPlayer = getClass ("{obc}.entity.CraftPlayer" );
654
659
Method getHandle = craftPlayer .getMethod ("getHandle" );
@@ -672,6 +677,9 @@ private static class ReflectionHelper {
672
677
STRING_TO_CHAT = MethodHandles .lookup ().unreflect (stringToChat );
673
678
674
679
packetPlayOutChat = getClass ("{nms}.PacketPlayOutChat" );
680
+ packetPlayOutChatComponent = getField (packetPlayOutChat , "a" );
681
+ packetPlayOutChatMessageType = getField (packetPlayOutChat , "b" );
682
+ packetPlayOutChatUuid = MAJOR_VER >= 16 ? getField (packetPlayOutChat , "c" ) : null ;
675
683
packetPlayOutTitle = getClass ("{nms}.PacketPlayOutTitle" );
676
684
677
685
titleAction = getClass ("{nms}.PacketPlayOutTitle$EnumTitleAction" );
@@ -686,17 +694,16 @@ private static class ReflectionHelper {
686
694
enumActionbarMessage = getChatMessageType .invoke (null , (byte ) 2 );
687
695
}
688
696
697
+ SETUP = true ;
689
698
} catch (Exception e ) {
690
699
e .printStackTrace ();
691
700
SETUP = false ;
692
701
}
693
-
694
702
}
695
703
696
704
static void sendPacket (Object packet , Player ... players ) {
697
- if (!SETUP ) {
698
- throw new IllegalStateException ("ReflectionHelper is not set up!" );
699
- }
705
+ assertIsSetup ();
706
+
700
707
if (packet == null ) {
701
708
return ;
702
709
}
@@ -712,102 +719,80 @@ static void sendPacket(Object packet, Player... players) {
712
719
713
720
}
714
721
715
- private static void setType (Object object , byte type ) {
716
- if (MAJOR_VER < 12 ) {
717
- set ("b" , object , type );
718
- return ;
719
- }
720
-
721
- switch (type ) {
722
- case 1 :
723
- set ("b" , object , enumChatMessage );
724
- break ;
725
- case 2 :
726
- set ("b" , object , enumActionbarMessage );
727
- break ;
728
- default :
729
- throw new IllegalArgumentException ("type must be 1 or 2" );
730
- }
731
- }
732
-
733
722
static Object createActionbarPacket (String message ) {
734
- if (!SETUP ) {
735
- throw new IllegalStateException ("ReflectionHelper is not set up!" );
736
- }
723
+ assertIsSetup ();
724
+
737
725
Object packet = createTextPacket (message );
738
726
setType (packet , (byte ) 2 );
739
727
return packet ;
740
728
}
741
729
742
730
static Object createTextPacket (String message ) {
743
- if (!SETUP ) {
744
- throw new IllegalStateException ("ReflectionHelper is not set up!" );
745
- }
731
+ assertIsSetup ();
732
+
746
733
try {
747
734
Object packet = packetPlayOutChat .newInstance ();
748
- set ("a" , packet , fromJson (message ));
735
+ setFieldValue (packetPlayOutChatComponent , packet , fromJson (message ));
736
+ setFieldValue (packetPlayOutChatUuid , packet , UUID .randomUUID ());
749
737
setType (packet , (byte ) 1 );
750
738
return packet ;
751
739
} catch (Exception e ) {
752
740
e .printStackTrace ();
753
741
return null ;
754
742
}
755
-
756
743
}
757
744
758
- static void sendTextPacket (String message , Player ... players ) {
745
+ static Object createTitlePacket (String message ) {
746
+ assertIsSetup ();
747
+
759
748
try {
760
- for (Player player : players ) {
761
- Class chatTypeClass = getClass ("{nms}.ChatMessageType" );
762
- Constructor <?> constructor = packetPlayOutChat .getConstructor (getClass ("{nms}.IChatBaseComponent" ), chatTypeClass , UUID .class );
763
- Object packet = constructor .newInstance (fromJson (message ), Enum .valueOf (chatTypeClass , "CHAT" ), player .getUniqueId ());
764
-
765
- Object handler = player .getClass ().getMethod ("getHandle" ).invoke (player );
766
- Object playerConnection = handler .getClass ().getField ("playerConnection" ).get (handler );
767
- playerConnection .getClass ().getMethod ("sendPacket" , getClass ("{nms}.Packet" )).invoke (playerConnection , packet );
768
- }
769
- } catch (IllegalArgumentException | NoSuchMethodException | NoSuchFieldException | IllegalAccessException | InvocationTargetException | InstantiationException | ClassNotFoundException e ) {
749
+ return packetPlayOutTitle .getConstructor (titleAction , iChatBaseComponent ).newInstance (enumActionTitle , fromJson (message ));
750
+ } catch (Exception e ) {
770
751
e .printStackTrace ();
752
+ return null ;
771
753
}
772
754
}
773
755
774
- static Object createTitlePacket (String message ) {
775
- if (!SETUP ) {
776
- throw new IllegalStateException ("ReflectionHelper is not set up!" );
777
- }
756
+ static Object createTitleTimesPacket (int fadeIn , int stay , int fadeOut ) {
757
+ assertIsSetup ();
758
+
778
759
try {
779
- return packetPlayOutTitle .getConstructor (titleAction , iChatBaseComponent ).newInstance (enumActionTitle , fromJson ( message ) );
760
+ return packetPlayOutTitle .getConstructor (int . class , int . class , int . class ).newInstance (fadeIn , stay , fadeOut );
780
761
} catch (Exception e ) {
781
762
e .printStackTrace ();
782
763
return null ;
783
764
}
784
-
785
765
}
786
766
787
767
static Object createSubtitlePacket (String message ) {
788
- if (!SETUP ) {
789
- throw new IllegalStateException ("ReflectionHelper is not set up!" );
790
- }
768
+ assertIsSetup ();
769
+
791
770
try {
792
771
return packetPlayOutTitle .getConstructor (titleAction , iChatBaseComponent ).newInstance (enumActionSubtitle , fromJson (message ));
793
772
} catch (Exception e ) {
794
773
e .printStackTrace ();
795
774
return null ;
796
775
}
797
-
798
776
}
799
777
800
- static Object createTitleTimesPacket (int fadeIn , int stay , int fadeOut ) {
801
- if (!SETUP ) {
802
- throw new IllegalStateException ("ReflectionHelper is not set up!" );
803
- }
804
- try {
805
- return packetPlayOutTitle .getConstructor (int .class , int .class , int .class ).newInstance (fadeIn , stay , fadeOut );
806
- } catch (Exception e ) {
807
- e .printStackTrace ();
808
- return null ;
778
+ private static void setType (Object chatPacket , byte type ) {
779
+ assertIsSetup ();
780
+
781
+ if (MAJOR_VER < 12 ) {
782
+ setFieldValue (packetPlayOutChatMessageType , chatPacket , type );
783
+ return ;
809
784
}
810
785
786
+ switch (type ) {
787
+ case 1 :
788
+ setFieldValue (packetPlayOutChatMessageType , chatPacket , enumChatMessage );
789
+ break ;
790
+ case 2 :
791
+ setFieldValue (packetPlayOutChatMessageType , chatPacket , enumActionbarMessage );
792
+ break ;
793
+ default :
794
+ throw new IllegalArgumentException ("type must be 1 or 2" );
795
+ }
811
796
}
812
797
813
798
/**
@@ -817,9 +802,8 @@ static Object createTitleTimesPacket(int fadeIn, int stay, int fadeOut) {
817
802
* @return The chat component
818
803
*/
819
804
static Object componentText (String message ) {
820
- if (!SETUP ) {
821
- throw new IllegalStateException ("ReflectionHelper is not set up!" );
822
- }
805
+ assertIsSetup ();
806
+
823
807
try {
824
808
return chatComponentText .newInstance (message );
825
809
} catch (Exception e ) {
@@ -836,9 +820,8 @@ static Object componentText(String message) {
836
820
* @return The object representing the text in JSON form, or <code>null</code> if something went wrong converting the String to JSON data
837
821
*/
838
822
static Object fromJson (String json ) {
839
- if (!SETUP ) {
840
- throw new IllegalStateException ("ReflectionHelper is not set up!" );
841
- }
823
+ assertIsSetup ();
824
+
842
825
if (!json .trim ().startsWith ("{" )) {
843
826
return componentText (json );
844
827
}
@@ -849,60 +832,45 @@ static Object fromJson(String json) {
849
832
e .printStackTrace ();
850
833
return null ;
851
834
}
852
-
853
835
}
854
836
855
- /**
856
- * Returns a class with the given package and name. This method replaces <code>{nms}</code> with <code>net.minecraft.server.[version]</code> and <code>{obc}</code> with <code>org.bukkit.craft.[version]</code>
857
- * <br>
858
- * <br>
859
- * Example:
860
- *
861
- * <pre>
862
- * Class<?> entityPlayer = ReflectionHelper.getClass("{nms}.EntityPlayer");
863
- * </pre>
864
- *
865
- * @param path The path to the {@link Class}
866
- * @return The class
867
- * @throws ClassNotFoundException If the class was not found
868
- */
869
- static Class <?> getClass (String path ) throws ClassNotFoundException {
837
+ private static void assertIsSetup () {
870
838
if (!SETUP ) {
871
- throw new IllegalStateException ("ReflectionHelper is not set up!" );
839
+ throw new IllegalStateException ("JSONMessage. ReflectionHelper is not set up yet !" );
872
840
}
841
+ }
842
+
843
+ private static Class <?> getClass (String path ) throws ClassNotFoundException {
873
844
return Class .forName (path .replace ("{nms}" , "net.minecraft.server." + version ).replace ("{obc}" , "org.bukkit.craftbukkit." + version ));
874
845
}
875
846
876
- /**
877
- * Sets a field with the given name on an object to the value specified
878
- *
879
- * @param field The name of the field to change
880
- * @param obj The object to change the field of
881
- * @param value The new value to set
882
- */
883
- static void set (String field , Object obj , Object value ) {
847
+ private static void setFieldValue (Field field , Object instance , Object value ) {
848
+ if (field == null ) {
849
+ // useful for fields that might not exist
850
+ return ;
851
+ }
852
+
884
853
try {
885
- Field f = obj .getClass ().getDeclaredField (field );
886
- f .setAccessible (true );
887
- f .set (obj , value );
888
- } catch (Exception e ) {
854
+ field .set (instance , value );
855
+ } catch (IllegalAccessException e ) {
889
856
e .printStackTrace ();
890
857
}
891
858
}
892
859
893
- static int getVersion () {
894
- if (!SETUP ) {
895
- throw new IllegalStateException ("ReflectionHelper is not set up!" );
896
- }
860
+ private static Field getField (Class <?> classObject , String fieldName ) {
897
861
try {
898
- return Integer .parseInt (version .split ("_" )[1 ]);
899
- } catch (NumberFormatException e ) {
862
+ Field field = classObject .getDeclaredField (fieldName );
863
+ field .setAccessible (true );
864
+ return field ;
865
+ } catch (NoSuchFieldException e ) {
900
866
e .printStackTrace ();
901
- return 10 ;
867
+ return null ;
902
868
}
903
-
904
869
}
905
870
871
+ private static int getVersion () {
872
+ return MAJOR_VER ;
873
+ }
906
874
}
907
875
908
876
/**
@@ -1013,12 +981,11 @@ public String getColorValue() {
1013
981
1014
982
/**
1015
983
* @return The color
1016
- *
1017
984
* @deprecated Use {@link #getColorValue()} instead
1018
985
*/
1019
986
@ Deprecated
1020
987
public ChatColor getColor () {
1021
- if (this .color .startsWith ("#" ) && ReflectionHelper .MAJOR_VER < 16 )
988
+ if (this .color .startsWith ("#" ) && ReflectionHelper .MAJOR_VER < 16 )
1022
989
throw new IllegalStateException ("Custom Hex colors can only be used in Minecraft 1.16 or newer!" );
1023
990
1024
991
try {
@@ -1030,7 +997,6 @@ public ChatColor getColor() {
1030
997
1031
998
/**
1032
999
* @param color The color to set
1033
- *
1034
1000
* @deprecated Use {@link #setColor(String)} instead
1035
1001
*/
1036
1002
@ Deprecated
0 commit comments