Files
GameModes-SpeedHG/src/main/kotlin/club/mcscrims/speedhg/kit/Kit.kt
TDSTOS 72a58fdd9c Add Kit GUI (menu/anvil) and integrate MenuListener
Introduce a full chest-based kit selection UI and anvil search: add Menu, MenuHolder, KitSelectorMenu, KitItemFactory, AnvilSearchMenu (with AnvilSearchTracker) and a central MenuListener to dispatch menu and anvil interactions. Integrate the GUI into KitCommand (opens selector on no args, enforces mid-game selection rules, remove/replace backup kits when switching) and register MenuListener in the main plugin. Add permission speedhg.bypass and update ConnectListener to kick joiners when a game is running unless they have the bypass permission. Remove static playstyle lore from language file (now rendered dynamically), and apply small import/refactor cleanups (use wildcard imports for kit impls, java.util.* replacements).
2026-03-26 17:06:40 +01:00

92 lines
3.4 KiB
Kotlin

package club.mcscrims.speedhg.kit
import club.mcscrims.speedhg.kit.ability.ActiveAbility
import club.mcscrims.speedhg.kit.ability.PassiveAbility
import net.kyori.adventure.text.Component
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import java.util.*
import java.util.concurrent.ConcurrentHashMap
/**
* Base class for every kit in SpeedHG.
*
* ## How to create a new kit
* 1. Extend this class.
* 2. Implement all abstract members.
* 3. For each [Playstyle], create a private inner class extending [ActiveAbility]
* and another extending [PassiveAbility].
* 4. Return the correct instance from [getActiveAbility] / [getPassiveAbility]
* using a `when(playstyle)` expression.
* 5. Register the kit via `plugin.kitManager.registerKit(YourKit())` in [SpeedHG.onEnable].
*
* See [TemplateKit] for a fully annotated example.
*/
abstract class Kit {
/** Unique snake_case identifier (e.g. `"warrior"`, `"archer"`). */
abstract val id: String
/** Coloured display name shown in the kit selection GUI. */
abstract val displayName: Component
/** Short lore lines shown on the item in the kit GUI. */
abstract val lore: List<String>
/** Icon used in the kit selection GUI. */
abstract val icon: Material
// -------------------------------------------------------------------------
// Playstyle-specific abilities — implement with a `when` expression
// -------------------------------------------------------------------------
/**
* Return the [ActiveAbility] for the given [playstyle].
*
* ```kotlin
* override fun getActiveAbility(playstyle: Playstyle) = when (playstyle) {
* Playstyle.AGGRESSIVE -> AggressiveActive()
* Playstyle.DEFENSIVE -> DefensiveActive()
* }
* ```
*
* **Performance note:** This is called frequently by [KitEventDispatcher].
* Prefer returning a cached singleton (`private val aggressiveActive = AggressiveActive()`)
* over allocating a new instance on each call.
*/
abstract fun getActiveAbility( playstyle: Playstyle ): ActiveAbility
/** Return the [PassiveAbility] for the given [playstyle]. Same caching advice applies. */
abstract fun getPassiveAbility( playstyle: Playstyle ): PassiveAbility
// -------------------------------------------------------------------------
// Item distribution
// -------------------------------------------------------------------------
abstract val cachedItems: ConcurrentHashMap<UUID, List<ItemStack>>
/**
* Give the player their kit-specific items at game start (after teleportation).
* The standard HG items (soup, compass, etc.) are already given by [GameManager].
* Only add kit-exclusive items here.
*/
abstract fun giveItems( player: Player, playstyle: Playstyle )
// -------------------------------------------------------------------------
// Lifecycle hooks (optional)
// -------------------------------------------------------------------------
/**
* Called once per round when the kit is applied to [player].
* Use for permanent potion effects, scoreboard objectives, repeating tasks, etc.
* The matching [PassiveAbility.onActivate] is called immediately after this.
*/
open fun onAssign( player: Player, playstyle: Playstyle ) {}
/**
* Called when the kit is removed (game over / round reset).
* The matching [PassiveAbility.onDeactivate] is called immediately before this.
*/
open fun onRemove( player: Player ) {}
}