Skip to content

Commit 590fea1

Browse files
authored
Update JSONMessage for 1.16 (#7)
* Update JSONMessage for 1.16 * Improve readme * Add hex color and font support * Add check for custom color in <1.16 * Improvements and corrections * tiny spaces * Re-add old getColor and setColor methods * Update Color methods
1 parent 2742e5f commit 590fea1

File tree

2 files changed

+198
-39
lines changed

2 files changed

+198
-39
lines changed

README.md

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -144,29 +144,47 @@ If you want to see all the available methods, you can find them just below this.
144144

145145
## Methods overview
146146

147-
Method | Description
148-
------ | -----------
149-
`create(String)` | Creates a new JSONMessage with the given text as a starting point
147+
### Text/Styling
148+
Method | Description
149+
------------------ | -----------
150+
`bar()` | Creates a horizontal divider bar 53 characters long. This is perfect for the default chat window width
151+
`bar(int)` | Creates a horizontal divider bar of the given length
152+
`create(String)` | Creates a new JSONMessage with the given text as a starting point
150153
`color(ChatColor)` | Sets the color of the current message part
154+
`newline()` | Inserts a newline. It really isn't necessary, you can just use `\n` if you want
151155
`style(ChatColor)` | Adds a style to the current message part
152-
`runCommand(String)` | `ClickEvent`: Runs the given command
153-
`suggestCommand(String)` | `ClickEvent`: Suggests the given command by inserting it into the player's chat area
154-
`openURL(String)` | `ClickEvent`: Opens the given URL
155-
`changePage(int)` | `ClickEvent`: changes the page of a book to the given page
156-
`tooltip(String)` | `HoverEvent`: shows the given text
157-
`tooltip(JSONMessage)` | `HoverEvent`: shows the given JSON as text (works just like the rest of this system)
158-
`achievement(String)` | `HoverEvent`: shows an achievement with the given ID
159-
`then(String)` | Adds another part to the message
160-
`bar(int)` | Creates a horizontal divider bar of the given length
161-
`bar()` | Creates a horizontal divider bar 53 characters long. This is perfect for the default chat window width
162-
`newline()` | Inserts a newline. It really isn't necessary, you can just use `\n` if you want
163-
`toJSON()` | Converts the JSONMessage to a `JsonObject` (Google's Gson library, comes with Bukkit)
156+
`then(String)` | Adds another part to the message
157+
158+
### HoverAction
159+
Method | Description
160+
---------------------- | -----------
161+
`achievement(String)` | Shows an achievement with the given ID
162+
`tooltip(JSONMessage)` | Shows the given JSON as text (works just like the rest of this system)
163+
`tooltip(String)` | Shows the given text
164+
165+
### ClickAction
166+
Method | Description
167+
------------------------ | -----------
168+
`changePage(int)` | Changes the page of a book to the given page
169+
`copyText(String)` | Copies the provided text into the Player's clipboard (1.15+ only. Will default to `suggestCommand(String)`)
170+
`openURL(String)` | Opens the given URL
171+
`runCommand(String)` | Runs the given command
172+
`suggestCommand(String)` | Suggests the given command by inserting it into the player's chat area
173+
174+
### Sending
175+
Method | Description
176+
--------------------------------------- | -----------
177+
`actionbar(Player...)` | Converts the JSONMessage to the legacy format and sends it to one or multiple players
178+
`(static) actionbar(String, Player...)` | Sends an action-bar message to one or multiple players
179+
`send(Player...)` | Sends the JSONMessage to one or multiple players
180+
`subtitle(Player...)` | Sends the JSONMessage as a subtitle to one or multiple players
181+
`title(int, int, int, Player...)` | Sends the JSONMessage as a title to one or multiple players. Int parameters are `fadeIn`, `stay`, and `fadeOut`
182+
183+
### Others
184+
Method | Description
185+
------------ | -----------
186+
`toJSON()` | Converts the JSONMessage to a `JsonObject` (Google's Gson library, comes with Bukkit)
164187
`toString()` | Converts the JSONMessage to a String, usable in things like `/tellraw`. This is an alias of `toJSON().toString()`
165-
`send(Player...)` | Sends the JSONMessage to one or many players
166-
`title(int, int, int, Player...)` | Sends the JSONMessage as a title to one or many players. Int parameters are `fadeIn`, `stay`, and `fadeOut`
167-
`subtitle(Player...)` | Sends the JSONMessage as a subtitle to one or many players
168-
`(static) actionbar(String, Player...)` | Sends an action-bar message to one or many players
169-
`actionbar(Player...)` | Converts the JSONMessage to the legacy format and sends it to one or many players
170188

171189
### Method Notes
172190

src/main/java/me/rayzr522/jsonmessage/JSONMessage.java

Lines changed: 160 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,14 @@
1515
import java.lang.invoke.MethodHandles;
1616
import java.lang.reflect.Constructor;
1717
import java.lang.reflect.Field;
18+
import java.lang.reflect.InvocationTargetException;
1819
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.*;
2321

2422
/**
2523
* This is a complete JSON message builder class. To create a new JSONMessage do
2624
* {@link #create(String)}
27-
*
25+
*
2826
* @author Rayzr
2927
*/
3028
@SuppressWarnings({"WeakerAccess", "unused"})
@@ -161,6 +159,11 @@ public String toLegacy() {
161159
* @param players The players you want to send this to
162160
*/
163161
public void send(Player... players) {
162+
if (ReflectionHelper.MAJOR_VER >= 16) {
163+
ReflectionHelper.sendTextPacket(toString(), players);
164+
return;
165+
}
166+
164167
ReflectionHelper.sendPacket(ReflectionHelper.createTextPacket(toString()), players);
165168
}
166169

@@ -202,10 +205,55 @@ public void actionbar(Player... players) {
202205
* @return This {@link JSONMessage} instance
203206
*/
204207
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+
205238
last().setColor(color);
206239
return this;
207240
}
208241

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+
209257
/**
210258
* Adds a style to the current message part.
211259
*
@@ -250,6 +298,18 @@ public JSONMessage openURL(String url) {
250298
return this;
251299
}
252300

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+
253313
/**
254314
* Changes the page of a book. Using this in a non-book context is useless
255315
* and will probably error.
@@ -421,10 +481,16 @@ public MessageEvent(String action, Object value) {
421481
public JsonObject toJSON() {
422482
JsonObject obj = new JsonObject();
423483
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+
424490
if (value instanceof JsonElement) {
425-
obj.add("value", (JsonElement) value);
491+
obj.add(valueType, (JsonElement) value);
426492
} else {
427-
obj.addProperty("value", value.toString());
493+
obj.addProperty(valueType, value.toString());
428494
}
429495
return obj;
430496
}
@@ -472,7 +538,7 @@ public static MessageEvent runCommand(String command) {
472538
}
473539

474540
/**
475-
* Suggests a command by putting inserting it in chat.
541+
* Suggests a command by inserting it in chat.
476542
*
477543
* @param command The command to suggest
478544
* @return The {@link MessageEvent}
@@ -501,6 +567,20 @@ public static MessageEvent changePage(int page) {
501567
return new MessageEvent("change_page", page);
502568
}
503569

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+
504584
}
505585

506586
public static class HoverEvent {
@@ -674,6 +754,22 @@ static Object createTextPacket(String message) {
674754

675755
}
676756

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+
677773
static Object createTitlePacket(String message) {
678774
if (!SETUP) {
679775
throw new IllegalStateException("ReflectionHelper is not set up!");
@@ -816,12 +912,13 @@ static int getVersion() {
816912
*
817913
* @author Rayzr
818914
*/
819-
public class MessagePart {
915+
public static class MessagePart {
820916

821917
private final List<ChatColor> styles = new ArrayList<>();
822918
private MessageEvent onClick;
823919
private MessageEvent onHover;
824-
private ChatColor color;
920+
private String color;
921+
private String font;
825922
private String text;
826923

827924
public MessagePart(String text) {
@@ -839,8 +936,8 @@ public JsonObject toJSON() {
839936
JsonObject obj = new JsonObject();
840937
obj.addProperty("text", text);
841938

842-
if (color != null) {
843-
obj.addProperty("color", color.name().toLowerCase());
939+
if (color != null && !color.isEmpty()) {
940+
obj.addProperty("color", color.toLowerCase());
844941
}
845942

846943
for (ChatColor style : styles) {
@@ -855,6 +952,10 @@ public JsonObject toJSON() {
855952
obj.add("hoverEvent", onHover.toJSON());
856953
}
857954

955+
if (font != null) {
956+
obj.addProperty("font", font);
957+
}
958+
858959
return obj;
859960

860961
}
@@ -865,7 +966,7 @@ public JsonObject toJSON() {
865966
public String toLegacy() {
866967
StringBuilder output = new StringBuilder();
867968
if (color != null) {
868-
output.append(color.toString());
969+
output.append(color);
869970
}
870971
styles.stream()
871972
.map(ChatColor::toString)
@@ -905,16 +1006,43 @@ public void setOnHover(MessageEvent onHover) {
9051006
/**
9061007
* @return The color
9071008
*/
908-
public ChatColor getColor() {
1009+
public String getColorValue() {
9091010
return color;
9101011
}
9111012

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+
9121030
/**
9131031
* @param color The color to set
1032+
*
1033+
* @deprecated Use {@link #setColor(String)} instead
9141034
*/
1035+
@Deprecated
9151036
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!");
9181046
}
9191047
this.color = color;
9201048
}
@@ -934,11 +1062,25 @@ public void addStyle(ChatColor style) {
9341062
throw new IllegalArgumentException("Style cannot be null!");
9351063
}
9361064
if (!style.isFormat()) {
937-
throw new IllegalArgumentException(color.name() + " is not a style!");
1065+
throw new IllegalArgumentException(style.name() + " is not a style!");
9381066
}
9391067
styles.add(style);
9401068
}
9411069

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+
9421084
/**
9431085
* @return The raw text
9441086
*/
@@ -954,5 +1096,4 @@ public void setText(String text) {
9541096
}
9551097

9561098
}
957-
958-
}
1099+
}

0 commit comments

Comments
 (0)