Add kit inventory

This commit is contained in:
TDSTOS
2025-12-11 19:47:45 +01:00
parent c741739cdd
commit 1acb5681fc
5 changed files with 271 additions and 104 deletions

View File

@@ -18,12 +18,14 @@ class KitsCommand(
label: String,
args: Array<out String>
): Boolean {
if (sender !is Player) {
if ( sender !is Player )
{
sender.sendMessage("§cOnly players can use this command.")
return true
}
kitInventoryManager.openKitInventory(sender, 1)
kitInventoryManager.openKitInventory( sender, 1 )
return true
}
}

View File

@@ -3,13 +3,18 @@ package club.mcscrims.speedhg.kit
import org.bukkit.inventory.Inventory
import org.bukkit.inventory.InventoryHolder
class KitInventoryHolder(val page: Int) : InventoryHolder {
class KitInventoryHolder(
val page: Int
) : InventoryHolder {
private lateinit var inventory: Inventory
override fun getInventory(): Inventory = inventory
fun setInventory(inventory: Inventory) {
fun setInventory(
inventory: Inventory
) {
this.inventory = inventory
}
}

View File

@@ -1,6 +1,7 @@
package club.mcscrims.speedhg.kit
import club.mcscrims.speedhg.SpeedHG
import club.mcscrims.speedhg.SpeedHG.Companion.content
import org.bukkit.Material
import org.bukkit.Sound
import org.bukkit.entity.Player
@@ -16,46 +17,49 @@ class KitInventoryListener(
) : Listener {
@EventHandler
fun onInventoryClick(event: InventoryClickEvent) {
fun onInventoryClick(
event: InventoryClickEvent
) {
val holder = event.inventory.holder
if (holder !is KitInventoryHolder) {
if ( holder !is KitInventoryHolder )
return
}
event.isCancelled = true
val player = event.whoClicked as? Player ?: return
val clickedItem = event.currentItem ?: return
if (clickedItem.type == Material.AIR) {
if ( clickedItem.type == Material.AIR )
return
}
when (event.rawSlot) {
when( event.rawSlot )
{
45 -> {
if (holder.page > 1) {
player.playSound(player.location, Sound.UI_BUTTON_CLICK, 1f, 1f)
kitInventoryManager.openKitInventory(player, holder.page - 1)
if ( holder.page > 1 )
{
player.playSound( player.location, Sound.UI_BUTTON_CLICK, 1f, 1f )
kitInventoryManager.openKitInventory( player, holder.page - 1 )
}
}
49 -> {
player.playSound(player.location, Sound.UI_BUTTON_CLICK, 1f, 0.8f)
player.playSound( player.location, Sound.UI_BUTTON_CLICK, 1f, 0.8f )
player.closeInventory()
}
53 -> {
val totalKits = kitManager.getAllKits().size
val totalPages = (totalKits + 27) / 28
if (holder.page < totalPages) {
player.playSound(player.location, Sound.UI_BUTTON_CLICK, 1f, 1f)
kitInventoryManager.openKitInventory(player, holder.page + 1)
val totalPages = ( totalKits + 27 ) / 28
if ( holder.page < totalPages )
{
player.playSound( player.location, Sound.UI_BUTTON_CLICK, 1f, 1f )
kitInventoryManager.openKitInventory( player, holder.page + 1 )
}
}
in 10..43 -> {
val allKits = kitManager.getAllKits().toList()
val startIndex = (holder.page - 1) * 28
val endIndex = (startIndex + 28).coerceAtMost(allKits.size)
val kitsOnPage = allKits.subList(startIndex, endIndex)
val startIndex = ( holder.page - 1 ) * 28
val endIndex = ( startIndex + 28 ).coerceAtMost( allKits.size )
val kitsOnPage = allKits.subList( startIndex, endIndex )
val kitSlots = listOf(
10, 11, 12, 13, 14, 15, 16,
@@ -64,20 +68,22 @@ class KitInventoryListener(
37, 38, 39, 40, 41, 42, 43
)
val slotIndex = kitSlots.indexOf(event.rawSlot)
if (slotIndex != -1 && slotIndex < kitsOnPage.size) {
val slotIndex = kitSlots.indexOf( event.rawSlot )
if ( slotIndex != -1 && slotIndex < kitsOnPage.size )
{
val selectedKit = kitsOnPage[slotIndex]
if (kitManager.selectKit(player, selectedKit.id)) {
player.playSound(player.location, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1f, 1.2f)
if (kitManager.selectKit( player, selectedKit.id ))
{
player.playSound( player.location, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1f, 1.2f )
plugin.chatManager.sendMessage(
player,
"kits.selected",
"{kit}" to selectedKit.displayName.content()
)
kitInventoryManager.openKitInventory(player, holder.page)
kitInventoryManager.openKitInventory( player, holder.page )
} else {
player.playSound(player.location, Sound.ENTITY_VILLAGER_NO, 1f, 1f)
player.playSound( player.location, Sound.ENTITY_VILLAGER_NO, 1f, 1f )
}
}
}
@@ -85,11 +91,13 @@ class KitInventoryListener(
}
@EventHandler
fun onInventoryDrag(event: InventoryDragEvent) {
fun onInventoryDrag(
event: InventoryDragEvent
) {
val holder = event.inventory.holder
if (holder is KitInventoryHolder) {
if ( holder is KitInventoryHolder )
event.isCancelled = true
}
}
}

View File

@@ -1,7 +1,7 @@
package club.mcscrims.speedhg.kit
import club.mcscrims.speedhg.SpeedHG
import club.mcscrims.speedhg.SpeedHG.Companion.content
import kotlinx.coroutines.runBlocking
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.format.NamedTextColor
import net.kyori.adventure.text.format.TextDecoration
@@ -11,7 +11,6 @@ import org.bukkit.enchantments.Enchantment
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemFlag
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.ItemMeta
class KitInventoryManager(
private val plugin: SpeedHG,
@@ -21,36 +20,39 @@ class KitInventoryManager(
private val kitsPerPage = 28
private val rows = 6
fun openKitInventory(player: Player, page: Int = 1) {
fun openKitInventory(
player: Player,
page: Int = 1
) {
val allKits = kitManager.getAllKits().toList()
val totalPages = (allKits.size + kitsPerPage - 1) / kitsPerPage
val validPage = page.coerceIn(1, totalPages.coerceAtLeast(1))
val totalPages = ( allKits.size + kitsPerPage - 1 ) / kitsPerPage
val validPage = page.coerceIn( 1, totalPages.coerceAtLeast( 1 ))
val holder = KitInventoryHolder(validPage)
val holder = KitInventoryHolder( validPage )
val title = Component.text("Kits - Page $validPage/$totalPages")
.color(NamedTextColor.DARK_PURPLE)
.decoration(TextDecoration.BOLD, true)
.color( NamedTextColor.DARK_PURPLE )
.decoration( TextDecoration.BOLD, true )
val inventory = Bukkit.createInventory(holder, rows * 9, title)
holder.setInventory(inventory)
val inventory = Bukkit.createInventory( holder, rows * 9, title )
holder.setInventory( inventory )
fillBorder(inventory)
fillKits(inventory, allKits, validPage, player)
fillNavigationItems(inventory, validPage, totalPages)
fillBorder( inventory )
fillKits( inventory, allKits, validPage, player )
fillNavigationItems( inventory, validPage, totalPages )
player.openInventory(inventory)
player.openInventory( inventory )
}
private fun fillBorder(inventory: org.bukkit.inventory.Inventory) {
private fun fillBorder(
inventory: org.bukkit.inventory.Inventory
) {
val borderItem = createBorderItem()
for (i in 0..8) {
inventory.setItem(i, borderItem)
}
for ( i in 0..8 )
inventory.setItem( i, borderItem )
for (i in 45..53) {
inventory.setItem(i, borderItem)
}
for ( i in 45..53 )
inventory.setItem( i, borderItem )
}
private fun fillKits(
@@ -59,11 +61,11 @@ class KitInventoryManager(
page: Int,
player: Player
) {
val startIndex = (page - 1) * kitsPerPage
val endIndex = (startIndex + kitsPerPage).coerceAtMost(allKits.size)
val kitsOnPage = allKits.subList(startIndex, endIndex)
val startIndex = ( page - 1 ) * kitsPerPage
val endIndex = ( startIndex + kitsPerPage ).coerceAtMost( allKits.size )
val kitsOnPage = allKits.subList( startIndex, endIndex )
val selectedKit = kitManager.getSelectedKit(player)
val selectedKit = kitManager.getSelectedKit( player )
val kitSlots = listOf(
10, 11, 12, 13, 14, 15, 16,
@@ -73,10 +75,11 @@ class KitInventoryManager(
)
kitsOnPage.forEachIndexed { index, kit ->
if (index < kitSlots.size) {
if ( index < kitSlots.size )
{
val isSelected = selectedKit?.id == kit.id
val kitItem = createKitItem(kit, isSelected, player)
inventory.setItem(kitSlots[index], kitItem)
val kitItem = createKitItem( kit, isSelected, player )
inventory.setItem(kitSlots[ index ], kitItem )
}
}
}
@@ -86,116 +89,135 @@ class KitInventoryManager(
page: Int,
totalPages: Int
) {
if (page > 1) {
inventory.setItem(45, createPreviousPageItem())
if ( page > 1 )
inventory.setItem( 45, createPreviousPageItem() )
inventory.setItem( 49, createCloseItem() )
if ( page < totalPages )
inventory.setItem( 53, createNextPageItem() )
}
inventory.setItem(49, createCloseItem())
if (page < totalPages) {
inventory.setItem(53, createNextPageItem())
}
}
private fun createBorderItem(): ItemStack {
val item = ItemStack(Material.GRAY_STAINED_GLASS_PANE)
private fun createBorderItem(): ItemStack
{
val item = ItemStack( Material.GRAY_STAINED_GLASS_PANE )
val meta = item.itemMeta
meta.displayName(Component.text(" "))
meta.displayName(Component.text( " " ))
item.itemMeta = meta
return item
}
private fun createKitItem(kit: AbstractKit, isSelected: Boolean, player: Player): ItemStack {
val item = ItemStack(kit.icon)
private fun createKitItem(
kit: AbstractKit,
isSelected: Boolean,
player: Player
): ItemStack
{
val item = ItemStack( kit.icon )
val meta = item.itemMeta
meta.displayName(kit.displayName.decoration(TextDecoration.ITALIC, false))
meta.displayName(kit.displayName.decoration( TextDecoration.ITALIC, false ))
val lore = mutableListOf<Component>()
if (isSelected) {
if ( isSelected ) {
lore.add(
Component.text("✔ Currently Selected")
.color(NamedTextColor.GREEN)
.decoration(TextDecoration.ITALIC, false)
.color( NamedTextColor.GREEN )
.decoration( TextDecoration.ITALIC, false )
)
} else {
lore.add(
Component.text("Click to select")
.color(NamedTextColor.YELLOW)
.decoration(TextDecoration.ITALIC, false)
.color( NamedTextColor.YELLOW )
.decoration( TextDecoration.ITALIC, false )
)
}
lore.add(Component.empty())
lore.add( Component.empty() )
kit.description.forEach { line ->
lore.add(
Component.text(line)
.color(NamedTextColor.GRAY)
.decoration(TextDecoration.ITALIC, false)
line.color( NamedTextColor.GRAY )
.decoration( TextDecoration.ITALIC, false )
)
}
if (canUseKit(player, kit)) {
if (isSelected) {
meta.addEnchant(Enchantment.UNBREAKING, 1, true)
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS)
if (canUseKit( player, kit )) {
if ( isSelected )
{
meta.addEnchant( Enchantment.UNBREAKING, 1, true )
meta.addItemFlags( ItemFlag.HIDE_ENCHANTS )
}
} else {
lore.add(Component.empty())
lore.add( Component.empty() )
lore.add(
Component.text("⚠ Locked")
.color(NamedTextColor.RED)
.decoration(TextDecoration.ITALIC, false)
.decoration(TextDecoration.BOLD, true)
.color( NamedTextColor.RED )
.decoration( TextDecoration.ITALIC, false )
.decoration( TextDecoration.BOLD, true )
)
}
meta.lore(lore)
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES)
meta.lore( lore )
meta.addItemFlags( ItemFlag.HIDE_ATTRIBUTES )
item.itemMeta = meta
return item
}
private fun createPreviousPageItem(): ItemStack {
val item = ItemStack(Material.ARROW)
private fun createPreviousPageItem(): ItemStack
{
val item = ItemStack( Material.ARROW )
val meta = item.itemMeta
meta.displayName(
Component.text("← Previous Page")
.color(NamedTextColor.YELLOW)
.decoration(TextDecoration.ITALIC, false)
.color( NamedTextColor.YELLOW )
.decoration( TextDecoration.ITALIC, false )
)
item.itemMeta = meta
return item
}
private fun createNextPageItem(): ItemStack {
val item = ItemStack(Material.ARROW)
private fun createNextPageItem(): ItemStack
{
val item = ItemStack( Material.ARROW )
val meta = item.itemMeta
meta.displayName(
Component.text("Next Page →")
.color(NamedTextColor.YELLOW)
.decoration(TextDecoration.ITALIC, false)
.color( NamedTextColor.YELLOW )
.decoration( TextDecoration.ITALIC, false )
)
item.itemMeta = meta
return item
}
private fun createCloseItem(): ItemStack {
val item = ItemStack(Material.BARRIER)
private fun createCloseItem(): ItemStack
{
val item = ItemStack( Material.BARRIER )
val meta = item.itemMeta
meta.displayName(
Component.text("Close")
.color(NamedTextColor.RED)
.decoration(TextDecoration.ITALIC, false)
.color( NamedTextColor.RED )
.decoration( TextDecoration.ITALIC, false )
)
item.itemMeta = meta
return item
}
private fun canUseKit(player: Player, kit: AbstractKit): Boolean {
return true
private fun canUseKit(
player: Player,
kit: AbstractKit
): Boolean
{
val unlockedKits = mutableListOf<String>()
runBlocking {
val kitPlayer = plugin.playerRepository.findByUuid( player.uniqueId )
if ( kitPlayer != null ) unlockedKits.addAll( kitPlayer.unlockedKits )
}
return unlockedKits.contains( kit.id )
}
}

View File

@@ -4,12 +4,16 @@ import club.mcscrims.speedhg.SpeedHG
import club.mcscrims.speedhg.game.GameManager
import club.mcscrims.speedhg.game.GameStateTypes
import club.mcscrims.speedhg.util.DirectionUtil
import club.mcscrims.spigot.chat.getDisplayName
import kotlinx.coroutines.runBlocking
import org.bukkit.Bukkit
import org.bukkit.Material
import org.bukkit.Sound
import org.bukkit.attribute.Attribute
import org.bukkit.entity.Entity
import org.bukkit.entity.Player
import org.bukkit.entity.Projectile
import org.bukkit.entity.Tameable
import org.bukkit.event.Event
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
@@ -22,6 +26,7 @@ import org.bukkit.event.enchantment.EnchantItemEvent
import org.bukkit.event.entity.EntityDamageByEntityEvent
import org.bukkit.event.entity.EntityDamageEvent
import org.bukkit.event.entity.FoodLevelChangeEvent
import org.bukkit.event.entity.PlayerDeathEvent
import org.bukkit.event.inventory.ClickType
import org.bukkit.event.inventory.CraftItemEvent
import org.bukkit.event.inventory.InventoryClickEvent
@@ -542,4 +547,129 @@ class GameStateListener(
event.isCancelled = true
}
enum class DeathType {
PLAYER,
ENTITY,
WORLD
}
private val playerDeathMessages: Int = plugin.messageConfig.data.deathMessages["player"]!!.size
private val entityDeathMessages: Int = plugin.messageConfig.data.deathMessages["entity"]!!.size
private val worldDeathMessages: Int = plugin.messageConfig.data.deathMessages["world"]!!.size
@EventHandler
fun onDeath(
event: PlayerDeathEvent
) {
val player = event.entity
suppressEvent( event )
val lastDamageCause = player.lastDamageCause
var killer: Entity? = null
var deathType = DeathType.WORLD
if ( lastDamageCause is EntityDamageByEntityEvent )
{
val damager = lastDamageCause.damager
if ( damager !is Player )
{
if ( damager is Projectile )
{
if ( damager.shooter is Player )
{
deathType = DeathType.PLAYER
killer = damager.shooter as Player
}
else
{
deathType = DeathType.ENTITY
killer = damager.shooter as Entity
}
}
else if ( damager is Tameable && damager.isTamed && damager.owner is Player )
{
deathType = DeathType.PLAYER
killer = damager.owner as Player
}
else
{
deathType = DeathType.ENTITY
killer = damager
}
}
else
{
deathType = DeathType.PLAYER
killer = damager
}
}
if ( killer != null && killer is Player )
{
killer.exp += 0.5f
runBlocking { plugin.statsRepository.addKills( killer.uniqueId, 1 ) }
}
when( deathType )
{
DeathType.PLAYER ->
{
val random = this.random.nextInt( 0, playerDeathMessages )
val message = plugin.chatFormatter.formatList( "death.player",
"{player}" to player.getDisplayName, "{killer}" to (killer as Player).getDisplayName
)[ random ]
for ( p in Bukkit.getOnlinePlayers() )
plugin.chatManager.sendInteractiveMessage( p, message )
}
DeathType.ENTITY ->
{
val random = this.random.nextInt( 0, entityDeathMessages )
val message = plugin.chatFormatter.formatList( "death.entity",
"{player}" to player.getDisplayName, "{entity}" to killer!!.type.name
)[ random ]
for ( p in Bukkit.getOnlinePlayers() )
plugin.chatManager.sendInteractiveMessage( p, message )
}
DeathType.WORLD ->
{
val random = this.random.nextInt( 0, worldDeathMessages )
val message = plugin.chatFormatter.formatList( "death.world",
"{player}" to player.getDisplayName
)[ random ]
for ( p in Bukkit.getOnlinePlayers() )
plugin.chatManager.sendInteractiveMessage( p, message )
}
}
}
private fun suppressEvent(
event: PlayerDeathEvent
) {
val player = event.entity
event.deathMessage( null )
event.setShouldDropExperience( false )
event.setShouldPlayDeathSound( false )
player.world.strikeLightningEffect( player.location )
runBlocking {
plugin.statsRepository.addDeaths( player.uniqueId, 1 )
plugin.playerRepository.updateAliveStatus( player.uniqueId, false )
}
if ( player.isOnline )
player.kick(plugin.chatFormatter.format( "death.kick" ))
}
}