Major refactor and bugfixes across language loading, kit lifecycle, and event handling:
- LanguageManager: Introduce LangData to hold string and list entries, load YAML lists alongside strings, and centralize retrieval (avoid reloading files at access time).
- GameManager: Use apply {} to configure worldBorder more concisely.
- KitManager.clearAll: Handle offline players by cleaning chargeData without calling lifecycle hooks (onActivate/onDeactivate cannot run for offline players).
- GoblinKit: Track per-player steal BukkitTask, cancel tasks on kit removal, only restore kits if player is still alive, and fix inventory removal by removing cached items and cleaning cache.
- KitEventDispatcher: Use null-safe chaining for victim passive hooks and early-return on non-block-position moves to ignore head-rotation events.
- GameStateListener: Add feastStarted flag placeholder and adjust iron ore handling/messages; add TODO for DB update.
- Extensions: Change legacySerializer visibility to internal.
These changes improve stability around scheduled tasks, offline cleanup, and language list support.
153 lines
4.6 KiB
Kotlin
153 lines
4.6 KiB
Kotlin
package club.mcscrims.speedhg.kit
|
|
|
|
import club.mcscrims.speedhg.SpeedHG
|
|
import club.mcscrims.speedhg.kit.charge.PlayerChargeData
|
|
import org.bukkit.entity.Player
|
|
import java.util.UUID
|
|
import java.util.concurrent.ConcurrentHashMap
|
|
|
|
/**
|
|
* Manages kit registration, player selections, and the charge state for all online players.
|
|
*
|
|
* ## Typical usage flow
|
|
* ```
|
|
* // During plugin startup
|
|
* kitManager.registerKit(WarriorKit())
|
|
* kitManager.registerKit(ArcherKit())
|
|
*
|
|
* // During lobby (e.g. GUI click)
|
|
* kitManager.selectKit(player, kitManager.getKit("warrior")!!)
|
|
* kitManager.selectPlaystyle(player, Playstyle.AGGRESSIVE)
|
|
*
|
|
* // When the game round starts (replace the TODO in GameManager.startGame)
|
|
* kitManager.applyKit(player) // gives items, runs onAssign / passive.onActivate
|
|
*
|
|
* // When the round ends
|
|
* kitManager.clearAll() // runs onRemove / passive.onDeactivate for every player
|
|
* ```
|
|
*/
|
|
class KitManager(
|
|
private val plugin: SpeedHG
|
|
) {
|
|
|
|
// All kits available this session, keyed by Kit.id
|
|
private val registeredKits = ConcurrentHashMap<String, Kit>()
|
|
|
|
// Lobby selections — set before the round starts
|
|
private val selectedKits = ConcurrentHashMap<UUID, Kit>()
|
|
private val selectedPlaystyles = ConcurrentHashMap<UUID, Playstyle>()
|
|
|
|
// Live charge state — populated by applyKit, cleared by removeKit/clearAll
|
|
private val chargeData = ConcurrentHashMap<UUID, PlayerChargeData>()
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Kit registration
|
|
// -------------------------------------------------------------------------
|
|
|
|
fun registerKit(
|
|
kit: Kit
|
|
) {
|
|
registeredKits[kit.id] = kit
|
|
plugin.logger.info("[KitManager] Registered kit: ${kit.id}")
|
|
}
|
|
|
|
fun getRegisteredKits(): Collection<Kit> = registeredKits.values
|
|
|
|
fun getKit( id: String ): Kit? = registeredKits[id]
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Player selections (lobby phase)
|
|
// -------------------------------------------------------------------------
|
|
|
|
fun selectKit(
|
|
player: Player,
|
|
kit: Kit
|
|
) {
|
|
selectedKits[player.uniqueId] = kit
|
|
}
|
|
|
|
/**
|
|
* Set the playstyle for a player.
|
|
* Defaults to [Playstyle.DEFENSIVE] if never called.
|
|
*/
|
|
fun selectPlaystyle(
|
|
player: Player,
|
|
playstyle: Playstyle
|
|
) {
|
|
selectedPlaystyles[player.uniqueId] = playstyle
|
|
}
|
|
|
|
fun getSelectedKit( player: Player ): Kit? = selectedKits[player.uniqueId]
|
|
|
|
fun getSelectedPlaystyle( player: Player ): Playstyle =
|
|
selectedPlaystyles[player.uniqueId] ?: Playstyle.DEFENSIVE
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Game lifecycle
|
|
// -------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Apply the player's selected kit at game start.
|
|
*
|
|
* Call this from [GameManager.startGame] for every online player, **after** teleportation.
|
|
* If the player has not selected a kit, this is a no-op.
|
|
*/
|
|
fun applyKit(
|
|
player: Player
|
|
) {
|
|
val kit = selectedKits[player.uniqueId] ?: return
|
|
val playstyle = getSelectedPlaystyle( player )
|
|
val active = kit.getActiveAbility( playstyle )
|
|
|
|
chargeData[player.uniqueId] = PlayerChargeData( active.hitsRequired )
|
|
|
|
kit.onAssign( player, playstyle )
|
|
kit.getPassiveAbility( playstyle ).onActivate( player )
|
|
kit.giveItems( player, playstyle )
|
|
}
|
|
|
|
/**
|
|
* Remove and clean up a player's kit (round over, player eliminated, etc.).
|
|
* Safe to call even if the player has no kit assigned.
|
|
*/
|
|
fun removeKit(
|
|
player: Player
|
|
) {
|
|
val kit = selectedKits[player.uniqueId] ?: return
|
|
val playstyle = getSelectedPlaystyle( player )
|
|
|
|
kit.getPassiveAbility( playstyle ).onDeactivate( player )
|
|
kit.onRemove( player )
|
|
|
|
chargeData.remove( player.uniqueId )
|
|
}
|
|
|
|
/**
|
|
* Remove all kits and clear every selection.
|
|
* Call this at the end of each round, **before** resetting other game state.
|
|
*/
|
|
fun clearAll()
|
|
{
|
|
selectedKits.keys.toList().forEach { uuid ->
|
|
val player = plugin.server.getPlayer( uuid )
|
|
if ( player != null )
|
|
removeKit( player )
|
|
else
|
|
{
|
|
// Daten bereinigen ohne Lifecycle-Hooks (Spieler ist offline)
|
|
chargeData.remove( uuid )
|
|
// Hinweis: onDeactivate/onRemove können nicht aufgerufen werden
|
|
// → Kits müssen in onActivate gestartete Tasks UUID-basiert führen
|
|
}
|
|
}
|
|
selectedKits.clear()
|
|
selectedPlaystyles.clear()
|
|
chargeData.clear()
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Charge access (used by KitEventDispatcher)
|
|
// -------------------------------------------------------------------------
|
|
|
|
fun getChargeData( player: Player ): PlayerChargeData? = chargeData[player.uniqueId]
|
|
} |