mercredi 14 août 2019

(Bukkit) Tablist objectives

Same thread: https://bukkit.org/threads/tablist-objectives.480313/

First, I will start with: Why don't I use the Bukkit API to create a score?

  • Because it has a lot of problems, such as not appearing to some users.
  • The object update stops accidentally while the scheduler task is running.
  • It does not appear at all (no method or scheduler query error).

Java Reflections problem:

  • The query is slower, but the result is satisfactory.
  • There are no accidental freezes during the upgrade
  • It appears correctly for all players

So my problem is, if I use Java Reflection for creating tablist objective then why does it throw IllegalArgumentException when invoke?

This reflection is made because many users are still using Bukkit 1.8 and should be supported. But this is for versions 1.8 and above.

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 + "\"}");
}

The results should look like this: https://imgur.com/gallery/AIHO80M

The console error:

[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)





Aucun commentaire:

Enregistrer un commentaire