diff --git a/src/main/java/pw/yumc/YumCore/bukkit/compatible/C.java b/src/main/java/pw/yumc/YumCore/bukkit/compatible/C.java index 80b2f51..b2dc923 100644 --- a/src/main/java/pw/yumc/YumCore/bukkit/compatible/C.java +++ b/src/main/java/pw/yumc/YumCore/bukkit/compatible/C.java @@ -1,10 +1,5 @@ package pw.yumc.YumCore.bukkit.compatible; -import com.google.common.base.Charsets; -import org.bukkit.*; -import org.json.simple.JSONObject; -import pw.yumc.YumCore.bukkit.Log; - import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -12,6 +7,18 @@ import java.util.Arrays; import java.util.Collection; import java.util.UUID; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.OfflinePlayer; +import org.bukkit.Server; +import org.bukkit.World; +import org.json.simple.JSONObject; + +import com.google.common.base.Charsets; + +import pw.yumc.YumCore.bukkit.Log; +import pw.yumc.YumCore.bukkit.P; + /** * Bukkit兼容类 * @@ -22,31 +29,34 @@ public class C { private static Class nmsChatSerializer; private static Class nmsIChatBaseComponent; private static Class packetType; - private static Class packetActions; - private static Class packetTitle; + private static Method chatSerializer; private static Method getHandle; private static String version; + private static boolean newversion; + private static Field playerConnection; private static Method sendPacket; + + public static boolean init; static { try { version = getNMSVersion(); - boolean newversion = Integer.parseInt(version.split("_")[1]) > 7; + newversion = Integer.parseInt(version.split("_")[1]) > 7; nmsChatSerializer = Class.forName(a(newversion ? "IChatBaseComponent$ChatSerializer" : "ChatSerializer")); + chatSerializer = nmsChatSerializer.getMethod("a", String.class); nmsIChatBaseComponent = Class.forName(a("IChatBaseComponent")); packetType = Class.forName(a("PacketPlayOutChat")); - packetActions = Class.forName(a(newversion ? "PacketPlayOutTitle$EnumTitleAction" : "EnumTitleAction")); - packetTitle = Class.forName(a("PacketPlayOutTitle")); Class typeCraftPlayer = Class.forName(b("entity.CraftPlayer")); Class typeNMSPlayer = Class.forName(a("EntityPlayer")); Class typePlayerConnection = Class.forName(a("PlayerConnection")); getHandle = typeCraftPlayer.getMethod("getHandle"); playerConnection = typeNMSPlayer.getField("playerConnection"); sendPacket = typePlayerConnection.getMethod("sendPacket", Class.forName(a("Packet"))); + init = true; } catch (Exception e) { - Log.warning(C.class.getSimpleName() + " 兼容性工具初始化失败 可能造成部分功能不可用!"); + Log.warning("C 兼容性工具初始化失败 可能造成部分功能不可用!"); Log.d(e); } } @@ -71,6 +81,33 @@ public class C { return Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; } + /** + * 给玩家发送Json消息 + * + * @param receivingPacket + * 接受信息的玩家 + * @param json + * Json信息 + * @param type + * 类型(0=>消息 2=>ActionBar) + */ + public static void sendJson(org.bukkit.entity.Player receivingPacket, String json, int type) { + Object packet; + try { + Object serialized = nmsChatSerializer.getMethod("a", String.class).invoke(null, json); + if (!version.contains("1_7")) { + packet = packetType.getConstructor(nmsIChatBaseComponent, byte.class).newInstance(serialized, (byte) type); + } else { + packet = packetType.getConstructor(nmsIChatBaseComponent, int.class).newInstance(serialized, type); + } + Object player = getHandle.invoke(receivingPacket); + Object connection = playerConnection.get(player); + sendPacket.invoke(connection, packet); + } catch (Exception ex) { + Log.d("Json发包错误 " + version, ex); + } + } + public static class ActionBar { private ActionBar() { } @@ -96,7 +133,7 @@ public class C { * 需要显示的时间 */ public static void broadcast(final String message, final int times) { - new Thread(new Runnable() { + Bukkit.getScheduler().runTaskAsynchronously(P.instance, new Runnable() { @Override public void run() { int time = times; @@ -106,13 +143,12 @@ public class C { } try { Thread.sleep(1000); - } catch (InterruptedException e) { - // Ignore + } catch (InterruptedException ignored) { } time--; } while (time > 0); } - }).start(); + }); } /** @@ -126,7 +162,7 @@ public class C { * 需要显示的时间 */ public static void broadcast(final World world, final String message, final int times) { - new Thread(new Runnable() { + Bukkit.getScheduler().runTaskAsynchronously(P.instance, new Runnable() { @Override public void run() { int time = times; @@ -138,14 +174,13 @@ public class C { } try { Thread.sleep(1000); - } catch (InterruptedException e) { - // Ignore + } catch (InterruptedException ignored) { } time--; } while (time > 0); } - }).start(); + }); } /** @@ -157,20 +192,7 @@ public class C { * ActionBar信息 */ public static void send(org.bukkit.entity.Player receivingPacket, String msg) { - Object packet; - try { - Object serialized = nmsChatSerializer.getMethod("a", String.class).invoke(null, "{\"text\":\"" + ChatColor.translateAlternateColorCodes('&', JSONObject.escape(msg)) + "\"}"); - if (!version.contains("1_7")) { - packet = packetType.getConstructor(nmsIChatBaseComponent, byte.class).newInstance(serialized, (byte) 2); - } else { - packet = packetType.getConstructor(nmsIChatBaseComponent, int.class).newInstance(serialized, 2); - } - Object player = getHandle.invoke(receivingPacket); - Object connection = playerConnection.get(player); - sendPacket.invoke(connection, packet); - } catch (Exception ex) { - Log.d("ActionBar发包错误 " + version, ex); - } + sendJson(receivingPacket, "{\"text\":\"" + ChatColor.translateAlternateColorCodes('&', JSONObject.escape(msg)) + "\"}", 2); } /** @@ -184,7 +206,7 @@ public class C { * 需要显示的时间 */ public static void send(final org.bukkit.entity.Player receivingPacket, final String msg, final int times) { - new Thread(new Runnable() { + Bukkit.getScheduler().runTaskAsynchronously(P.instance, new Runnable() { @Override public void run() { int time = times; @@ -192,13 +214,12 @@ public class C { send(receivingPacket, msg); try { Thread.sleep(1000); - } catch (InterruptedException e) { - // Ignore + } catch (InterruptedException ignored) { } time--; } while (time > 0); } - }).start(); + }); } } @@ -226,7 +247,7 @@ public class C { } // getOnlinePlayers end } catch (Exception e) { - Log.warning(Player.class.getSimpleName() + "兼容性工具初始化失败 可能造成部分功能不可用!"); + Log.warning("Player 兼容性工具初始化失败 可能造成部分功能不可用!"); } try { // getOfflinePlayer start @@ -285,6 +306,21 @@ public class C { } public static class Title { + private static Class packetActions; + private static Class packetTitle; + private static Constructor packetTitleSendConstructor; + private static Constructor packetTitleSetTimeConstructor; + static { + try { + packetActions = Class.forName(a(newversion ? "PacketPlayOutTitle$EnumTitleAction" : "EnumTitleAction")); + packetTitle = Class.forName(a("PacketPlayOutTitle")); + packetTitleSendConstructor = packetTitle.getConstructor(packetActions, nmsIChatBaseComponent); + packetTitleSetTimeConstructor = packetTitle.getConstructor(packetActions, nmsIChatBaseComponent, Integer.TYPE, Integer.TYPE, Integer.TYPE); + } catch (Exception ignore) { + Log.warning("Title 兼容性工具初始化失败 可能造成部分功能不可用!"); + } + } + private Title() { } @@ -353,7 +389,7 @@ public class C { Object player = getHandle.invoke(recoverPlayer); Object connection = playerConnection.get(player); Object[] actions = packetActions.getEnumConstants(); - Object packet = packetTitle.getConstructor(packetActions, nmsIChatBaseComponent).newInstance(actions[4], null); + Object packet = packetTitleSendConstructor.newInstance(actions[4], null); sendPacket.invoke(connection, packet); } @@ -399,21 +435,17 @@ public class C { Object packet; // Send if set if ((fadeInTime != -1) && (fadeOutTime != -1) && (stayTime != -1)) { - packet = packetTitle.getConstructor(packetActions, nmsIChatBaseComponent, Integer.TYPE, Integer.TYPE, Integer.TYPE).newInstance(actions[2], - null, - fadeInTime * 20, - stayTime * 20, - fadeOutTime * 20); + packet = packetTitleSendConstructor.newInstance(actions[2], null, fadeInTime * 20, stayTime * 20, fadeOutTime * 20); sendPacket.invoke(connection, packet); } // Send title - Object serialized = nmsChatSerializer.getMethod("a", String.class).invoke(null, "{\"text\":\"" + ChatColor.translateAlternateColorCodes('&', title) + "\"}"); - packet = packetTitle.getConstructor(packetActions, nmsIChatBaseComponent).newInstance(actions[0], serialized); + Object serialized = chatSerializer.invoke(null, "{\"text\":\"" + ChatColor.translateAlternateColorCodes('&', title) + "\"}"); + packet = packetTitleSendConstructor.newInstance(actions[0], serialized); sendPacket.invoke(connection, packet); if (!"".equals(subtitle)) { // Send subtitle if present - serialized = nmsChatSerializer.getMethod("a", String.class).invoke(null, "{\"text\":\"" + ChatColor.translateAlternateColorCodes('&', subtitle) + "\"}"); - packet = packetTitle.getConstructor(packetActions, nmsIChatBaseComponent).newInstance(actions[1], serialized); + serialized = chatSerializer.invoke(null, "{\"text\":\"" + ChatColor.translateAlternateColorCodes('&', subtitle) + "\"}"); + packet = packetTitleSendConstructor.newInstance(actions[1], serialized); sendPacket.invoke(connection, packet); } } catch (Exception e) { diff --git a/src/main/java/pw/yumc/YumCore/tellraw/ItemSerialize.java b/src/main/java/pw/yumc/YumCore/tellraw/ItemSerialize.java index b898129..a536301 100644 --- a/src/main/java/pw/yumc/YumCore/tellraw/ItemSerialize.java +++ b/src/main/java/pw/yumc/YumCore/tellraw/ItemSerialize.java @@ -20,7 +20,7 @@ import pw.yumc.YumCore.bukkit.Log; * @author 喵♂呜 */ public abstract class ItemSerialize { - static ItemSerialize itemSerialize = new Manual(); + static ItemSerialize itemSerialize; static { try { itemSerialize = new Automatic(); diff --git a/src/main/java/pw/yumc/YumCore/tellraw/Tellraw.java b/src/main/java/pw/yumc/YumCore/tellraw/Tellraw.java index df1405d..2b4dfab 100644 --- a/src/main/java/pw/yumc/YumCore/tellraw/Tellraw.java +++ b/src/main/java/pw/yumc/YumCore/tellraw/Tellraw.java @@ -21,15 +21,18 @@ import pw.yumc.YumCore.bukkit.compatible.C; */ public class Tellraw implements Cloneable { private List messageParts = new ArrayList<>(); + private String cache; static { if (Bukkit.getVersion().contains("Paper") || Bukkit.getVersion().contains("Torch")) { - Log.console("§c========== §4警 告 §c=========="); - Log.console("§a 当前服务器为 §6Paper §a或 §6Torch "); - Log.console("§c 异步命令会刷报错 §b不影响使用"); - Log.console("§d 如果介意请使用原版 Spigot"); - Log.console("§e YUMC构建站: http://ci.yumc.pw/job/Spigot/"); - Log.console("§c==========================="); + if (!C.init) { + Log.console("§c========== §4警 告 §c=========="); + Log.console("§a 当前服务器为 §6Paper §a或 §6Torch "); + Log.console("§c 异步命令会刷报错 §b不影响使用"); + Log.console("§d 如果介意请使用原版 Spigot"); + Log.console("§e YUMC构建站: http://ci.yumc.pw/job/Spigot/"); + Log.console("§c==========================="); + } } } @@ -172,7 +175,11 @@ public class Tellraw implements Cloneable { public void send(final CommandSender sender) { final String json = toJsonString(); if (sender instanceof Player && json.getBytes().length < 32000) { - Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + sender.getName() + " " + json); + if (C.init) { + C.sendJson((Player) sender, json, 0); + } else { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + sender.getName() + " " + json); + } } else { sender.sendMessage(toOldMessageFormat()); } @@ -231,7 +238,7 @@ public class Tellraw implements Cloneable { * @param name * 物品名称 * @param item - * {@link ItemStack} + * {@link ItemStack}; * @return {@link Tellraw} */ public Tellraw then(String name, ItemStack item) { @@ -295,15 +302,18 @@ public class Tellraw implements Cloneable { * @return Json串 */ public String toJsonString() { - StringBuilder msg = new StringBuilder(); - msg.append("[\"\""); - for (MessagePart messagePart : messageParts) { - msg.append(","); - messagePart.writeJson(msg); + if (cache == null) { + StringBuilder msg = new StringBuilder(); + msg.append("[\"\""); + for (MessagePart messagePart : messageParts) { + msg.append(","); + messagePart.writeJson(msg); + } + msg.append("]"); + cache = msg.toString(); + Log.d(cache); } - msg.append("]"); - Log.debug(msg.toString()); - return msg.toString(); + return cache; } public Tellraw setMessageParts(List messageParts) { @@ -395,6 +405,7 @@ public class Tellraw implements Cloneable { } else { messageParts.add(part); } + cache = null; return this; } }