@@ -150,44 +150,73 @@ public class InterfacesListeners private constructor(private val plugin: Plugin)
150
150
private val queries: Cache <UUID , ChatQuery > = Caffeine .newBuilder()
151
151
.build()
152
152
153
- /* * A cache of open player interface views, with weak values. */
153
+ /* * A cache of player interfaces that should be opened again in the future. */
154
+ private val backgroundPlayerInterfaceViews: Cache <UUID , PlayerInterfaceView > = Caffeine .newBuilder()
155
+ .weakValues()
156
+ .build()
157
+
158
+ /* * A cache of actively open player interfaces. */
154
159
private val openPlayerInterfaceViews: Cache <UUID , PlayerInterfaceView > = Caffeine .newBuilder()
155
160
.weakValues()
156
161
.build()
157
162
158
- /* * Re-opens the current open interface of [player]. */
163
+ /* * Re-opens the current background interface of [player]. */
159
164
public fun reopenInventory (player : Player ) {
160
- getOpenInterface (player.uniqueId)?.also {
165
+ getBackgroundPlayerInterface (player.uniqueId)?.also {
161
166
SCOPE .launch {
162
167
it.open()
163
168
}
164
169
}
165
170
}
166
171
167
- /* * Returns the currently open interface for [playerId]. */
168
- public fun getOpenInterface (playerId : UUID ): PlayerInterfaceView ? {
172
+ /* *
173
+ * Returns the background interface for [playerId]. This is the last
174
+ * player interface that was opened, which should be re-opened once
175
+ * we no longer have anything else showing.
176
+ */
177
+ public fun getBackgroundPlayerInterface (playerId : UUID ): PlayerInterfaceView ? {
169
178
// Check if the menu is definitely still meant to be open
179
+ val result = backgroundPlayerInterfaceViews.getIfPresent(playerId) ? : return null
180
+ if (result.shouldStillBeOpened) return result
181
+ backgroundPlayerInterfaceViews.invalidate(playerId)
182
+ return null
183
+ }
184
+
185
+ /* *
186
+ * Returns the currently open player interface for [playerId].
187
+ */
188
+ public fun getOpenPlayerInterface (playerId : UUID ): PlayerInterfaceView ? {
170
189
val result = openPlayerInterfaceViews.getIfPresent(playerId) ? : return null
171
- if (result.shouldStillBeOpened) {
172
- return result
173
- }
190
+ if (result.shouldStillBeOpened) return result
174
191
openPlayerInterfaceViews.invalidate(playerId)
175
192
return null
176
193
}
177
194
178
- /* * Updates the currently open interface for [playerId] to [view]. */
179
- public fun setOpenInterface (playerId : UUID , view : PlayerInterfaceView ? ) {
195
+ /* * Marks the given [view] as the opened player interface. */
196
+ public fun openPlayerInterface (playerId : UUID , view : PlayerInterfaceView ) {
197
+ backgroundPlayerInterfaceViews.invalidate(playerId)
198
+ openPlayerInterfaceViews.put(playerId, view)
199
+ }
200
+
201
+ /* * Closes the given [view] of a player interface. */
202
+ public fun closePlayerInterface (playerId : UUID , view : PlayerInterfaceView ? ) {
180
203
// Save the contents of their currently shown inventory
181
204
val bukkitPlayer = Bukkit .getPlayer(playerId)
182
205
if (bukkitPlayer != null ) {
183
206
saveInventoryContentsIfOpened(bukkitPlayer)
184
207
}
185
208
209
+ abortQuery(playerId, view)
186
210
if (view == null ) {
211
+ backgroundPlayerInterfaceViews.invalidate(playerId)
187
212
openPlayerInterfaceViews.invalidate(playerId)
188
213
} else {
189
- abortQuery(playerId, null )
190
- openPlayerInterfaceViews.put(playerId, view)
214
+ if (backgroundPlayerInterfaceViews.getIfPresent(playerId) == = view) {
215
+ backgroundPlayerInterfaceViews.invalidate(playerId)
216
+ }
217
+ if (openPlayerInterfaceViews.getIfPresent(playerId) == = view) {
218
+ openPlayerInterfaceViews.invalidate(playerId)
219
+ }
191
220
}
192
221
}
193
222
@@ -212,6 +241,13 @@ public class InterfacesListeners private constructor(private val plugin: Plugin)
212
241
val holder = event.inventory.holder
213
242
val view = convertHolderToInterfaceView(holder) ? : return
214
243
244
+ // Move the current open inventory to the background to indicate
245
+ // it is no longer the actually opened inventory!
246
+ openPlayerInterfaceViews.getIfPresent(event.player.uniqueId)?.also {
247
+ backgroundPlayerInterfaceViews.put(event.player.uniqueId, it)
248
+ openPlayerInterfaceViews.invalidate(event.player.uniqueId)
249
+ }
250
+
215
251
// Abort any previous query the player had
216
252
abortQuery(event.player.uniqueId, null )
217
253
view.onOpen()
@@ -231,15 +267,15 @@ public class InterfacesListeners private constructor(private val plugin: Plugin)
231
267
232
268
SCOPE .launch {
233
269
// Determine if we can re-open a previous interface
234
- val openInterface = getOpenInterface (event.player.uniqueId)
235
- val shouldReopen = reason in REOPEN_REASONS && ! event.player.isDead && openInterface != null
270
+ val backgroundInterface = getBackgroundPlayerInterface (event.player.uniqueId)
271
+ val shouldReopen = reason in REOPEN_REASONS && ! event.player.isDead && backgroundInterface != null
236
272
237
273
// Mark the current view as closed properly
238
274
view.markClosed(reason)
239
275
240
276
// If possible, open back up a previous interface
241
277
if (shouldReopen) {
242
- requireNotNull(openInterface ).open()
278
+ requireNotNull(backgroundInterface ).open()
243
279
}
244
280
}
245
281
}
@@ -375,7 +411,7 @@ public class InterfacesListeners private constructor(private val plugin: Plugin)
375
411
@EventHandler
376
412
public fun onPlayerQuit (event : PlayerQuitEvent ) {
377
413
abortQuery(event.player.uniqueId, null )
378
- setOpenInterface (event.player.uniqueId, null )
414
+ closePlayerInterface (event.player.uniqueId, null )
379
415
}
380
416
381
417
/* * Returns whether [block] will trigger some interaction if clicked with [item]. */
@@ -388,7 +424,7 @@ public class InterfacesListeners private constructor(private val plugin: Plugin)
388
424
if (event.useItemInHand() == Event .Result .DENY ) return
389
425
390
426
val player = event.player
391
- val view = getOpenInterface (player.uniqueId) ? : return
427
+ val view = getOpenPlayerInterface (player.uniqueId) ? : return
392
428
393
429
// If we are prioritizing block interactions we assure they are not happening first
394
430
if (view.builder.prioritiseBlockInteractions) {
@@ -428,7 +464,7 @@ public class InterfacesListeners private constructor(private val plugin: Plugin)
428
464
@EventHandler(priority = EventPriority .LOW , ignoreCancelled = true )
429
465
public fun onDropItem (event : PlayerDropItemEvent ) {
430
466
val player = event.player
431
- val view = getOpenInterface (player.uniqueId) ? : return
467
+ val view = getOpenPlayerInterface (player.uniqueId) ? : return
432
468
val slot = player.inventory.heldItemSlot
433
469
val droppedSlot = GridPoint .at(3 , slot)
434
470
@@ -441,7 +477,7 @@ public class InterfacesListeners private constructor(private val plugin: Plugin)
441
477
@EventHandler(priority = EventPriority .LOW , ignoreCancelled = true )
442
478
public fun onSwapHands (event : PlayerSwapHandItemsEvent ) {
443
479
val player = event.player
444
- val view = getOpenInterface (player.uniqueId) ? : return
480
+ val view = getOpenPlayerInterface (player.uniqueId) ? : return
445
481
val slot = player.inventory.heldItemSlot
446
482
val interactedSlot1 = GridPoint .at(3 , slot)
447
483
val interactedSlot2 = GridPoint .at(4 , 4 )
@@ -527,7 +563,7 @@ public class InterfacesListeners private constructor(private val plugin: Plugin)
527
563
if (holder is AbstractInterfaceView <* , * , * >) return holder
528
564
529
565
// If it's the player's own inventory use the held one
530
- if (holder is HumanEntity ) return getOpenInterface (holder.uniqueId)
566
+ if (holder is HumanEntity ) return getOpenPlayerInterface (holder.uniqueId)
531
567
532
568
return null
533
569
}
0 commit comments