同一线程:https://bukkit.org/threads/tablist-objectives.480313/
首先,我将从以下内容开始: 为什么我不使用Bukkit API来创建乐谱?
Java思考问题:
所以我的问题是,如果我使用Java Reflection创建标签列表目标,那么为什么调用时它会引发IllegalArgumentException?
之所以这样思考,是因为许多用户仍在使用Bukkit 1.8,并且应该受到支持。但这适用于1.8及更高版本。
public void updatePingTab(Player player) {
String bukkitVersion = Bukkit.getVersion();
Class<?> criteria = null;
if (getPackageVersion().contains("1_8_R1")) {
criteria = getNMSClass("EnumScoreboardHealthDisplay");
} else {
criteria = getNMSClass("IScoreboardCriteria$EnumScoreboardHealthDisplay");
}
Class<?> pPlayObj = getNMSClass("PacketPlayOutScoreboardObjective");
Object playObjIns = pPlayObj.getConstructor().newInstance();
setField(playObjIns, "a", "ms");
setField(playObjIns, "d", 0);
if (bukkitVersion.contains("1.13") || bukkitVersion.contains("1.14")) {
setField(playObjIns, "b", getAsIChatBaseComponent("PingTab"));
} else {
setField(playObjIns, "b", "PingTab");
}
setField(playObjIns, "c", criteria.getEnumConstants()[0]);
Constructor<?> score = getNMSClass("ScoreboardScore")
.getConstructor(getNMSClass("Scoreboard"),
getNMSClass("ScoreboardObjective"), String.class);
Method scoreSet = getNMSClass("ScoreboardScore").getMethod("setScore", int.class);
scoreSet.setAccessible(true);
//console error ˇ
scoreSet.invoke(score.newInstance(player.getScoreboard(), pPlayObj,
player.getName().length() <= 14 ? player.getName()
: player.getName().substring(0, 14)), pingPlayer(player));//console error ^
sendPacket(player, playObjIns);
}
public static Class<?> getNMSClass(String name) throws ClassNotFoundException {
return Class.forName("net.minecraft.server." + getPackageVersion() + "." + name);
}
public static void sendPacket(Player player, Object packet) {
try {
Object playerHandle = getNMSPlayer(player);
Object playerConnection = getFieldObject(playerHandle, playerHandle.getClass().getField("playerConnection"));
playerConnection.getClass().getMethod("sendPacket", getNMSClass("Packet")).invoke(playerConnection, packet);
} catch (Throwable t) {
t.printStackTrace();
}
}
public static String getPackageVersion() {
return Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
}
public static Object getFieldObject(Object object, Field field) throws Throwable {
return field.get(object);
}
public static Object getNMSPlayer(Player p) throws Throwable {
return p.getClass().getMethod("getHandle", new Class[0]).invoke(p, new Object[0]);
}
public static void setField(Object object, String fieldName, Object fieldValue) throws Throwable {
setField(object, fieldName, fieldValue, true);
}
public static void setField(Object object, String fieldName, Object fieldValue, boolean declared) throws Throwable {
Field field;
if (declared) {
field = object.getClass().getDeclaredField(fieldName);
} else {
field = object.getClass().getField(fieldName);
}
field.setAccessible(true);
field.set(object, fieldValue);
}
public static Object getAsIChatBaseComponent(String name) throws Exception {
Class<?> iChatBaseComponent = ReflectionUtils.getNMSClass("IChatBaseComponent");
Method m = iChatBaseComponent.getDeclaredClasses()[0].getMethod("a", String.class);
return m.invoke(iChatBaseComponent, "{\"text\":\"" + name + "\"}");
}
结果应如下所示: https://imgur.com/gallery/AIHO80M
控制台错误:
[13:16:53 WARN]: java.lang.IllegalArgumentException: argument type mismatch
[13:16:53 WARN]: at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
[13:16:53 WARN]: at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
[13:16:53 WARN]: at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
[13:16:53 WARN]: at java.lang.reflect.Constructor.newInstance(Unknown Source)
[13:16:53 WARN]: at hu.montlikadani.tablist.Objects$1.run(Objects.java:108)
[13:16:53 WARN]: at org.bukkit.craftbukkit.v1_14_R1.scheduler.CraftTask.run(CraftTask.java:84)
[13:16:53 WARN]: at org.bukkit.craftbukkit.v1_14_R1.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:452)
[13:16:53 WARN]: at net.minecraft.server.v1_14_R1.MinecraftServer.b(MinecraftServer.java:1147)
[13:16:53 WARN]: at net.minecraft.server.v1_14_R1.DedicatedServer.b(DedicatedServer.java:420)
[13:16:53 WARN]: at net.minecraft.server.v1_14_R1.MinecraftServer.a(MinecraftServer.java:1074)
[13:16:53 WARN]: at net.minecraft.server.v1_14_R1.MinecraftServer.run(MinecraftServer.java:918)
[13:16:53 WARN]: at java.lang.Thread.run(Unknown Source)
答案 0 :(得分:0)
ScoreboardScore
类的构造函数需要参数Scoreboard, ScoreboardObjective, String
。但是使用player.getScoreboard(), pPlayObj, playerName
,您将使用Scoreboard, Class<?>, String
创建一个实例。