@@ -13,30 +13,29 @@ public class BukkitPluginMessageSender extends AbstractBukkitPluginMessageSender
1313
1414 private final AbstractBukkitBadlionPlugin apiBukkit ;
1515
16- private final Method getHandleMethod ;
17- private final Field playerConnectionField ;
18- private final Method sendPacketMethod ;
19-
2016 private String versionSuffix ;
21- private String versionName ;
2217
23- private Constructor <?> packetPlayOutCustomPayloadConstructor ;
24- private Constructor <?> packetPlayOutMinecraftKeyConstructor ;
25- private Constructor <?> discardedPayloadConstructor ;
26- private Method resourceLocationParseMethod ;
18+ private Class <?> packetDataSerializerClass ;
2719 private Class <?> minecraftKeyClass ;
2820 private Class <?> customPacketPayloadClass ;
29- private boolean useMinecraftKey ;
30- private boolean usePacketPayload ;
31- private boolean useDiscardedPayload ;
3221
33- // Bukkit 1.8+ support
34- private Class <?> packetDataSerializerClass ;
35- private Method packetDataSerializerWriteBytesMethod ;
22+ private Constructor <?> packetPlayOutCustomPayloadConstructor ;
3623 private Constructor <?> packetDataSerializerConstructor ;
24+ private Constructor <?> packetPlayOutMinecraftKeyConstructor ;
25+ private Constructor <?> discardedPayloadConstructor ;
3726
27+ private Method sendCustomPayloadMethod ;
3828 private Method wrappedBufferMethod ;
29+ private Method packetDataSerializerWriteBytesMethod ;
30+ private Method resourceLocationParseMethod ;
31+ private Method getHandleMethod ;
32+ private Method sendPacketMethod ;
3933
34+ private Field playerConnectionField ;
35+
36+ private boolean useMinecraftKey ;
37+ private boolean usePacketPayload ;
38+ private boolean useDiscardedPayload ;
4039
4140 public BukkitPluginMessageSender (AbstractBukkitBadlionPlugin apiBukkit ) {
4241 this .apiBukkit = apiBukkit ;
@@ -49,7 +48,6 @@ public BukkitPluginMessageSender(AbstractBukkitBadlionPlugin apiBukkit) {
4948 String suffix = parts [parts .length - 1 ];
5049 if (!suffix .startsWith ("v" )) {
5150 // 1.20.5+ support
52- // TODO: In 1.20.5+, the private method `CraftPlayer.sendCustomPayload(ResourceLocation, byte[])` should do the trick and handle all future versions
5351 if ("craftbukkit" .equals (suffix )) {
5452 suffix = "" ;
5553 } else {
@@ -58,9 +56,10 @@ public BukkitPluginMessageSender(AbstractBukkitBadlionPlugin apiBukkit) {
5856 }
5957
6058 this .versionSuffix = suffix ;
61- this .versionName = this .apiBukkit .getServer ().getVersion ();
6259
63- this .apiBukkit .getLogger ().info ("Found version " + this .versionSuffix + " (" + this .versionName + ")" );
60+ String versionName = this .apiBukkit .getServer ().getVersion ();
61+
62+ this .apiBukkit .getLogger ().info ("Found version " + this .versionSuffix + " (" + versionName + ")" );
6463 }
6564
6665 // We need to use reflection because Bukkit by default handles plugin messages in a really silly way
@@ -70,6 +69,26 @@ public BukkitPluginMessageSender(AbstractBukkitBadlionPlugin apiBukkit) {
7069 throw new RuntimeException ("Failed to find CraftPlayer class" );
7170 }
7271
72+ // Paper method added in 1.20.2+, hopefully should never change
73+ this .minecraftKeyClass = this .getClass ("net.minecraft.resources.MinecraftKey" );
74+ if (this .minecraftKeyClass != null ) {
75+ this .sendCustomPayloadMethod = this .getMethod (craftPlayerClass , "sendCustomPayload" , this .minecraftKeyClass , byte [].class );
76+
77+ if (this .sendCustomPayloadMethod != null ) {
78+ this .packetPlayOutMinecraftKeyConstructor = this .getConstructor (this .minecraftKeyClass , String .class );
79+
80+ if (this .packetPlayOutMinecraftKeyConstructor == null ) {
81+ this .resourceLocationParseMethod = this .getMethod (this .minecraftKeyClass , "parse" , String .class );
82+
83+ if (this .resourceLocationParseMethod == null ) {
84+ this .resourceLocationParseMethod = this .getMethod (this .minecraftKeyClass , "a" , String .class );
85+ }
86+ }
87+
88+ return ;
89+ }
90+ }
91+
7392 Class <?> nmsPlayerClass = this .getClass ("net.minecraft.server.level.EntityPlayer" );
7493 if (nmsPlayerClass == null ) {
7594 throw new RuntimeException ("Failed to find EntityPlayer class" );
@@ -121,8 +140,6 @@ public BukkitPluginMessageSender(AbstractBukkitBadlionPlugin apiBukkit) {
121140 // If we made it this far in theory we are on at least 1.8
122141 this .packetPlayOutCustomPayloadConstructor = this .getConstructor (packetPlayOutCustomPayloadClass , String .class , this .packetDataSerializerClass );
123142 if (this .packetPlayOutCustomPayloadConstructor == null ) {
124- this .minecraftKeyClass = this .getClass ("net.minecraft.resources.MinecraftKey" );
125-
126143 // Fix for Paper in newer versions
127144 this .packetPlayOutCustomPayloadConstructor = this .getConstructor (packetPlayOutCustomPayloadClass , this .minecraftKeyClass , this .packetDataSerializerClass );
128145
@@ -218,6 +235,19 @@ public void sendPluginMessagePacket(Player player, String channel, Object data)
218235 try {
219236 Object packet ;
220237
238+ if (this .sendCustomPayloadMethod != null ) {
239+ Object key ;
240+
241+ if (this .packetPlayOutMinecraftKeyConstructor == null ) {
242+ key = this .resourceLocationParseMethod .invoke (null , channel );
243+ } else {
244+ key = this .packetPlayOutMinecraftKeyConstructor .newInstance (channel );
245+ }
246+
247+ this .sendCustomPayloadMethod .invoke (player , key , data );
248+ return ;
249+ }
250+
221251 // Newer MC version, setup ByteBuf object
222252 if (this .packetDataSerializerClass != null ) {
223253 if (this .usePacketPayload ) {
0 commit comments