Skip to content

Commit 4224909

Browse files
committed
Fixed Bukkit ModApi on 1.20.6+
1 parent d5de4cf commit 4224909

File tree

1 file changed

+67
-26
lines changed

1 file changed

+67
-26
lines changed

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

Lines changed: 67 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package net.badlion.bukkitapi;
22

3-
import org.bukkit.Bukkit;
43
import org.bukkit.entity.Player;
54

65
import java.lang.reflect.Constructor;
@@ -19,13 +18,16 @@ public class BukkitPluginMessageSender extends AbstractBukkitPluginMessageSender
1918
private final Method sendPacketMethod;
2019

2120
private String versionSuffix;
21+
private String versionName;
2222

2323
private Constructor<?> packetPlayOutCustomPayloadConstructor;
2424
private Constructor<?> packetPlayOutMinecraftKeyConstructor;
25+
private Constructor<?> discardedPayloadConstructor;
2526
private Class<?> minecraftKeyClass;
2627
private Class<?> customPacketPayloadClass;
2728
private boolean useMinecraftKey;
2829
private boolean usePacketPayload;
30+
private boolean useDiscardedPayload;
2931

3032
// Bukkit 1.8+ support
3133
private Class<?> packetDataSerializerClass;
@@ -39,23 +41,29 @@ public BukkitPluginMessageSender(AbstractBukkitBadlionPlugin apiBukkit) {
3941
this.apiBukkit = apiBukkit;
4042

4143
// Get the v1_X_Y from the end of the package name, e.g. v_1_7_R4 or v_1_12_R1
42-
String packageName = Bukkit.getServer().getClass().getPackage().getName();
44+
String packageName = this.apiBukkit.getServer().getClass().getPackage().getName();
4345
String[] parts = packageName.split("\\.");
4446

4547
if (parts.length > 0) {
4648
String suffix = parts[parts.length - 1];
4749
if (!suffix.startsWith("v")) {
48-
throw new RuntimeException("Failed to find version for running Minecraft server, got suffix " + suffix);
50+
// 1.20.5+ support
51+
if ("craftbukkit".equals(suffix)) {
52+
suffix = "";
53+
} else {
54+
throw new RuntimeException("Failed to find version for running Minecraft server, got suffix " + suffix);
55+
}
4956
}
5057

5158
this.versionSuffix = suffix;
59+
this.versionName = this.apiBukkit.getServer().getVersion();
5260

53-
this.apiBukkit.getLogger().info("Found version " + this.versionSuffix);
61+
this.apiBukkit.getLogger().info("Found version " + this.versionSuffix + " (" + this.versionName + ")");
5462
}
5563

5664
// We need to use reflection because Bukkit by default handles plugin messages in a really silly way
5765
// Reflection stuff
58-
Class<?> craftPlayerClass = this.getClass("org.bukkit.craftbukkit." + this.versionSuffix + ".entity.CraftPlayer");
66+
Class<?> craftPlayerClass = this.getClass(this.versionSuffix == null || this.versionSuffix.isEmpty() ? "org.bukkit.craftbukkit.entity.CraftPlayer" : "org.bukkit.craftbukkit." + this.versionSuffix + ".entity.CraftPlayer");
5967
if (craftPlayerClass == null) {
6068
throw new RuntimeException("Failed to find CraftPlayer class");
6169
}
@@ -124,6 +132,16 @@ public BukkitPluginMessageSender(AbstractBukkitBadlionPlugin apiBukkit) {
124132
this.packetDataSerializerWriteBytesMethod = this.getMethod(this.packetDataSerializerClass, "c", byte[].class);
125133
this.packetPlayOutMinecraftKeyConstructor = this.getConstructor(this.minecraftKeyClass, String.class);
126134
this.usePacketPayload = true;
135+
136+
Class<?> discardedPayloadClass = this.getClass("net.minecraft.network.protocol.common.custom.DiscardedPayload");
137+
138+
if (discardedPayloadClass != null) {
139+
this.discardedPayloadConstructor = this.getConstructor(discardedPayloadClass, this.minecraftKeyClass, byteBufClass);
140+
141+
if (this.discardedPayloadConstructor != null) {
142+
this.useDiscardedPayload = true;
143+
}
144+
}
127145
}
128146

129147
if (this.packetPlayOutCustomPayloadConstructor == null) {
@@ -141,35 +159,47 @@ public BukkitPluginMessageSender(AbstractBukkitBadlionPlugin apiBukkit) {
141159
throw new RuntimeException("Failed to find CraftPlayer.getHandle()");
142160
}
143161

162+
Field playerConnectionField;
163+
144164
if (this.versionSuffix.contains("v1_17") || this.versionSuffix.contains("v1_18") || this.versionSuffix.contains("v1_19")) {
145-
this.playerConnectionField = this.getField(nmsPlayerClass, "b");
165+
playerConnectionField = this.getField(nmsPlayerClass, "b");
146166
} else {
147-
this.playerConnectionField = this.getField(nmsPlayerClass, "c");
167+
playerConnectionField = this.getField(nmsPlayerClass, "c");
168+
}
169+
170+
if (playerConnectionField == null) {
171+
playerConnectionField = this.getField(nmsPlayerClass, "connection");
148172
}
149173

150-
if (this.playerConnectionField == null) {
174+
if (playerConnectionField != null) {
175+
this.playerConnectionField = playerConnectionField;
176+
} else {
151177
throw new RuntimeException("Failed to find EntityPlayer.playerConnection");
152178
}
153179

154180
if (!this.versionSuffix.contains("v1_17")) {
155181
final Class<?> packet1_18Class = this.getClass("net.minecraft.network.protocol.Packet");
182+
Method sendPacketMethod;
156183

157184
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-
}
185+
sendPacketMethod = this.getMethod(playerConnectionClass.getSuperclass(), "b", packet1_18Class);
163186
} else {
164-
this.sendPacketMethod = this.getMethod(playerConnectionClass, "a", packet1_18Class);
187+
sendPacketMethod = this.getMethod(playerConnectionClass, "a", packet1_18Class);
188+
}
165189

166-
if (this.sendPacketMethod == null) {
167-
throw new RuntimeException("Failed to find PlayerConnection.a(Packet)");
168-
}
190+
if (sendPacketMethod == null) {
191+
sendPacketMethod = this.getMethod(playerConnectionClass.getSuperclass(), "send", packet1_18Class);
192+
}
193+
194+
if (sendPacketMethod != null) {
195+
this.sendPacketMethod = sendPacketMethod;
196+
} else {
197+
throw new RuntimeException("Failed to find PlayerConnection.send(Packet)");
169198
}
170199

171200
} else {
172201
this.sendPacketMethod = this.getMethod(playerConnectionClass, "sendPacket");
202+
173203
if (this.sendPacketMethod == null) {
174204
throw new RuntimeException("Failed to find PlayerConnection.sendPacket()");
175205
}
@@ -184,17 +214,28 @@ public void sendPluginMessagePacket(Player player, String channel, Object data)
184214
// Newer MC version, setup ByteBuf object
185215
if (this.packetDataSerializerClass != null) {
186216
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-
}
217+
Object payload;
218+
219+
if (this.useDiscardedPayload) {
220+
// 1.20.5+
221+
payload = this.discardedPayloadConstructor.newInstance(
222+
this.packetPlayOutMinecraftKeyConstructor.newInstance(channel),
223+
this.wrappedBufferMethod.invoke(null, data)
224+
);
225+
} else {
226+
// 1.20.2 - 1.20.4
227+
payload = Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{this.customPacketPayloadClass}, (proxy, method, args) -> {
228+
if (method.getReturnType().equals(BukkitPluginMessageSender.this.minecraftKeyClass)) {
229+
return this.packetPlayOutMinecraftKeyConstructor.newInstance(channel);
230+
} else if (args.length == 1 && this.packetDataSerializerClass.isAssignableFrom(args[0].getClass())) {
231+
this.packetDataSerializerWriteBytesMethod.invoke(args[0], data);
232+
return null;
233+
}
194234

195-
return null;
196-
});
235+
return null;
236+
});
197237

238+
}
198239
packet = this.packetPlayOutCustomPayloadConstructor.newInstance(payload);
199240
} else {
200241
Object byteBuf = this.wrappedBufferMethod.invoke(null, data);

0 commit comments

Comments
 (0)