Skip to content

Commit df599a8

Browse files
committed
Ensure background interface is re-opened in all cases
1 parent 94a1777 commit df599a8

File tree

3 files changed

+36
-16
lines changed

3 files changed

+36
-16
lines changed

interfaces/src/main/kotlin/com/noxcrew/interfaces/InterfacesListeners.kt

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ public class InterfacesListeners private constructor(private val plugin: Plugin)
150150
.expireAfterWrite(200.toLong(), TimeUnit.MILLISECONDS)
151151
.build()
152152

153+
private var dontReopen: Boolean = false
154+
153155
/** The inventory currently opened by players, we track this internally because the [InventoryCloseEvent] has the wrong parameters. */
154156
private val openInventory = ConcurrentHashMap<HumanEntity, AbstractInterfaceView<*, *, *>>()
155157

@@ -165,8 +167,18 @@ public class InterfacesListeners private constructor(private val plugin: Plugin)
165167
/** A map of interfaces being rendered for each player. */
166168
private val renderingPlayerInterfaceViews = ConcurrentHashMap<UUID, InterfaceView>()
167169

170+
/** Runs [function] without reopening a new menu. */
171+
public fun withoutReopen(function: () -> Unit) {
172+
val oldValue = dontReopen
173+
dontReopen = true
174+
function()
175+
dontReopen = oldValue
176+
}
177+
168178
/** Re-opens the current background interface of [player]. */
169179
public fun reopenInventory(player: Player) {
180+
// Don't re-open the background inventory when we're coming from the open event.
181+
if (dontReopen) return
170182
(getOpenPlayerInterface(player.uniqueId) ?: getBackgroundPlayerInterface(player.uniqueId))?.also {
171183
SCOPE.launch(InterfacesCoroutineDetails(player.uniqueId, "reopening background interface")) {
172184
it.reopenIfIntended()
@@ -269,10 +281,12 @@ public class InterfacesListeners private constructor(private val plugin: Plugin)
269281
// Close the previous view first with open new as the reason, unless we
270282
// are currently opening this view!
271283
if (openInventory[event.player] != view) {
284+
dontReopen = true
272285
openInventory.put(event.player, view)?.markClosed(SCOPE, Reason.OPEN_NEW)
286+
dontReopen = false
273287
}
274288

275-
// Move the current open inventory to the background to indicate
289+
// Move any currently open player inventory to the background to indicate
276290
// it is no longer the actually opened inventory!
277291
demoteOpenView(event.player.uniqueId)
278292

@@ -283,20 +297,26 @@ public class InterfacesListeners private constructor(private val plugin: Plugin)
283297

284298
@EventHandler
285299
public fun onClose(event: InventoryCloseEvent) {
286-
// Don't listen to close events unless we have an inventory open
287-
if (!openInventory.containsKey(event.player)) return
288300
val reason = event.reason
289301

290-
// Save previous inventory contents before we open the new one
291-
saveInventoryContentsIfOpened(event.player)
302+
// Save previous inventory contents before we open the new one (only if we have one open!)
303+
if (openInventory.containsKey(event.player)) {
304+
saveInventoryContentsIfOpened(event.player)
305+
}
292306

293307
// When opening a new inventory we ignore the close event as it wrongly
294308
// reports the actual menu being closed! We rely entirely on the open event
295309
// and what we have previously stored as the open inventory.
296310
if (reason == Reason.OPEN_NEW) return
297311

298312
// Mark whatever inventory was open as closed!
299-
openInventory.remove(event.player)?.markClosed(SCOPE, reason)
313+
val opened = openInventory.remove(event.player)
314+
if (opened != null) {
315+
opened.markClosed(SCOPE, reason)
316+
} else if (reason in REOPEN_REASONS && !event.player.isDead) {
317+
// If the opened menu didn't trigger a re-open, do it manually!
318+
reopenInventory(event.player as Player)
319+
}
300320
}
301321

302322
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
@@ -659,8 +679,8 @@ public class InterfacesListeners private constructor(private val plugin: Plugin)
659679
val completedClickHandler = view.executeSync(
660680
InterfacesExceptionContext(
661681
view.player,
662-
InterfacesOperation.RUNNING_CLICK_HANDLER
663-
)
682+
InterfacesOperation.RUNNING_CLICK_HANDLER,
683+
),
664684
) {
665685
// Run any pre-processors
666686
view.builder.clickPreprocessors
@@ -734,7 +754,9 @@ public class InterfacesListeners private constructor(private val plugin: Plugin)
734754
runSync {
735755
// Close the current inventory to open another to avoid close reasons
736756
val reopen = view.shouldStillBeOpened
737-
view.player.closeInventory(Reason.OPEN_NEW)
757+
INSTANCE.withoutReopen {
758+
view.player.closeInventory(Reason.OPEN_NEW)
759+
}
738760

739761
// Ensure the view is allowed to be opened again after we're done
740762
if (reopen) {

interfaces/src/main/kotlin/com/noxcrew/interfaces/view/AbstractInterfaceView.kt

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -246,12 +246,8 @@ public abstract class AbstractInterfaceView<I : InterfacesInventory, T : Interfa
246246
supervisor = SupervisorJob()
247247

248248
// Test if a background menu should be opened
249-
val backgroundInterface = InterfacesListeners.INSTANCE.getBackgroundPlayerInterface(player.uniqueId)
250-
val shouldReopen = reason in REOPEN_REASONS && !player.isDead && backgroundInterface != null
251-
if (shouldReopen) {
252-
SCOPE.launch(InterfacesCoroutineDetails(player.uniqueId, "reopening background interface")) {
253-
backgroundInterface?.reopenIfIntended()
254-
}
249+
if (reason in REOPEN_REASONS && !player.isDead) {
250+
InterfacesListeners.INSTANCE.reopenInventory(player)
255251
}
256252
}
257253
}

interfaces/src/main/kotlin/com/noxcrew/interfaces/view/PlayerInterfaceView.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ public class PlayerInterfaceView internal constructor(
4040
// Remove this inventory from the background interface before closing so it
4141
// doesn't automatically re-open!
4242
InterfacesListeners.INSTANCE.markViewClosed(player.uniqueId, this)
43-
player.closeInventory()
43+
InterfacesListeners.INSTANCE.withoutReopen {
44+
player.closeInventory()
45+
}
4446
}
4547

4648
// Open this player interface for the player

0 commit comments

Comments
 (0)