77import com .google .gson .JsonElement ;
88import com .google .gson .JsonObject ;
99import com .google .gson .JsonPrimitive ;
10+
1011import org .bukkit .Bukkit ;
1112import org .bukkit .ChatColor ;
1213import org .bukkit .entity .Player ;
1516import java .lang .invoke .MethodHandles ;
1617import java .lang .reflect .Constructor ;
1718import java .lang .reflect .Field ;
18- import java .lang .reflect .InvocationTargetException ;
1919import 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 ;
2125
2226/**
2327 * This is a complete JSON message builder class. To create a new JSONMessage do
2428 * {@link #create(String)}
25- *
29+ *
2630 * @author Rayzr
2731 */
2832@ SuppressWarnings ({"WeakerAccess" , "unused" })
@@ -160,8 +164,8 @@ public String toLegacy() {
160164 */
161165 public void send (Player ... players ) {
162166 if (ReflectionHelper .MAJOR_VER >= 16 ) {
163- ReflectionHelper .sendTextPacket (toString (), players );
164- return ;
167+ // ReflectionHelper.sendTextPacket(toString(), players);
168+ // return;
165169 }
166170
167171 ReflectionHelper .sendPacket (ReflectionHelper .createTextPacket (toString ()), players );
@@ -226,9 +230,9 @@ public JSONMessage color(String color) {
226230 * Sets the color of the current message part.
227231 * <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
228232 * default ChatColor be used instead.
229- *
233+ *
230234 * @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
232236 * @return This {@link JSONMessage} instance
233237 */
234238 public JSONMessage color (String color , ChatColor def ) {
@@ -242,14 +246,14 @@ public JSONMessage color(String color, ChatColor def) {
242246 /**
243247 * Sets the font of the current message part.
244248 * <br>When this is used on versions older than 1.16 will this do nothing.
245- *
249+ *
246250 * @param font The font to set
247251 * @return This {@link JSONMessage} instance
248252 */
249253 public JSONMessage font (String font ) {
250254 if (ReflectionHelper .MAJOR_VER < 16 )
251255 return this ;
252-
256+
253257 last ().setFont (font );
254258 return this ;
255259 }
@@ -627,6 +631,9 @@ private static class ReflectionHelper {
627631 private static Class <?> craftPlayer ;
628632 private static Constructor <?> chatComponentText ;
629633 private static Class <?> packetPlayOutChat ;
634+ private static Field packetPlayOutChatComponent ;
635+ private static Field packetPlayOutChatMessageType ;
636+ private static Field packetPlayOutChatUuid ;
630637 private static Class <?> packetPlayOutTitle ;
631638 private static Class <?> iChatBaseComponent ;
632639 private static Class <?> titleAction ;
@@ -646,9 +653,7 @@ private static class ReflectionHelper {
646653 version = split [split .length - 1 ];
647654
648655 try {
649- SETUP = true ;
650-
651- MAJOR_VER = getVersion ();
656+ MAJOR_VER = Integer .parseInt (version .split ("_" )[1 ]);
652657
653658 craftPlayer = getClass ("{obc}.entity.CraftPlayer" );
654659 Method getHandle = craftPlayer .getMethod ("getHandle" );
@@ -672,6 +677,9 @@ private static class ReflectionHelper {
672677 STRING_TO_CHAT = MethodHandles .lookup ().unreflect (stringToChat );
673678
674679 packetPlayOutChat = getClass ("{nms}.PacketPlayOutChat" );
680+ packetPlayOutChatComponent = getField (packetPlayOutChat , "a" );
681+ packetPlayOutChatMessageType = getField (packetPlayOutChat , "b" );
682+ packetPlayOutChatUuid = MAJOR_VER >= 16 ? getField (packetPlayOutChat , "c" ) : null ;
675683 packetPlayOutTitle = getClass ("{nms}.PacketPlayOutTitle" );
676684
677685 titleAction = getClass ("{nms}.PacketPlayOutTitle$EnumTitleAction" );
@@ -686,17 +694,16 @@ private static class ReflectionHelper {
686694 enumActionbarMessage = getChatMessageType .invoke (null , (byte ) 2 );
687695 }
688696
697+ SETUP = true ;
689698 } catch (Exception e ) {
690699 e .printStackTrace ();
691700 SETUP = false ;
692701 }
693-
694702 }
695703
696704 static void sendPacket (Object packet , Player ... players ) {
697- if (!SETUP ) {
698- throw new IllegalStateException ("ReflectionHelper is not set up!" );
699- }
705+ assertIsSetup ();
706+
700707 if (packet == null ) {
701708 return ;
702709 }
@@ -712,102 +719,80 @@ static void sendPacket(Object packet, Player... players) {
712719
713720 }
714721
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-
733722 static Object createActionbarPacket (String message ) {
734- if (!SETUP ) {
735- throw new IllegalStateException ("ReflectionHelper is not set up!" );
736- }
723+ assertIsSetup ();
724+
737725 Object packet = createTextPacket (message );
738726 setType (packet , (byte ) 2 );
739727 return packet ;
740728 }
741729
742730 static Object createTextPacket (String message ) {
743- if (!SETUP ) {
744- throw new IllegalStateException ("ReflectionHelper is not set up!" );
745- }
731+ assertIsSetup ();
732+
746733 try {
747734 Object packet = packetPlayOutChat .newInstance ();
748- set ("a" , packet , fromJson (message ));
735+ setFieldValue (packetPlayOutChatComponent , packet , fromJson (message ));
736+ setFieldValue (packetPlayOutChatUuid , packet , UUID .randomUUID ());
749737 setType (packet , (byte ) 1 );
750738 return packet ;
751739 } catch (Exception e ) {
752740 e .printStackTrace ();
753741 return null ;
754742 }
755-
756743 }
757744
758- static void sendTextPacket (String message , Player ... players ) {
745+ static Object createTitlePacket (String message ) {
746+ assertIsSetup ();
747+
759748 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 ) {
770751 e .printStackTrace ();
752+ return null ;
771753 }
772754 }
773755
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+
778759 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 );
780761 } catch (Exception e ) {
781762 e .printStackTrace ();
782763 return null ;
783764 }
784-
785765 }
786766
787767 static Object createSubtitlePacket (String message ) {
788- if (!SETUP ) {
789- throw new IllegalStateException ("ReflectionHelper is not set up!" );
790- }
768+ assertIsSetup ();
769+
791770 try {
792771 return packetPlayOutTitle .getConstructor (titleAction , iChatBaseComponent ).newInstance (enumActionSubtitle , fromJson (message ));
793772 } catch (Exception e ) {
794773 e .printStackTrace ();
795774 return null ;
796775 }
797-
798776 }
799777
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 ;
809784 }
810785
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+ }
811796 }
812797
813798 /**
@@ -817,9 +802,8 @@ static Object createTitleTimesPacket(int fadeIn, int stay, int fadeOut) {
817802 * @return The chat component
818803 */
819804 static Object componentText (String message ) {
820- if (!SETUP ) {
821- throw new IllegalStateException ("ReflectionHelper is not set up!" );
822- }
805+ assertIsSetup ();
806+
823807 try {
824808 return chatComponentText .newInstance (message );
825809 } catch (Exception e ) {
@@ -836,9 +820,8 @@ static Object componentText(String message) {
836820 * @return The object representing the text in JSON form, or <code>null</code> if something went wrong converting the String to JSON data
837821 */
838822 static Object fromJson (String json ) {
839- if (!SETUP ) {
840- throw new IllegalStateException ("ReflectionHelper is not set up!" );
841- }
823+ assertIsSetup ();
824+
842825 if (!json .trim ().startsWith ("{" )) {
843826 return componentText (json );
844827 }
@@ -849,60 +832,45 @@ static Object fromJson(String json) {
849832 e .printStackTrace ();
850833 return null ;
851834 }
852-
853835 }
854836
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 () {
870838 if (!SETUP ) {
871- throw new IllegalStateException ("ReflectionHelper is not set up!" );
839+ throw new IllegalStateException ("JSONMessage. ReflectionHelper is not set up yet !" );
872840 }
841+ }
842+
843+ private static Class <?> getClass (String path ) throws ClassNotFoundException {
873844 return Class .forName (path .replace ("{nms}" , "net.minecraft.server." + version ).replace ("{obc}" , "org.bukkit.craftbukkit." + version ));
874845 }
875846
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+
884853 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 ) {
889856 e .printStackTrace ();
890857 }
891858 }
892859
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 ) {
897861 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 ) {
900866 e .printStackTrace ();
901- return 10 ;
867+ return null ;
902868 }
903-
904869 }
905870
871+ private static int getVersion () {
872+ return MAJOR_VER ;
873+ }
906874 }
907875
908876 /**
@@ -1013,12 +981,11 @@ public String getColorValue() {
1013981
1014982 /**
1015983 * @return The color
1016- *
1017984 * @deprecated Use {@link #getColorValue()} instead
1018985 */
1019986 @ Deprecated
1020987 public ChatColor getColor () {
1021- if (this .color .startsWith ("#" ) && ReflectionHelper .MAJOR_VER < 16 )
988+ if (this .color .startsWith ("#" ) && ReflectionHelper .MAJOR_VER < 16 )
1022989 throw new IllegalStateException ("Custom Hex colors can only be used in Minecraft 1.16 or newer!" );
1023990
1024991 try {
@@ -1030,7 +997,6 @@ public ChatColor getColor() {
1030997
1031998 /**
1032999 * @param color The color to set
1033- *
10341000 * @deprecated Use {@link #setColor(String)} instead
10351001 */
10361002 @ Deprecated
0 commit comments