Advertisement
Guest User

Untitled

a guest
Dec 13th, 2017
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 23.54 KB | None | 0 0
  1.  
  2. import java.lang.reflect.Constructor;
  3. import java.lang.reflect.Field;
  4. import java.lang.reflect.Method;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. import java.util.Objects;
  8.  
  9. import org.bukkit.Bukkit;
  10. import org.bukkit.ChatColor;
  11. import org.bukkit.entity.Player;
  12.  
  13. import com.google.common.base.Strings;
  14. import com.google.common.collect.BiMap;
  15. import com.google.common.collect.ImmutableBiMap;
  16. import com.google.gson.JsonArray;
  17. import com.google.gson.JsonElement;
  18. import com.google.gson.JsonObject;
  19. import com.google.gson.JsonPrimitive;
  20.  
  21. /**
  22. * This is a complete JSON message builder class. To create a new JSONMessage do
  23. * {@link #create(String)}
  24. *
  25. * @author Rayzr
  26. *
  27. */
  28. public class JSONMessage {
  29.  
  30. private static final BiMap<ChatColor, String> stylesToNames;
  31.  
  32. static {
  33. ImmutableBiMap.Builder<ChatColor, String> builder = ImmutableBiMap.builder();
  34. for (final ChatColor style : ChatColor.values()) {
  35. if (!style.isFormat()) {
  36. continue;
  37. }
  38.  
  39. String styleName;
  40. switch (style) {
  41. case MAGIC:
  42. styleName = "obfuscated";
  43. break;
  44. case UNDERLINE:
  45. styleName = "underlined";
  46. break;
  47. default:
  48. styleName = style.name().toLowerCase();
  49. break;
  50. }
  51.  
  52. builder.put(style, styleName);
  53. }
  54. stylesToNames = builder.build();
  55. }
  56.  
  57. private List<MessagePart> parts = new ArrayList<MessagePart>();
  58.  
  59. /**
  60. * Creates a new JSONChat object
  61. *
  62. * @param text the text to start with
  63. */
  64. private JSONMessage(String text) {
  65. parts.add(new MessagePart(text));
  66. }
  67.  
  68. /**
  69. * Creates a new JSONChat object
  70. *
  71. * @param text the text to start with
  72. */
  73. public static JSONMessage create(String text) {
  74. return new JSONMessage(text);
  75. }
  76.  
  77. /**
  78. * Creates a new JSONChat object
  79. */
  80. public static JSONMessage create() {
  81. return create("");
  82. }
  83.  
  84. /**
  85. * Sends an action bar message
  86. *
  87. * @param players the players you want to send it to
  88. */
  89. public static void actionbar(String message, Player... players) {
  90.  
  91. ReflectionHelper.sendPacket(ReflectionHelper.createActionbarPacket(ChatColor.translateAlternateColorCodes('&', message)), players);
  92.  
  93. }
  94.  
  95. /**
  96. * @return The latest {@link MessagePart}
  97. * @throws ArrayIndexOutOfBoundsException If {@code parts.size() <= 0}.
  98. */
  99. public MessagePart last() {
  100. if (parts.size() <= 0) {
  101. throw new ArrayIndexOutOfBoundsException("No MessageParts exist!");
  102. }
  103. return parts.get(parts.size() - 1);
  104. }
  105.  
  106. /**
  107. * Converts this JSONChat instance to actual JSON
  108. *
  109. * @return The JSON representation of this
  110. */
  111. public JsonObject toJSON() {
  112.  
  113. JsonObject obj = new JsonObject();
  114.  
  115. obj.addProperty("text", "");
  116.  
  117. JsonArray array = new JsonArray();
  118. for (MessagePart part : parts) {
  119. array.add(part.toJSON());
  120. }
  121. obj.add("extra", array);
  122.  
  123. return obj;
  124. }
  125.  
  126. /**
  127. * Converts this JSONMessage object to a String representation of the JSON.
  128. * This is an alias of {@code toJSON().toString()}.
  129. */
  130. @Override
  131. public String toString() {
  132. return toJSON().toString();
  133. }
  134.  
  135. /**
  136. * Converts this JSONMessage object to the legacy formatting system, which
  137. * uses formatting codes (like &6, &l, &4, etc.)
  138. *
  139. * @return This JSONMessage in legacy format
  140. */
  141. public String toLegacy() {
  142. StringBuilder output = new StringBuilder();
  143. for (MessagePart part : parts) {
  144. output.append(part.toLegacy());
  145. }
  146. return output.toString();
  147. }
  148.  
  149. /**
  150. * Sends this JSONMessage to all the players specified
  151. *
  152. * @param players the players you want to send this to
  153. */
  154. public void send(Player... players) {
  155.  
  156. ReflectionHelper.sendPacket(ReflectionHelper.createTextPacket(toString()), players);
  157.  
  158. }
  159.  
  160. /**
  161. * Sends this as a title to all the players specified
  162. *
  163. * @param fadeIn how many ticks to fade in
  164. * @param stay how many ticks to stay
  165. * @param fadeOut how many ticks to fade out
  166. * @param players the players to send it to
  167. */
  168. public void title(int fadeIn, int stay, int fadeOut, Player... players) {
  169.  
  170. ReflectionHelper.sendPacket(ReflectionHelper.createTitleTimesPacket(fadeIn, stay, fadeOut), players);
  171. ReflectionHelper.sendPacket(ReflectionHelper.createTitlePacket(toString()), players);
  172.  
  173. }
  174.  
  175. /**
  176. * Sends this as a subtitle to all the players specified
  177. *
  178. * @param fadeIn how many ticks to fade in
  179. * @param stay how many ticks to stay
  180. * @param fadeOut how many ticks to fade out
  181. * @param players the players to send it to
  182. */
  183. public void subtitle(Player... players) {
  184.  
  185. ReflectionHelper.sendPacket(ReflectionHelper.createSubtitlePacket(toString()), players);
  186.  
  187. }
  188.  
  189. /**
  190. * Sends an action bar message
  191. *
  192. * @param players the players you want to send this to
  193. */
  194. public void actionbar(Player... players) {
  195. actionbar(toLegacy(), players);
  196. }
  197.  
  198. /**
  199. * Sets the color of the current message part.
  200. *
  201. * @param color the color to set
  202. * @return this
  203. */
  204. public JSONMessage color(ChatColor color) {
  205. last().setColor(color);
  206. return this;
  207. }
  208.  
  209. /**
  210. * Adds a style to the current message part.
  211. *
  212. * @param style the style to add
  213. * @return this
  214. */
  215. public JSONMessage style(ChatColor style) {
  216. last().addStyle(style);
  217. return this;
  218. }
  219.  
  220. /**
  221. * Makes the text run a command.
  222. *
  223. * @param cmd the command to run
  224. * @return this
  225. */
  226. public JSONMessage runCommand(String cmd) {
  227. last().setOnClick(ClickEvent.runCommand(cmd));
  228. return this;
  229. }
  230.  
  231. /**
  232. * Makes the text suggest a command.
  233. *
  234. * @param cmd the command to suggest
  235. * @return this
  236. */
  237. public JSONMessage suggestCommand(String cmd) {
  238. last().setOnClick(ClickEvent.suggestCommand(cmd));
  239. return this;
  240. }
  241.  
  242. /**
  243. * Opens a URL.
  244. *
  245. * @param url the url to open
  246. * @return this
  247. */
  248. public JSONMessage openURL(String url) {
  249. last().setOnClick(ClickEvent.openURL(url));
  250. return this;
  251. }
  252.  
  253. /**
  254. * Changes the page of a book. Using this in a non-book context is useless
  255. * and will probably error.
  256. *
  257. * @param page the page to change to
  258. * @return this
  259. */
  260. public JSONMessage changePage(int page) {
  261. last().setOnClick(ClickEvent.changePage(page));
  262. return this;
  263. }
  264.  
  265. /**
  266. * Shows text when you hover over it
  267. *
  268. * @param text the text to show
  269. * @return this
  270. */
  271. public JSONMessage tooltip(String text) {
  272. last().setOnHover(HoverEvent.showText(text));
  273. return this;
  274. }
  275.  
  276. /**
  277. * Shows text when you hover over it
  278. *
  279. * @param message the text to show
  280. * @return this
  281. */
  282. public JSONMessage tooltip(JSONMessage message) {
  283. last().setOnHover(HoverEvent.showText(message));
  284. return this;
  285. }
  286.  
  287. /**
  288. * Shows an achievement when you hover over it
  289. *
  290. * @param id the id of the achievement
  291. * @return
  292. */
  293. public JSONMessage achievement(String id) {
  294. last().setOnHover(HoverEvent.showAchievement(id));
  295. return this;
  296. }
  297.  
  298. /**
  299. * Adds another part to this JSONChat
  300. *
  301. * @param text the text to start with
  302. * @return this
  303. */
  304. public JSONMessage then(String text) {
  305. return then(new MessagePart(text));
  306. }
  307.  
  308. /**
  309. * Adds another part to this JSONChat
  310. *
  311. * @param text the next part
  312. * @return this
  313. */
  314. public JSONMessage then(MessagePart nextPart) {
  315. parts.add(nextPart);
  316. return this;
  317. }
  318.  
  319. /**
  320. * Adds a horizontal bar to the message of the given length
  321. *
  322. * @param length the length of the horizontal bar
  323. * @return this
  324. */
  325. public JSONMessage bar(int length) {
  326. return then(Strings.repeat("-", length)).color(ChatColor.DARK_GRAY).style(ChatColor.STRIKETHROUGH);
  327. }
  328.  
  329. /**
  330. * Adds a horizontal bar to the message that's 53 characters long. This is
  331. * the default width of the player's chat window.
  332. *
  333. * @return this
  334. */
  335. public JSONMessage bar() {
  336. return bar(53);
  337. }
  338.  
  339. /**
  340. * Adds a blank line to the message
  341. *
  342. * @return this
  343. */
  344. public JSONMessage newline() {
  345. return then("\n");
  346. }
  347.  
  348. ///////////////////////////
  349. // BEGIN UTILITY CLASSES //
  350. ///////////////////////////
  351. /**
  352. * Defines a section of the message.
  353. *
  354. * @author Rayzr
  355. *
  356. */
  357. public class MessagePart {
  358.  
  359. private MessageEvent onClick;
  360. private MessageEvent onHover;
  361. private List<ChatColor> styles = new ArrayList<ChatColor>();
  362. private ChatColor color;
  363. private String text;
  364.  
  365. public MessagePart(String text) {
  366. this.text = text == null ? "null" : text;
  367. }
  368.  
  369. public JsonObject toJSON() {
  370. Objects.requireNonNull(text);
  371.  
  372. JsonObject obj = new JsonObject();
  373. obj.addProperty("text", text);
  374.  
  375. if (color != null) {
  376. obj.addProperty("color", color.name().toLowerCase());
  377. }
  378.  
  379. for (ChatColor style : styles) {
  380. obj.addProperty(stylesToNames.get(style), true);
  381. }
  382.  
  383. if (onClick != null) {
  384. obj.add("clickEvent", onClick.toJSON());
  385. }
  386.  
  387. if (onHover != null) {
  388. obj.add("hoverEvent", onHover.toJSON());
  389. }
  390.  
  391. return obj;
  392.  
  393. }
  394.  
  395. /**
  396. * @return
  397. */
  398. public String toLegacy() {
  399. StringBuilder output = new StringBuilder();
  400. if (color != null) {
  401. output.append(color.toString());
  402. }
  403. for (ChatColor style : styles) {
  404. output.append(style.toString());
  405. }
  406. return output.append(text).toString();
  407. }
  408.  
  409. /**
  410. * @return the onClick event
  411. */
  412. public MessageEvent getOnClick() {
  413. return onClick;
  414. }
  415.  
  416. /**
  417. * @param onClick the onClick event to set
  418. */
  419. public void setOnClick(MessageEvent onClick) {
  420. this.onClick = onClick;
  421. }
  422.  
  423. /**
  424. * @return the onHover event
  425. */
  426. public MessageEvent getOnHover() {
  427. return onHover;
  428. }
  429.  
  430. /**
  431. * @param onHover the onHover event to set
  432. */
  433. public void setOnHover(MessageEvent onHover) {
  434. this.onHover = onHover;
  435. }
  436.  
  437. /**
  438. * @return the color
  439. */
  440. public ChatColor getColor() {
  441. return color;
  442. }
  443.  
  444. /**
  445. * @param color the color to set
  446. */
  447. public void setColor(ChatColor color) {
  448. if (!color.isColor()) {
  449. throw new IllegalArgumentException(color.name() + " is not a color!");
  450. }
  451. this.color = color;
  452. }
  453.  
  454. /**
  455. * @return the styles
  456. */
  457. public List<ChatColor> getStyles() {
  458. return styles;
  459. }
  460.  
  461. /**
  462. * Adds a style
  463. *
  464. * @param style the style to add
  465. */
  466. public void addStyle(ChatColor style) {
  467. if (style == null) {
  468. throw new IllegalArgumentException("Style cannot be null!");
  469. }
  470. if (!style.isFormat()) {
  471. throw new IllegalArgumentException(color.name() + " is not a style!");
  472. }
  473. styles.add(style);
  474. }
  475.  
  476. /**
  477. * @return the text
  478. */
  479. public String getText() {
  480. return text;
  481. }
  482.  
  483. /**
  484. * @param text the text to set
  485. */
  486. public void setText(String text) {
  487. this.text = text;
  488. }
  489.  
  490. }
  491.  
  492. public static class MessageEvent {
  493.  
  494. private String action;
  495. private Object value;
  496.  
  497. public MessageEvent(String action, Object value) {
  498.  
  499. this.action = action;
  500. this.value = value;
  501.  
  502. }
  503.  
  504. /**
  505. * @return
  506. */
  507. public JsonObject toJSON() {
  508. JsonObject obj = new JsonObject();
  509. obj.addProperty("action", action);
  510. if (value instanceof JsonElement) {
  511. obj.add("value", (JsonElement) value);
  512. } else {
  513. obj.addProperty("value", value.toString());
  514. }
  515. return obj;
  516. }
  517.  
  518. /**
  519. * @return the action
  520. */
  521. public String getAction() {
  522. return action;
  523. }
  524.  
  525. /**
  526. * @param action the action to set
  527. */
  528. public void setAction(String action) {
  529. this.action = action;
  530. }
  531.  
  532. /**
  533. * @return the value
  534. */
  535. public Object getValue() {
  536. return value;
  537. }
  538.  
  539. /**
  540. * @param value the value to set
  541. */
  542. public void setValue(Object value) {
  543. this.value = value;
  544. }
  545.  
  546. }
  547.  
  548. public static class ClickEvent {
  549.  
  550. /**
  551. * Runs a command.
  552. *
  553. * @param cmd the command to run
  554. * @return The MessageEvent
  555. */
  556. public static MessageEvent runCommand(String cmd) {
  557. return new MessageEvent("run_command", cmd);
  558. }
  559.  
  560. /**
  561. * Suggests a command by putting inserting it in chat.
  562. *
  563. * @param cmd the command to suggest
  564. * @return The MessageEvent
  565. */
  566. public static MessageEvent suggestCommand(String cmd) {
  567. return new MessageEvent("suggest_command", cmd);
  568. }
  569.  
  570. /**
  571. * Requires web links to be enabled on the client.
  572. *
  573. * @param url the url to open
  574. * @return The MessageEvent
  575. */
  576. public static MessageEvent openURL(String url) {
  577. return new MessageEvent("open_url", url);
  578. }
  579.  
  580. /**
  581. * Only used with written books.
  582. *
  583. * @param page the page to switch to
  584. * @return The MessageEvent
  585. */
  586. public static MessageEvent changePage(int page) {
  587. return new MessageEvent("change_page", page);
  588. }
  589.  
  590. }
  591.  
  592. public static class HoverEvent {
  593.  
  594. /**
  595. * Shows text when you hover over it
  596. *
  597. * @param text the text to show
  598. * @return The MessageEvent
  599. */
  600. public static MessageEvent showText(String text) {
  601. return new MessageEvent("show_text", text);
  602. }
  603.  
  604. /**
  605. * Shows text when you hover over it
  606. *
  607. * @param chat the JSON message to show
  608. * @return The MessageEvent
  609. */
  610. public static MessageEvent showText(JSONMessage message) {
  611. JsonArray arr = new JsonArray();
  612. arr.add(new JsonPrimitive(""));
  613. arr.add(message.toJSON());
  614. return new MessageEvent("show_text", arr);
  615. }
  616.  
  617. /**
  618. * Shows an achievement when you hover over it
  619. *
  620. * @param id the id over the achievement
  621. * @return
  622. */
  623. public static MessageEvent showAchievement(String id) {
  624. return new MessageEvent("show_achievement", id);
  625. }
  626.  
  627. }
  628.  
  629. private static class ReflectionHelper {
  630.  
  631. private static Class<?> craftPlayer;
  632.  
  633. private static Constructor<?> chatComponentText;
  634. private static Class<?> packetPlayOutChat;
  635. private static Class<?> packetPlayOutTitle;
  636. private static Class<?> iChatBaseComponent;
  637. private static Class<?> titleAction;
  638.  
  639. private static Field connection;
  640. private static Method getHandle;
  641. private static Method sendPacket;
  642. private static Method stringToChat;
  643.  
  644. private static Object actionTitle;
  645. private static Object actionSubtitle;
  646.  
  647. private static String version;
  648.  
  649. private static boolean SETUP = false;
  650.  
  651. static {
  652.  
  653. if (!SETUP) {
  654.  
  655. String[] split = Bukkit.getServer().getClass().getPackage().getName().split("\\.");
  656. version = split[split.length - 1];
  657.  
  658. try {
  659.  
  660. SETUP = true;
  661.  
  662. craftPlayer = getClass("{obc}.entity.CraftPlayer");
  663. getHandle = craftPlayer.getMethod("getHandle");
  664. connection = getHandle.getReturnType().getField("playerConnection");
  665. sendPacket = connection.getType().getMethod("sendPacket", getClass("{nms}.Packet"));
  666.  
  667. chatComponentText = getClass("{nms}.ChatComponentText").getConstructor(String.class);
  668.  
  669. iChatBaseComponent = getClass("{nms}.IChatBaseComponent");
  670.  
  671. if (getVersion() > 7) {
  672. stringToChat = getClass("{nms}.IChatBaseComponent$ChatSerializer").getMethod("a", String.class);
  673. } else {
  674. stringToChat = getClass("{nms}.ChatSerializer").getMethod("a", String.class);
  675. }
  676.  
  677. packetPlayOutChat = getClass("{nms}.PacketPlayOutChat");
  678. packetPlayOutTitle = getClass("{nms}.PacketPlayOutTitle");
  679.  
  680. titleAction = getClass("{nms}.PacketPlayOutTitle$EnumTitleAction");
  681.  
  682. actionTitle = titleAction.getField("TITLE").get(null);
  683. actionSubtitle = titleAction.getField("SUBTITLE").get(null);
  684.  
  685. } catch (Exception e) {
  686. e.printStackTrace();
  687. SETUP = false;
  688. }
  689.  
  690. }
  691.  
  692. }
  693.  
  694. public static void sendPacket(Object packet, Player... players) {
  695. if (!SETUP) {
  696. throw new IllegalStateException("ReflectionHelper is not set up!");
  697. }
  698. if (packet == null) {
  699. return;
  700. }
  701.  
  702. for (Player player : players) {
  703. try {
  704. sendPacket.invoke(connection.get(getHandle.invoke(player)), packet);
  705. } catch (Exception e) {
  706. System.err.println("Failed to send packet");
  707. e.printStackTrace();
  708. }
  709. }
  710.  
  711. }
  712.  
  713. public static Object createActionbarPacket(String message) {
  714. if (!SETUP) {
  715. throw new IllegalStateException("ReflectionHelper is not set up!");
  716. }
  717. Object packet = createTextPacket(message);
  718. set("b", packet, (byte) 2);
  719. return packet;
  720. }
  721.  
  722. public static Object createTextPacket(String message) {
  723. if (!SETUP) {
  724. throw new IllegalStateException("ReflectionHelper is not set up!");
  725. }
  726. try {
  727. Object packet = packetPlayOutChat.newInstance();
  728. set("a", packet, fromJson(message));
  729. set("b", packet, (byte) 1);
  730. return packet;
  731. } catch (Exception e) {
  732. e.printStackTrace();
  733. return null;
  734. }
  735.  
  736. }
  737.  
  738. public static Object createTitlePacket(String message) {
  739. if (!SETUP) {
  740. throw new IllegalStateException("ReflectionHelper is not set up!");
  741. }
  742. try {
  743. Object packet = packetPlayOutTitle.getConstructor(titleAction, iChatBaseComponent).newInstance(actionTitle, fromJson(message));
  744. return packet;
  745. } catch (Exception e) {
  746. e.printStackTrace();
  747. return null;
  748. }
  749.  
  750. }
  751.  
  752. public static Object createSubtitlePacket(String message) {
  753. if (!SETUP) {
  754. throw new IllegalStateException("ReflectionHelper is not set up!");
  755. }
  756. try {
  757. Object packet = packetPlayOutTitle.getConstructor(titleAction, iChatBaseComponent).newInstance(actionSubtitle, fromJson(message));
  758. return packet;
  759. } catch (Exception e) {
  760. e.printStackTrace();
  761. return null;
  762. }
  763.  
  764. }
  765.  
  766. public static Object createTitleTimesPacket(int fadeIn, int stay, int fadeOut) {
  767. if (!SETUP) {
  768. throw new IllegalStateException("ReflectionHelper is not set up!");
  769. }
  770. try {
  771. Object packet = packetPlayOutTitle.getConstructor(int.class, int.class, int.class).newInstance(fadeIn, stay, fadeOut);
  772. return packet;
  773. } catch (Exception e) {
  774. e.printStackTrace();
  775. return null;
  776. }
  777.  
  778. }
  779.  
  780. public static Object componentText(String msg) {
  781. if (!SETUP) {
  782. throw new IllegalStateException("ReflectionHelper is not set up!");
  783. }
  784. try {
  785. return chatComponentText.newInstance(msg);
  786. } catch (Exception e) {
  787. e.printStackTrace();
  788. return null;
  789. }
  790.  
  791. }
  792.  
  793. public static Object fromJson(String json) {
  794. if (!SETUP) {
  795. throw new IllegalStateException("ReflectionHelper is not set up!");
  796. }
  797. if (!json.trim().startsWith("{")) {
  798. return componentText(json);
  799. }
  800.  
  801. try {
  802. return stringToChat.invoke(null, json);
  803. } catch (Exception e) {
  804. e.printStackTrace();
  805. return null;
  806. }
  807.  
  808. }
  809.  
  810. public static Class<?> getClass(String path) throws ClassNotFoundException {
  811. if (!SETUP) {
  812. throw new IllegalStateException("ReflectionHelper is not set up!");
  813. }
  814. return Class.forName(path.replace("{nms}", "net.minecraft.server." + version).replace("{obc}", "org.bukkit.craftbukkit." + version));
  815. }
  816.  
  817. public static void set(String field, Object o, Object v) {
  818. try {
  819. Field f = o.getClass().getDeclaredField(field);
  820. f.setAccessible(true);
  821. f.set(o, v);
  822. } catch (Exception e) {
  823. e.printStackTrace();
  824. }
  825. }
  826.  
  827. public static int getVersion() {
  828. if (!SETUP) {
  829. throw new IllegalStateException("ReflectionHelper is not set up!");
  830. }
  831. try {
  832. return Integer.parseInt(version.split("_")[1]);
  833. } catch (NumberFormatException e) {
  834. e.printStackTrace();
  835. return 10;
  836. }
  837.  
  838. }
  839.  
  840. }
  841.  
  842. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement