@@ -198,8 +198,10 @@ public org.bukkit.inventory.ItemStack getCursor() {
198198
199199 /**
200200 * Sends all changes to the remote client.
201+ *
202+ * @param pingId Optional ping id to also send a ping packet, or any negative number to not send a ping packet.
201203 */
202- public void sendChangesToRemote () {
204+ public void sendChangesToRemote (int pingId ) {
203205 var packets = new ArrayList <Packet <? super ClientGamePacketListener >>();
204206
205207 for (int i = 0 ; i < items .size (); i ++) {
@@ -228,6 +230,10 @@ public void sendChangesToRemote() {
228230 }
229231 }
230232
233+ if (pingId >= 0 ) {
234+ packets .add (createMaskedPingPacket (pingId ));
235+ }
236+
231237 PacketListener .getInstance ().injectOutgoing (player , packets );
232238 }
233239
@@ -242,9 +248,11 @@ public void sendCarriedToRemote() {
242248
243249 /**
244250 * Sends all data to the remote client.
251+ *
252+ * @param pingId Optional ping id to also send a ping packet, or any negative number to not send a ping packet.
245253 */
246- public void sendAllToRemote () {
247- PacketListener .getInstance ().injectOutgoing (player , createContainerInitPacketList ());
254+ public void sendAllToRemote (int pingId ) {
255+ PacketListener .getInstance ().injectOutgoing (player , createContainerInitPacketList (pingId ));
248256 markRemoteSynced ();
249257 }
250258
@@ -256,7 +264,7 @@ public void sendAllToRemote() {
256264 public void sendOpenPacket (Component title ) {
257265 this .title = title ;
258266
259- var packets = createContainerInitPacketList ();
267+ var packets = createContainerInitPacketList (- 1 );
260268 packets .addFirst (new ClientboundOpenScreenPacket (containerId , menuType , PaperAdventure .asVanilla (title )));
261269 PacketListener .getInstance ().injectOutgoing (player , packets );
262270 markRemoteSynced ();
@@ -265,9 +273,10 @@ public void sendOpenPacket(Component title) {
265273 /**
266274 * Creates the list of packets needed for container initialization, excluding the open screen packet.
267275 *
276+ * @param pingId Optional ping id to also include a ping packet, or any negative number to not include a ping packet.
268277 * @return The list of packets
269278 */
270- private List <Packet <? super ClientGamePacketListener >> createContainerInitPacketList () {
279+ private List <Packet <? super ClientGamePacketListener >> createContainerInitPacketList (int pingId ) {
271280 var packets = new ArrayList <Packet <? super ClientGamePacketListener >>();
272281 packets .add (new ClientboundContainerSetContentPacket (
273282 containerId ,
@@ -278,6 +287,9 @@ private List<Packet<? super ClientGamePacketListener>> createContainerInitPacket
278287 for (int i = 0 ; i < dataSlots .length ; i ++) {
279288 packets .add (new ClientboundContainerSetDataPacket (containerId , i , dataSlots [i ]));
280289 }
290+ if (pingId >= 0 ) {
291+ packets .add (createMaskedPingPacket (pingId ));
292+ }
281293 return packets ;
282294 }
283295
@@ -304,7 +316,7 @@ public void open(Component title) {
304316 pl .redirectIncoming (player , ServerboundContainerClickPacket .class , incoming );
305317 pl .redirectIncoming (player , ServerboundContainerClosePacket .class , incoming );
306318 pl .redirectIncoming (player , ServerboundSelectBundleItemPacket .class , incoming );
307- pl .listenIncoming (player , ServerboundPongPacket .class , this :: handlePongAsync );
319+ pl .listenIncoming (player , ServerboundPongPacket .class , incoming );
308320 pl .discard (player , ClientboundOpenScreenPacket .class );
309321 pl .discard (player , ClientboundContainerSetContentPacket .class );
310322 pl .discard (player , ClientboundContainerSetDataPacket .class );
@@ -343,7 +355,7 @@ public void handleClosed() {
343355 *
344356 * @param id The window state id
345357 */
346- public void sendPing (int id ) {
358+ private ClientboundPingPacket createMaskedPingPacket (int id ) {
347359 // generate new ping id, remember mapping and timestamp
348360 int ping = MathUtils .RANDOM .nextInt ();
349361 pendingPongs .put (ping , new PingData (id , System .currentTimeMillis ()));
@@ -352,24 +364,7 @@ public void sendPing(int id) {
352364 long now = System .currentTimeMillis ();
353365 pendingPongs .values ().removeIf (data -> now - data .timestamp () > PING_TIMEOUT_MS );
354366
355- PacketListener .getInstance ().injectOutgoing (player , new ClientboundPingPacket (ping ));
356- }
357-
358- /**
359- * Handles a pong packet from the client.
360- *
361- * @param packet The packet that was received
362- */
363- public void handlePongAsync (ServerboundPongPacket packet ) {
364- var data = pendingPongs .remove (packet .getId ());
365- if (data == null )
366- return ; // ignore unknown pongs, unrelated to InvUI
367-
368- player .getScheduler ().run (
369- InvUI .getInstance ().getPlugin (),
370- _ -> getWindowEvents ().handlePong (data .id ()),
371- null
372- );
367+ return new ClientboundPingPacket (ping );
373368 }
374369
375370 //<editor-fold desc="action handlers">
@@ -404,10 +399,25 @@ protected UpdateType processPacket(Packet<? super ServerGamePacketListener> pack
404399 handleClose (p );
405400 yield UpdateType .NONE ;
406401 }
407- default -> UpdateType .NONE ; // unhandled packet
402+ case ServerboundPongPacket p -> {
403+ handlePong (p );
404+ yield UpdateType .NONE ;
405+ }
406+ default -> throw new UnsupportedOperationException ("Unknown packet type: " + packet .getClass ().getName ());
408407 };
409408 }
410409
410+ /**
411+ * Handles a pong packet from the client, which may or may not be related to a ping packet sent through this menu.
412+ *
413+ * @param packet The packet that was received
414+ */
415+ private void handlePong (ServerboundPongPacket packet ) {
416+ var data = pendingPongs .remove (packet .getId ());
417+ if (data != null ) // ignore unknown pongs, unrelated to InvUI
418+ getWindowEvents ().handlePong (data .id ());
419+ }
420+
411421 /**
412422 * Handles a client-initiated inventory close.
413423 *
0 commit comments