Skip to content

Commit

Permalink
fix: Stack overflow when close gui
Browse files Browse the repository at this point in the history
  • Loading branch information
Distractic committed Dec 14, 2023
1 parent 9431249 commit a960c11
Show file tree
Hide file tree
Showing 12 changed files with 124 additions and 67 deletions.
11 changes: 11 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import io.gitlab.arturbosch.detekt.Detekt
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
Expand Down Expand Up @@ -130,6 +131,16 @@ tasks {
targetCompatibility = javaVersionString
}

withType<Detekt>().configureEach {
reports {
html.required.set(true)
xml.required.set(true)
txt.required.set(false)
sarif.required.set(false)
md.required.set(false)
}
}

test {
useJUnitPlatform()
}
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-rc-1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
2 changes: 2 additions & 0 deletions src/main/kotlin/com/github/rushyverse/api/APIPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.github.rushyverse.api

import com.github.rushyverse.api.extension.registerListener
import com.github.rushyverse.api.game.SharedGameData
import com.github.rushyverse.api.gui.GUIManager
import com.github.rushyverse.api.koin.CraftContext
import com.github.rushyverse.api.koin.loadModule
import com.github.rushyverse.api.listener.api.LanguageListener
Expand Down Expand Up @@ -37,6 +38,7 @@ public class APIPlugin : JavaPlugin() {
single { ScoreboardManager() }
single { LanguageManager() }
single { SharedGameData() }
single { GUIManager() }
}

registerListener { LanguageListener() }
Expand Down
15 changes: 13 additions & 2 deletions src/main/kotlin/com/github/rushyverse/api/Plugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.github.rushyverse.api.configuration.reader.IFileReader
import com.github.rushyverse.api.configuration.reader.YamlFileReader
import com.github.rushyverse.api.extension.asComponent
import com.github.rushyverse.api.extension.registerListener
import com.github.rushyverse.api.gui.GUIListener
import com.github.rushyverse.api.koin.CraftContext
import com.github.rushyverse.api.koin.inject
import com.github.rushyverse.api.koin.loadModule
Expand All @@ -16,11 +17,21 @@ import com.github.rushyverse.api.player.Client
import com.github.rushyverse.api.player.ClientManager
import com.github.rushyverse.api.player.ClientManagerImpl
import com.github.rushyverse.api.player.language.LanguageManager
import com.github.rushyverse.api.serializer.*
import com.github.rushyverse.api.serializer.ComponentSerializer
import com.github.rushyverse.api.serializer.DyeColorSerializer
import com.github.rushyverse.api.serializer.EnchantmentSerializer
import com.github.rushyverse.api.serializer.ItemStackSerializer
import com.github.rushyverse.api.serializer.LocationSerializer
import com.github.rushyverse.api.serializer.MaterialSerializer
import com.github.rushyverse.api.serializer.NamespacedSerializer
import com.github.rushyverse.api.serializer.PatternSerializer
import com.github.rushyverse.api.serializer.PatternTypeSerializer
import com.github.rushyverse.api.serializer.RangeDoubleSerializer
import com.github.rushyverse.api.translation.ResourceBundleTranslator
import com.github.rushyverse.api.translation.Translator
import com.github.rushyverse.api.translation.registerResourceBundleForSupportedLocales
import com.github.shynixn.mccoroutine.bukkit.SuspendingJavaPlugin
import java.util.*
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.SerializersModuleBuilder
import kotlinx.serialization.modules.contextual
Expand All @@ -29,7 +40,6 @@ import org.bukkit.entity.Player
import org.jetbrains.annotations.Blocking
import org.koin.core.module.Module
import org.koin.dsl.bind
import java.util.*

/**
* Represents the base functionality required to create a plugin.
Expand Down Expand Up @@ -70,6 +80,7 @@ public abstract class Plugin(

registerListener { PlayerListener(this) }
registerListener { VillagerListener(this) }
registerListener { GUIListener(this) }
}

/**
Expand Down
16 changes: 10 additions & 6 deletions src/main/kotlin/com/github/rushyverse/api/gui/GUI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.github.rushyverse.api.gui

import com.github.rushyverse.api.koin.inject
import com.github.rushyverse.api.player.Client
import com.github.rushyverse.api.player.gui.GUIManager
import java.io.Closeable
import org.bukkit.Server
import org.bukkit.entity.HumanEntity
Expand All @@ -15,16 +14,20 @@ import org.bukkit.inventory.ItemStack
* Only one inventory is created for all the viewers.
* @property server Server.
* @property manager Manager to register or unregister the GUI.
* @property viewers List of viewers.
* @property isClosed If true, the GUI is closed; otherwise it is open.
*/
public abstract class GUI: Closeable {
public abstract class GUI : Closeable {

protected val server: Server by inject()

private val manager: GUIManager by inject()

public var isClosed: Boolean = false

init {
register()
}

/**
* Create the inventory of the GUI.
* @return The inventory of the GUI.
Expand All @@ -46,11 +49,12 @@ public abstract class GUI: Closeable {
public abstract suspend fun onClick(client: Client, clickedItem: ItemStack, event: InventoryClickEvent)

/**
* Close the inventory for the player.
* @param client Client to close the inventory for.
* Remove the client has a viewer of the GUI.
* @param client Client to close the GUI for.
* @param closeInventory If true, the interface will be closed, otherwise it will be kept open.
* @return True if the inventory was closed, false otherwise.
*/
public abstract suspend fun close(client: Client): Boolean
public abstract suspend fun close(client: Client, closeInventory: Boolean = true): Boolean

/**
* Close the inventory.
Expand Down
72 changes: 72 additions & 0 deletions src/main/kotlin/com/github/rushyverse/api/gui/GUIListener.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.github.rushyverse.api.gui

import com.github.rushyverse.api.Plugin
import com.github.rushyverse.api.extension.event.cancel
import com.github.rushyverse.api.koin.inject
import com.github.rushyverse.api.player.ClientManager
import org.bukkit.entity.HumanEntity
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.inventory.InventoryCloseEvent
import org.bukkit.event.player.PlayerQuitEvent

/**
* Listener for GUI events.
* @property clients Manager of clients.
*/
public class GUIListener(plugin: Plugin) : Listener {

private val clients: ClientManager by inject(plugin.id)

/**
* Called when a player clicks on an item in an inventory.
* If the click is detected in a GUI, the event is cancelled and the GUI is notified.
* @param event Event of the click.
*/
@EventHandler
public suspend fun onInventoryClick(event: InventoryClickEvent) {
if (event.isCancelled) return
val item = event.currentItem ?: return
val player = event.whoClicked

val client = clients.getClient(player)
val gui = client.gui() ?: return

// The item in a GUI is not supposed to be moved
event.cancel()
gui.onClick(client, item, event)
}

/**
* Called when a player closes an inventory.
* If the inventory is a GUI, the GUI is notified that it is closed for this player.
* @param event Event of the close.
*/
@EventHandler
public suspend fun onInventoryClose(event: InventoryCloseEvent) {
quitOpenedGUI(event.player)
}

/**
* Called when a player quits the server.
* If the player has a GUI opened, the GUI is notified that it is closed for this player.
* @param event Event of the quit.
*/
@EventHandler
public suspend fun onPlayerQuit(event: PlayerQuitEvent) {
quitOpenedGUI(event.player)
}

/**
* Quit the opened GUI for the player.
* @param player Player to quit the GUI for.
*/
private suspend fun quitOpenedGUI(player: HumanEntity) {
val client = clients.getClientOrNull(player)
val gui = client?.gui() ?: return
// We don't close the inventory because it is closing due to event.
gui.close(client, false)
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.github.rushyverse.api.player.gui
package com.github.rushyverse.api.gui

import com.github.rushyverse.api.gui.GUI
import com.github.rushyverse.api.player.Client

/**
Expand Down Expand Up @@ -47,6 +46,4 @@ public class GUIManager {
public fun remove(gui: GUI): Boolean {
return _guis.remove(gui)
}


}
9 changes: 7 additions & 2 deletions src/main/kotlin/com/github/rushyverse/api/gui/PersonalGUI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,13 @@ public abstract class PersonalGUI(
*/
protected abstract suspend fun fill(client: Client, inventory: Inventory)

override suspend fun close(client: Client): Boolean {
return mutex.withLock { inventories.remove(client) }?.close() == 1
override suspend fun close(client: Client, closeInventory: Boolean): Boolean {
return mutex.withLock { inventories.remove(client) }?.run {
if (closeInventory) {
close()
}
true
} == true
}

override suspend fun viewers(): List<HumanEntity> {
Expand Down
7 changes: 3 additions & 4 deletions src/main/kotlin/com/github/rushyverse/api/gui/SharedGUI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import org.bukkit.inventory.Inventory
public abstract class SharedGUI(
public val inventoryType: InventoryType,
public val title: Component
): GUI() {
) : GUI() {

private var inventory: Inventory? = null

Expand All @@ -43,13 +43,12 @@ public abstract class SharedGUI(

return inventory ?: createInventory(client).also {
inventory = it
register()
}
}

override suspend fun close(client: Client): Boolean {
override suspend fun close(client: Client, closeInventory: Boolean): Boolean {
val player = client.requirePlayer()
if(player.openInventory.topInventory == inventory) {
if (closeInventory && player.openInventory.topInventory == inventory) {
player.closeInventory()
return true
}
Expand Down
45 changes: 0 additions & 45 deletions src/main/kotlin/com/github/rushyverse/api/listener/GUIListener.kt

This file was deleted.

4 changes: 2 additions & 2 deletions src/main/kotlin/com/github/rushyverse/api/player/Client.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ package com.github.rushyverse.api.player
import com.github.rushyverse.api.delegate.DelegatePlayer
import com.github.rushyverse.api.extension.asComponent
import com.github.rushyverse.api.gui.GUI
import com.github.rushyverse.api.gui.GUIManager
import com.github.rushyverse.api.koin.inject
import com.github.rushyverse.api.player.exception.PlayerNotFoundException
import com.github.rushyverse.api.player.gui.GUIManager
import com.github.rushyverse.api.player.language.LanguageManager
import com.github.rushyverse.api.player.scoreboard.ScoreboardManager
import com.github.rushyverse.api.translation.SupportedLanguage
import fr.mrmicky.fastboard.adventure.FastBoard
import java.util.*
import kotlinx.coroutines.CoroutineScope
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver
import org.bukkit.entity.Player
import java.util.*

/**
* Client to store and manage data about player.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import org.bukkit.entity.HumanEntity
* @param player Player.
* @return The client linked to a player.
*/
public suspend inline fun <reified T : Client> ClientManager.getTypedClient(player: HumanEntity): T = getClient(player) as T
public suspend inline fun <reified T : Client> ClientManager.getTypedClient(player: HumanEntity): T =
getClient(player) as T

/**
* Get a client from the key linked to a player.
Expand Down

0 comments on commit a960c11

Please sign in to comment.