diff --git a/src/main/kotlin/club/mcscrims/speedhg/game/GameManager.kt b/src/main/kotlin/club/mcscrims/speedhg/game/GameManager.kt new file mode 100644 index 0000000..7674d68 --- /dev/null +++ b/src/main/kotlin/club/mcscrims/speedhg/game/GameManager.kt @@ -0,0 +1,35 @@ +package club.mcscrims.speedhg.game + +import org.bukkit.plugin.java.JavaPlugin + +class GameManager(private val plugin: JavaPlugin) { + + private var currentState: GameState? = null + + fun transitionTo(nextState: GameState) { + val previousState = currentState + + try { + currentState?.onExit(nextState) + } catch (e: Exception) { + plugin.logger.severe("Error during onExit for state ${currentState?.name}: ${e.message}") + e.printStackTrace() + } + + currentState = nextState + + try { + nextState.onEnter(previousState) + } catch (e: Exception) { + plugin.logger.severe("Error during onEnter for state ${nextState.name}: ${e.message}") + e.printStackTrace() + } + } + + fun getCurrentState(): GameState? = currentState + + fun shutdown() { + currentState?.onExit(null) + currentState = null + } +} diff --git a/src/main/kotlin/club/mcscrims/speedhg/game/GameState.kt b/src/main/kotlin/club/mcscrims/speedhg/game/GameState.kt new file mode 100644 index 0000000..04d75ed --- /dev/null +++ b/src/main/kotlin/club/mcscrims/speedhg/game/GameState.kt @@ -0,0 +1,110 @@ +package club.mcscrims.speedhg.game + +import org.bukkit.Bukkit +import org.bukkit.entity.Player +import org.bukkit.event.HandlerList +import org.bukkit.event.Listener +import org.bukkit.plugin.java.JavaPlugin +import org.bukkit.scheduler.BukkitTask + +open class GameState( + val name: String, + protected val gameManager: GameManager, + protected val plugin: JavaPlugin, + protected val durationSeconds: Int? = null +) { + + private val listeners = mutableListOf() + private var tickTask: BukkitTask? = null + private var remainingSeconds: Int = durationSeconds ?: 0 + private var isActive: Boolean = false + + open fun onEnter(previous: GameState?) { + isActive = true + remainingSeconds = durationSeconds ?: 0 + + if (durationSeconds != null && durationSeconds > 0) { + startTicking() + } + } + + open fun onTick() { + } + + open fun onEndOfDuration() { + } + + open fun onExit(next: GameState?) { + isActive = false + stopTicking() + unregisterAllListeners() + } + + private fun startTicking() { + tickTask = Bukkit.getScheduler().runTaskTimer(plugin, Runnable { + if (!isActive) { + stopTicking() + return@Runnable + } + + try { + onTick() + } catch (e: Exception) { + plugin.logger.severe("Error during onTick for state $name: ${e.message}") + e.printStackTrace() + } + + if (durationSeconds != null && remainingSeconds > 0) { + remainingSeconds-- + + if (remainingSeconds <= 0) { + try { + onEndOfDuration() + } catch (e: Exception) { + plugin.logger.severe("Error during onEndOfDuration for state $name: ${e.message}") + e.printStackTrace() + } + } + } + }, 20L, 20L) + } + + private fun stopTicking() { + tickTask?.cancel() + tickTask = null + } + + protected fun registerListener(listener: Listener) { + listeners.add(listener) + Bukkit.getPluginManager().registerEvents(listener, plugin) + } + + private fun unregisterAllListeners() { + listeners.forEach { listener -> + HandlerList.unregisterAll(listener) + } + listeners.clear() + } + + protected fun transitionTo(next: GameState) { + gameManager.transitionTo(next) + } + + protected fun broadcast(message: String) { + Bukkit.broadcastMessage(message) + } + + protected fun forAlivePlayers(action: (Player) -> Unit) { + Bukkit.getOnlinePlayers() + .filter { !it.isDead } + .forEach { player -> + try { + action(player) + } catch (e: Exception) { + plugin.logger.warning("Error executing action for player ${player.name}: ${e.message}") + } + } + } + + fun getRemainingSeconds(): Int = remainingSeconds +}