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).
92 lines
3.4 KiB
Kotlin
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 ) {}
|
|
} |