Skip to content

Commit 166f091

Browse files
committed
Fixed ModApi not working on 1.20.2 due to protocol class changes
1 parent 708d2af commit 166f091

File tree

1 file changed

+63
-19
lines changed

1 file changed

+63
-19
lines changed

bukkit-1.17/src/main/java/net/badlion/bukkitapi/BukkitPluginMessageSender.java

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55

66
import java.lang.reflect.Constructor;
77
import java.lang.reflect.Field;
8-
import java.lang.reflect.InvocationTargetException;
98
import java.lang.reflect.Method;
9+
import java.lang.reflect.Proxy;
1010
import java.util.Arrays;
11+
import java.util.logging.Level;
1112

1213
public class BukkitPluginMessageSender extends AbstractBukkitPluginMessageSender {
1314

@@ -21,10 +22,14 @@ public class BukkitPluginMessageSender extends AbstractBukkitPluginMessageSender
2122

2223
private Constructor<?> packetPlayOutCustomPayloadConstructor;
2324
private Constructor<?> packetPlayOutMinecraftKeyConstructor;
25+
private Class<?> minecraftKeyClass;
26+
private Class<?> customPacketPayloadClass;
2427
private boolean useMinecraftKey;
28+
private boolean usePacketPayload;
2529

2630
// Bukkit 1.8+ support
2731
private Class<?> packetDataSerializerClass;
32+
private Method packetDataSerializerWriteBytesMethod;
2833
private Constructor<?> packetDataSerializerConstructor;
2934

3035
private Method wrappedBufferMethod;
@@ -67,7 +72,11 @@ public BukkitPluginMessageSender(AbstractBukkitBadlionPlugin apiBukkit) {
6772

6873
Class<?> packetPlayOutCustomPayloadClass = this.getClass("net.minecraft.network.protocol.game.PacketPlayOutCustomPayload");
6974
if (packetPlayOutCustomPayloadClass == null) {
70-
throw new RuntimeException("Failed to find PacketPlayOutCustomPayload class");
75+
packetPlayOutCustomPayloadClass = this.getClass("net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket");
76+
77+
if (packetPlayOutCustomPayloadClass == null) {
78+
throw new RuntimeException("Failed to find PacketPlayOutCustomPayload class");
79+
}
7180
}
7281

7382
this.packetPlayOutCustomPayloadConstructor = this.getConstructor(packetPlayOutCustomPayloadClass, String.class, byte[].class);
@@ -102,16 +111,27 @@ public BukkitPluginMessageSender(AbstractBukkitBadlionPlugin apiBukkit) {
102111
// If we made it this far in theory we are on at least 1.8
103112
this.packetPlayOutCustomPayloadConstructor = this.getConstructor(packetPlayOutCustomPayloadClass, String.class, this.packetDataSerializerClass);
104113
if (this.packetPlayOutCustomPayloadConstructor == null) {
105-
Class<?> minecraftKeyClass = this.getClass("net.minecraft.resources.MinecraftKey");
114+
this.minecraftKeyClass = this.getClass("net.minecraft.resources.MinecraftKey");
106115

107116
// Fix for Paper in newer versions
108-
this.packetPlayOutCustomPayloadConstructor = this.getConstructor(packetPlayOutCustomPayloadClass, minecraftKeyClass, this.packetDataSerializerClass);
117+
this.packetPlayOutCustomPayloadConstructor = this.getConstructor(packetPlayOutCustomPayloadClass, this.minecraftKeyClass, this.packetDataSerializerClass);
109118

110119
if (this.packetPlayOutCustomPayloadConstructor == null) {
111-
throw new RuntimeException("Failed to find PacketPlayOutCustomPayload constructor 2x");
120+
this.customPacketPayloadClass = this.getClass("net.minecraft.network.protocol.common.custom.CustomPacketPayload");
121+
122+
if (this.customPacketPayloadClass != null) {
123+
this.packetPlayOutCustomPayloadConstructor = this.getConstructor(packetPlayOutCustomPayloadClass, this.customPacketPayloadClass);
124+
this.packetDataSerializerWriteBytesMethod = this.getMethod(this.packetDataSerializerClass, "c", byte[].class);
125+
this.packetPlayOutMinecraftKeyConstructor = this.getConstructor(this.minecraftKeyClass, String.class);
126+
this.usePacketPayload = true;
127+
}
128+
129+
if (this.packetPlayOutCustomPayloadConstructor == null) {
130+
throw new RuntimeException("Failed to find PacketPlayOutCustomPayload constructor 2x");
131+
}
112132
} else {
113133
this.useMinecraftKey = true;
114-
this.packetPlayOutMinecraftKeyConstructor = this.getConstructor(minecraftKeyClass, String.class);
134+
this.packetPlayOutMinecraftKeyConstructor = this.getConstructor(this.minecraftKeyClass, String.class);
115135
}
116136
}
117137
}
@@ -134,9 +154,18 @@ public BukkitPluginMessageSender(AbstractBukkitBadlionPlugin apiBukkit) {
134154
if (!this.versionSuffix.contains("v1_17")) {
135155
final Class<?> packet1_18Class = this.getClass("net.minecraft.network.protocol.Packet");
136156

137-
this.sendPacketMethod = this.getMethod(playerConnectionClass, "a", packet1_18Class);
138-
if (this.sendPacketMethod == null) {
139-
throw new RuntimeException("Failed to find PlayerConnection.a(Packet)");
157+
if (this.usePacketPayload) {
158+
this.sendPacketMethod = this.getMethod(playerConnectionClass.getSuperclass(), "b", packet1_18Class);
159+
160+
if (this.sendPacketMethod == null) {
161+
throw new RuntimeException("Failed to find PlayerConnection.b(Packet)");
162+
}
163+
} else {
164+
this.sendPacketMethod = this.getMethod(playerConnectionClass, "a", packet1_18Class);
165+
166+
if (this.sendPacketMethod == null) {
167+
throw new RuntimeException("Failed to find PlayerConnection.a(Packet)");
168+
}
140169
}
141170

142171
} else {
@@ -151,16 +180,32 @@ public BukkitPluginMessageSender(AbstractBukkitBadlionPlugin apiBukkit) {
151180
public void sendPluginMessagePacket(Player player, String channel, Object data) {
152181
try {
153182
Object packet;
183+
154184
// Newer MC version, setup ByteBuf object
155185
if (this.packetDataSerializerClass != null) {
156-
Object byteBuf = this.wrappedBufferMethod.invoke(null, data);
157-
Object packetDataSerializer = this.packetDataSerializerConstructor.newInstance(byteBuf);
158-
159-
if (this.useMinecraftKey) {
160-
Object key = this.packetPlayOutMinecraftKeyConstructor.newInstance(channel);
161-
packet = this.packetPlayOutCustomPayloadConstructor.newInstance(key, packetDataSerializer);
186+
if (this.usePacketPayload) {
187+
Object payload = Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{this.customPacketPayloadClass}, (proxy, method, args) -> {
188+
if (method.getReturnType().equals(BukkitPluginMessageSender.this.minecraftKeyClass)) {
189+
return this.packetPlayOutMinecraftKeyConstructor.newInstance(channel);
190+
} else if (args.length == 1 && this.packetDataSerializerClass.isAssignableFrom(args[0].getClass())) {
191+
this.packetDataSerializerWriteBytesMethod.invoke(args[0], data);
192+
return null;
193+
}
194+
195+
return null;
196+
});
197+
198+
packet = this.packetPlayOutCustomPayloadConstructor.newInstance(payload);
162199
} else {
163-
packet = this.packetPlayOutCustomPayloadConstructor.newInstance(channel, packetDataSerializer);
200+
Object byteBuf = this.wrappedBufferMethod.invoke(null, data);
201+
Object packetDataSerializer = this.packetDataSerializerConstructor.newInstance(byteBuf);
202+
203+
if (this.useMinecraftKey) {
204+
Object key = this.packetPlayOutMinecraftKeyConstructor.newInstance(channel);
205+
packet = this.packetPlayOutCustomPayloadConstructor.newInstance(key, packetDataSerializer);
206+
} else {
207+
packet = this.packetPlayOutCustomPayloadConstructor.newInstance(channel, packetDataSerializer);
208+
}
164209
}
165210
} else {
166211
// Work our magic to make the packet
@@ -172,9 +217,8 @@ public void sendPluginMessagePacket(Player player, String channel, Object data)
172217
Object playerConnection = this.playerConnectionField.get(nmsPlayer);
173218
this.sendPacketMethod.invoke(playerConnection, packet);
174219

175-
} catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
176-
this.apiBukkit.getLogger().severe("Failed to send BLC mod packet");
177-
e.printStackTrace();
220+
} catch (Throwable throwable) {
221+
this.apiBukkit.getLogger().log(Level.SEVERE, "Failed to send BLC mod packet", throwable);
178222
}
179223
}
180224

0 commit comments

Comments
 (0)