From cd45943cdd9225dd371d5ec4676862e30fef2725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=E1=BA=A7n=20Nguy=E1=BB=85n=20Ng=E1=BB=8Dc=20Quang?= <3d7777456@gmail.com> Date: Thu, 1 Feb 2024 22:14:05 +0700 Subject: [PATCH] generate missing methods in SerializedOfflinePlayer at runtime --- .../protocol/events/PacketEvent.java | 2 +- .../events/SerializedOfflinePlayer.java | 73 ++++++++++++++++++- .../events/SerializedOfflinePlayerTest.java | 2 +- 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/comphenix/protocol/events/PacketEvent.java b/src/main/java/com/comphenix/protocol/events/PacketEvent.java index df3f3c208..6c6022527 100644 --- a/src/main/java/com/comphenix/protocol/events/PacketEvent.java +++ b/src/main/java/com/comphenix/protocol/events/PacketEvent.java @@ -527,7 +527,7 @@ private void writeObject(ObjectOutputStream output) throws IOException { // Write the name of the player (or NULL if it's not set) Player player = getPlayer(); - output.writeObject(player != null ? new SerializedOfflinePlayer(player) : null); + output.writeObject(player != null ? SerializedOfflinePlayer.init(player) : null); } private void readObject(ObjectInputStream input) throws ClassNotFoundException, IOException { diff --git a/src/main/java/com/comphenix/protocol/events/SerializedOfflinePlayer.java b/src/main/java/com/comphenix/protocol/events/SerializedOfflinePlayer.java index 57713e190..3ecc54a51 100644 --- a/src/main/java/com/comphenix/protocol/events/SerializedOfflinePlayer.java +++ b/src/main/java/com/comphenix/protocol/events/SerializedOfflinePlayer.java @@ -51,8 +51,12 @@ import java.lang.reflect.Method; import java.time.Duration; import java.time.Instant; +import java.util.ArrayList; import java.util.Date; +import java.util.HashSet; +import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -61,7 +65,7 @@ * * @author Kristian */ -class SerializedOfflinePlayer implements OfflinePlayer, Serializable { +abstract class SerializedOfflinePlayer implements OfflinePlayer, Serializable { /** * Generated by Eclipse. @@ -84,11 +88,33 @@ class SerializedOfflinePlayer implements OfflinePlayer, Serializable { private long lastSeen; private static final Constructor> proxyPlayerConstructor = setupProxyPlayerConstructor(); + private static final Constructor extends SerializedOfflinePlayer> CLASS_CONSTRUCTOR = setupClassConstructor(); + + /** + * Initialize a serializable offline player object from another offline player. + *
+ * All other methods cause an exception.
+ *
+ * @param player - another offline player.
+ * @return A serializable offline player object.
+ */
+ public static SerializedOfflinePlayer init(OfflinePlayer player) {
+ try {
+ CLASS_CONSTRUCTOR.setAccessible(true);
+ return CLASS_CONSTRUCTOR.newInstance(player);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Cannot access reflection.", e);
+ } catch (InstantiationException e) {
+ throw new RuntimeException("Cannot instantiate object.", e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException("Error in invocation.", e);
+ }
+ }
/**
* Constructor used by serialization.
*/
- public SerializedOfflinePlayer() {
+ protected SerializedOfflinePlayer() {
// Do nothing
}
@@ -97,7 +123,7 @@ public SerializedOfflinePlayer() {
*
* @param offline - another player.
*/
- public SerializedOfflinePlayer(OfflinePlayer offline) {
+ protected SerializedOfflinePlayer(OfflinePlayer offline) {
this.name = offline.getName();
this.uuid = offline.getUniqueId();
this.firstPlayed = offline.getFirstPlayed();
@@ -342,6 +368,47 @@ public Player getProxyPlayer() {
}
}
+ private static Constructor extends SerializedOfflinePlayer> setupClassConstructor() {
+ final Method[] existingMethods = SerializedOfflinePlayer.class.getDeclaredMethods();
+ final Set