1616
1717/**
1818 * This class facilitates the invocation of methods on the current packet listener.
19- * It attempts to execute the <code>disconnect</code> method , upon failure
19+ * It attempts to execute the <code>send</code>, and <code> disconnect</code> methods , upon failure
2020 * (either due to the absence of the method or the packet listener being of an incorrect type),
2121 * it delegates the call to the network manager.
2222 *
@@ -36,15 +36,35 @@ public class PacketListenerInvoker {
3636 private static final Class <?> COMMON_PACKET_LISTENER_CLASS = MinecraftReflection .getNullableNMS ("server.network.ServerCommonPacketListenerImpl" );
3737 private static final Class <?> PREFERRED_PACKET_LISTENER_CLASS = COMMON_PACKET_LISTENER_CLASS != null ? COMMON_PACKET_LISTENER_CLASS : GAME_PACKET_LISTENER_CLASS ;
3838
39+ private static final MethodAccessor PACKET_LISTENER_SEND = getPacketListenerSend ();
3940 private static final MethodAccessor PACKET_LISTENER_DISCONNECT = getPacketListenerDisconnect ();
4041 private static final boolean DOES_PACKET_LISTENER_DISCONNECT_USE_COMPONENT = doesPacketListenerDisconnectUseComponent ();
4142
43+ private static final MethodAccessor NETWORK_MANAGER_SEND = getNetworkManagerSend ();
4244 private static final MethodAccessor NETWORK_MANAGER_DISCONNECT = getNetworkManagerDisconnect ();
4345 private static final MethodAccessor NETWORK_MANAGER_PACKET_LISTENER = getNetworkManagerPacketListener ();
4446
4547 public static void ensureStaticInitializedWithoutError () {
4648 }
4749
50+ private static MethodAccessor getPacketListenerSend () {
51+ FuzzyReflection packetListener = FuzzyReflection .fromClass (PREFERRED_PACKET_LISTENER_CLASS );
52+
53+ List <Method > send = packetListener .getMethodList (FuzzyMethodContract .newBuilder ()
54+ .banModifier (Modifier .STATIC )
55+ .returnTypeVoid ()
56+ .parameterCount (1 )
57+ .parameterExactType (MinecraftReflection .getPacketClass (), 0 )
58+ .build ());
59+
60+ if (send .isEmpty ()) {
61+ ProtocolLogger .debug ("Can't get packet listener send method" );
62+ return null ;
63+ }
64+
65+ return Accessors .getMethodAccessor (send .get (0 ));
66+ }
67+
4868 private static MethodAccessor getPacketListenerDisconnect () {
4969 FuzzyReflection packetListener = FuzzyReflection .fromClass (PREFERRED_PACKET_LISTENER_CLASS );
5070
@@ -81,6 +101,19 @@ private static boolean doesPacketListenerDisconnectUseComponent() {
81101 return false ;
82102 }
83103
104+ private static MethodAccessor getNetworkManagerSend () {
105+ FuzzyReflection networkManager = FuzzyReflection .fromClass (MinecraftReflection .getNetworkManagerClass ());
106+
107+ Method send = networkManager .getMethod (FuzzyMethodContract .newBuilder ()
108+ .banModifier (Modifier .STATIC )
109+ .returnTypeVoid ()
110+ .parameterCount (1 )
111+ .parameterExactType (MinecraftReflection .getPacketClass (), 0 )
112+ .build ());
113+
114+ return Accessors .getMethodAccessor (send );
115+ }
116+
84117 private static MethodAccessor getNetworkManagerDisconnect () {
85118 FuzzyReflection networkManager = FuzzyReflection .fromClass (MinecraftReflection .getNetworkManagerClass ());
86119
@@ -144,6 +177,21 @@ private Object getPacketListener() {
144177 return this .packetListener .get ();
145178 }
146179
180+ /**
181+ * Sends a packet using the current packet listener if available and valid; otherwise,
182+ * falls back to the network manager.
183+ *
184+ * @param packet The packet to be sent.
185+ */
186+ public void send (Object packet ) {
187+ Object packetListener = this .getPacketListener ();
188+ if (PACKET_LISTENER_SEND != null && packetListener != null ) {
189+ PACKET_LISTENER_SEND .invoke (packetListener , packet );
190+ } else {
191+ NETWORK_MANAGER_SEND .invoke (this .networkManager , packet );
192+ }
193+ }
194+
147195 /**
148196 * Disconnects the player using the current packet listener if available and valid; otherwise,
149197 * falls back to the network manager.
0 commit comments