1
0
mirror of https://e.coding.net/circlecloud/YumCore.git synced 2024-11-22 01:48:50 +00:00

feat: 添加TellRaw发包模式 重构C兼容类

Signed-off-by: 502647092 <admin@yumc.pw>
This commit is contained in:
502647092 2017-01-21 14:38:47 +08:00
parent 12b9192aa3
commit 82ea829a73
3 changed files with 108 additions and 65 deletions

View File

@ -1,10 +1,5 @@
package pw.yumc.YumCore.bukkit.compatible; 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.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -12,6 +7,18 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.UUID; 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兼容类 * Bukkit兼容类
* *
@ -22,31 +29,34 @@ public class C {
private static Class<?> nmsChatSerializer; private static Class<?> nmsChatSerializer;
private static Class<?> nmsIChatBaseComponent; private static Class<?> nmsIChatBaseComponent;
private static Class<?> packetType; private static Class<?> packetType;
private static Class<?> packetActions;
private static Class<?> packetTitle;
private static Method chatSerializer;
private static Method getHandle; private static Method getHandle;
private static String version; private static String version;
private static boolean newversion;
private static Field playerConnection; private static Field playerConnection;
private static Method sendPacket; private static Method sendPacket;
public static boolean init;
static { static {
try { try {
version = getNMSVersion(); 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")); nmsChatSerializer = Class.forName(a(newversion ? "IChatBaseComponent$ChatSerializer" : "ChatSerializer"));
chatSerializer = nmsChatSerializer.getMethod("a", String.class);
nmsIChatBaseComponent = Class.forName(a("IChatBaseComponent")); nmsIChatBaseComponent = Class.forName(a("IChatBaseComponent"));
packetType = Class.forName(a("PacketPlayOutChat")); 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<?> typeCraftPlayer = Class.forName(b("entity.CraftPlayer"));
Class<?> typeNMSPlayer = Class.forName(a("EntityPlayer")); Class<?> typeNMSPlayer = Class.forName(a("EntityPlayer"));
Class<?> typePlayerConnection = Class.forName(a("PlayerConnection")); Class<?> typePlayerConnection = Class.forName(a("PlayerConnection"));
getHandle = typeCraftPlayer.getMethod("getHandle"); getHandle = typeCraftPlayer.getMethod("getHandle");
playerConnection = typeNMSPlayer.getField("playerConnection"); playerConnection = typeNMSPlayer.getField("playerConnection");
sendPacket = typePlayerConnection.getMethod("sendPacket", Class.forName(a("Packet"))); sendPacket = typePlayerConnection.getMethod("sendPacket", Class.forName(a("Packet")));
init = true;
} catch (Exception e) { } catch (Exception e) {
Log.warning(C.class.getSimpleName() + " 兼容性工具初始化失败 可能造成部分功能不可用!"); Log.warning("C 兼容性工具初始化失败 可能造成部分功能不可用!");
Log.d(e); Log.d(e);
} }
} }
@ -71,6 +81,33 @@ public class C {
return Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; 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 { public static class ActionBar {
private ActionBar() { private ActionBar() {
} }
@ -96,7 +133,7 @@ public class C {
* 需要显示的时间 * 需要显示的时间
*/ */
public static void broadcast(final String message, final int times) { public static void broadcast(final String message, final int times) {
new Thread(new Runnable() { Bukkit.getScheduler().runTaskAsynchronously(P.instance, new Runnable() {
@Override @Override
public void run() { public void run() {
int time = times; int time = times;
@ -106,13 +143,12 @@ public class C {
} }
try { try {
Thread.sleep(1000); Thread.sleep(1000);
} catch (InterruptedException e) { } catch (InterruptedException ignored) {
// Ignore
} }
time--; time--;
} while (time > 0); } while (time > 0);
} }
}).start(); });
} }
/** /**
@ -126,7 +162,7 @@ public class C {
* 需要显示的时间 * 需要显示的时间
*/ */
public static void broadcast(final World world, final String message, final int times) { 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 @Override
public void run() { public void run() {
int time = times; int time = times;
@ -138,14 +174,13 @@ public class C {
} }
try { try {
Thread.sleep(1000); Thread.sleep(1000);
} catch (InterruptedException e) { } catch (InterruptedException ignored) {
// Ignore
} }
time--; time--;
} while (time > 0); } while (time > 0);
} }
}).start(); });
} }
/** /**
@ -157,20 +192,7 @@ public class C {
* ActionBar信息 * ActionBar信息
*/ */
public static void send(org.bukkit.entity.Player receivingPacket, String msg) { public static void send(org.bukkit.entity.Player receivingPacket, String msg) {
Object packet; sendJson(receivingPacket, "{\"text\":\"" + ChatColor.translateAlternateColorCodes('&', JSONObject.escape(msg)) + "\"}", 2);
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);
}
} }
/** /**
@ -184,7 +206,7 @@ public class C {
* 需要显示的时间 * 需要显示的时间
*/ */
public static void send(final org.bukkit.entity.Player receivingPacket, final String msg, final int times) { 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 @Override
public void run() { public void run() {
int time = times; int time = times;
@ -192,13 +214,12 @@ public class C {
send(receivingPacket, msg); send(receivingPacket, msg);
try { try {
Thread.sleep(1000); Thread.sleep(1000);
} catch (InterruptedException e) { } catch (InterruptedException ignored) {
// Ignore
} }
time--; time--;
} while (time > 0); } while (time > 0);
} }
}).start(); });
} }
} }
@ -226,7 +247,7 @@ public class C {
} }
// getOnlinePlayers end // getOnlinePlayers end
} catch (Exception e) { } catch (Exception e) {
Log.warning(Player.class.getSimpleName() + "兼容性工具初始化失败 可能造成部分功能不可用!"); Log.warning("Player 兼容性工具初始化失败 可能造成部分功能不可用!");
} }
try { try {
// getOfflinePlayer start // getOfflinePlayer start
@ -285,6 +306,21 @@ public class C {
} }
public static class Title { 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() { private Title() {
} }
@ -353,7 +389,7 @@ public class C {
Object player = getHandle.invoke(recoverPlayer); Object player = getHandle.invoke(recoverPlayer);
Object connection = playerConnection.get(player); Object connection = playerConnection.get(player);
Object[] actions = packetActions.getEnumConstants(); 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); sendPacket.invoke(connection, packet);
} }
@ -399,21 +435,17 @@ public class C {
Object packet; Object packet;
// Send if set // Send if set
if ((fadeInTime != -1) && (fadeOutTime != -1) && (stayTime != -1)) { if ((fadeInTime != -1) && (fadeOutTime != -1) && (stayTime != -1)) {
packet = packetTitle.getConstructor(packetActions, nmsIChatBaseComponent, Integer.TYPE, Integer.TYPE, Integer.TYPE).newInstance(actions[2], packet = packetTitleSendConstructor.newInstance(actions[2], null, fadeInTime * 20, stayTime * 20, fadeOutTime * 20);
null,
fadeInTime * 20,
stayTime * 20,
fadeOutTime * 20);
sendPacket.invoke(connection, packet); sendPacket.invoke(connection, packet);
} }
// Send title // Send title
Object serialized = nmsChatSerializer.getMethod("a", String.class).invoke(null, "{\"text\":\"" + ChatColor.translateAlternateColorCodes('&', title) + "\"}"); Object serialized = chatSerializer.invoke(null, "{\"text\":\"" + ChatColor.translateAlternateColorCodes('&', title) + "\"}");
packet = packetTitle.getConstructor(packetActions, nmsIChatBaseComponent).newInstance(actions[0], serialized); packet = packetTitleSendConstructor.newInstance(actions[0], serialized);
sendPacket.invoke(connection, packet); sendPacket.invoke(connection, packet);
if (!"".equals(subtitle)) { if (!"".equals(subtitle)) {
// Send subtitle if present // Send subtitle if present
serialized = nmsChatSerializer.getMethod("a", String.class).invoke(null, "{\"text\":\"" + ChatColor.translateAlternateColorCodes('&', subtitle) + "\"}"); serialized = chatSerializer.invoke(null, "{\"text\":\"" + ChatColor.translateAlternateColorCodes('&', subtitle) + "\"}");
packet = packetTitle.getConstructor(packetActions, nmsIChatBaseComponent).newInstance(actions[1], serialized); packet = packetTitleSendConstructor.newInstance(actions[1], serialized);
sendPacket.invoke(connection, packet); sendPacket.invoke(connection, packet);
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -20,7 +20,7 @@ import pw.yumc.YumCore.bukkit.Log;
* @author * @author
*/ */
public abstract class ItemSerialize { public abstract class ItemSerialize {
static ItemSerialize itemSerialize = new Manual(); static ItemSerialize itemSerialize;
static { static {
try { try {
itemSerialize = new Automatic(); itemSerialize = new Automatic();

View File

@ -21,15 +21,18 @@ import pw.yumc.YumCore.bukkit.compatible.C;
*/ */
public class Tellraw implements Cloneable { public class Tellraw implements Cloneable {
private List<MessagePart> messageParts = new ArrayList<>(); private List<MessagePart> messageParts = new ArrayList<>();
private String cache;
static { static {
if (Bukkit.getVersion().contains("Paper") || Bukkit.getVersion().contains("Torch")) { if (Bukkit.getVersion().contains("Paper") || Bukkit.getVersion().contains("Torch")) {
Log.console("§c========== §4警 告 §c=========="); if (!C.init) {
Log.console("§a 当前服务器为 §6Paper §a或 §6Torch "); Log.console("§c========== §4警 告 §c==========");
Log.console("§c 异步命令会刷报错 §b不影响使用"); Log.console("§a 当前服务器为 §6Paper §a或 §6Torch ");
Log.console("§d 如果介意请使用原版 Spigot"); Log.console("§c 异步命令会刷报错 §b不影响使用");
Log.console("§e YUMC构建站: http://ci.yumc.pw/job/Spigot/"); Log.console("§d 如果介意请使用原版 Spigot");
Log.console("§c==========================="); 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) { public void send(final CommandSender sender) {
final String json = toJsonString(); final String json = toJsonString();
if (sender instanceof Player && json.getBytes().length < 32000) { 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 { } else {
sender.sendMessage(toOldMessageFormat()); sender.sendMessage(toOldMessageFormat());
} }
@ -231,7 +238,7 @@ public class Tellraw implements Cloneable {
* @param name * @param name
* 物品名称 * 物品名称
* @param item * @param item
* {@link ItemStack} * {@link ItemStack};
* @return {@link Tellraw} * @return {@link Tellraw}
*/ */
public Tellraw then(String name, ItemStack item) { public Tellraw then(String name, ItemStack item) {
@ -295,15 +302,18 @@ public class Tellraw implements Cloneable {
* @return Json串 * @return Json串
*/ */
public String toJsonString() { public String toJsonString() {
StringBuilder msg = new StringBuilder(); if (cache == null) {
msg.append("[\"\""); StringBuilder msg = new StringBuilder();
for (MessagePart messagePart : messageParts) { msg.append("[\"\"");
msg.append(","); for (MessagePart messagePart : messageParts) {
messagePart.writeJson(msg); msg.append(",");
messagePart.writeJson(msg);
}
msg.append("]");
cache = msg.toString();
Log.d(cache);
} }
msg.append("]"); return cache;
Log.debug(msg.toString());
return msg.toString();
} }
public Tellraw setMessageParts(List<MessagePart> messageParts) { public Tellraw setMessageParts(List<MessagePart> messageParts) {
@ -395,6 +405,7 @@ public class Tellraw implements Cloneable {
} else { } else {
messageParts.add(part); messageParts.add(part);
} }
cache = null;
return this; return this;
} }
} }