Remove legacy modules, add language & scoreboard

Large refactor removing many legacy subsystems (abilities, kit system, database repos, recraft, world manager, extensive config classes, lunar/luckperms integrations and various listeners/commands). Introduces a lightweight LanguageManager, AntiRunningManager, ScoreboardManager, ConnectListener and a SoupListener; simplifies the main SpeedHG plugin to initialize these components and register the connection listener. Build changes: update Gradle wrapper to 8.10, remove paperweight and several external dependencies, add fr.mrmicky:fastboard and simplify shadowJar/build task configuration. Adds default language resource (languages/en_US.yml) and updates plugin/config resources. Purpose: simplify and decouple the plugin, reduce dependency surface and prepare for a leaner, modular rewrite.
This commit is contained in:
TDSTOS
2026-03-25 00:55:20 +01:00
parent b4db8dbfeb
commit e411879b20
57 changed files with 1172 additions and 5165 deletions

View File

@@ -1,116 +0,0 @@
package club.mcscrims.speedhg.kit
import club.mcscrims.speedhg.SpeedHG
import club.mcscrims.speedhg.ability.AbilityContext
import club.mcscrims.speedhg.ability.AbilityResult
import club.mcscrims.speedhg.game.GameManager
import net.kyori.adventure.text.Component
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.event.entity.EntityDamageByEntityEvent
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.event.player.PlayerMoveEvent
import org.bukkit.inventory.ItemStack
abstract class AbstractKit(
val id: String,
val displayName: Component,
val description: List<Component>,
val icon: Material,
val playStyle: PlayStyle,
protected val plugin: SpeedHG,
protected val abilityContext: AbilityContext,
protected val gameManager: GameManager
) {
lateinit var config: Map<String, Double>
val items = mutableListOf<ItemStack>()
abstract fun onSelect( player: Player )
abstract fun onStart( player: Player )
abstract fun onHit( attacker: Player, victim: Player, event: EntityDamageByEntityEvent )
abstract fun onDamaged( attacker: Player, victim: Player, event: EntityDamageByEntityEvent )
abstract fun onInteract( player: Player, event: PlayerInteractEvent )
abstract fun onMove( player: Player, event: PlayerMoveEvent )
open fun cleanup(
player: Player
) {
abilityContext.clearPlayerData( player )
}
protected fun hasCooldown(
player: Player,
key: String
): Boolean
{
return abilityContext.getRemainingCooldown( player, key ) > 0
}
protected fun startCooldown(
player: Player,
key: String,
seconds: Int
) {
abilityContext.cooldownManager.startCooldown( player, key, seconds )
}
protected fun getRemainingCooldown(
player: Player,
key: String
): Double
{
return abilityContext.getRemainingCooldown( player, key )
}
protected fun getHits(
player: Player,
key: String
): Int
{
return abilityContext.getHits(player, key)
}
protected fun resetHits(
player: Player,
key: String
) {
abilityContext.hitCounterManager.resetHits( player, key )
}
protected fun abilityResult(
player: Player,
abilityKey: String,
requiredHits: Int? = null,
cooldownSeconds: Int? = null
): AbilityResult {
return abilityContext.canUseAbility( player, abilityKey, requiredHits, cooldownSeconds )
}
}
enum class PlayStyle {
OFFENSIVE, DEFENSIVE
}
enum class KitMetaData {
IN_GLADIATOR,
GLADIATOR_BLOCK,
IS_ANVIL,
IS_BLACK_PANTHER,
BP_EXTRA_DAMAGE,
VOODOO_HOLD,
ICEMAGE_SNOWBALL,
ICEMAGE_SPEED;
fun getKey(): String
{
return name
}
}

View File

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

View File

@@ -1,103 +0,0 @@
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
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.inventory.InventoryDragEvent
class KitInventoryListener(
private val plugin: SpeedHG,
private val kitManager: KitManager,
private val kitInventoryManager: KitInventoryManager
) : Listener {
@EventHandler
fun onInventoryClick(
event: InventoryClickEvent
) {
val holder = event.inventory.holder
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 )
return
when( event.rawSlot )
{
45 -> {
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.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 )
}
}
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 kitSlots = listOf(
10, 11, 12, 13, 14, 15, 16,
19, 20, 21, 22, 23, 24, 25,
28, 29, 30, 31, 32, 33, 34,
37, 38, 39, 40, 41, 42, 43
)
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 )
plugin.chatManager.sendMessage(
player,
"kits.selected",
"{kit}" to selectedKit.displayName.content()
)
kitInventoryManager.openKitInventory( player, holder.page )
} else {
player.playSound( player.location, Sound.ENTITY_VILLAGER_NO, 1f, 1f )
}
}
}
}
}
@EventHandler
fun onInventoryDrag(
event: InventoryDragEvent
) {
val holder = event.inventory.holder
if ( holder is KitInventoryHolder )
event.isCancelled = true
}
}

View File

@@ -1,223 +0,0 @@
package club.mcscrims.speedhg.kit
import club.mcscrims.speedhg.SpeedHG
import kotlinx.coroutines.runBlocking
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.format.NamedTextColor
import net.kyori.adventure.text.format.TextDecoration
import org.bukkit.Bukkit
import org.bukkit.Material
import org.bukkit.enchantments.Enchantment
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemFlag
import org.bukkit.inventory.ItemStack
class KitInventoryManager(
private val plugin: SpeedHG,
private val kitManager: KitManager
) {
private val kitsPerPage = 28
private val rows = 6
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 holder = KitInventoryHolder( validPage )
val title = Component.text("Kits - Page $validPage/$totalPages")
.color( NamedTextColor.DARK_PURPLE )
.decoration( TextDecoration.BOLD, true )
val inventory = Bukkit.createInventory( holder, rows * 9, title )
holder.setInventory( inventory )
fillBorder( inventory )
fillKits( inventory, allKits, validPage, player )
fillNavigationItems( inventory, validPage, totalPages )
player.openInventory( inventory )
}
private fun fillBorder(
inventory: org.bukkit.inventory.Inventory
) {
val borderItem = createBorderItem()
for ( i in 0..8 )
inventory.setItem( i, borderItem )
for ( i in 45..53 )
inventory.setItem( i, borderItem )
}
private fun fillKits(
inventory: org.bukkit.inventory.Inventory,
allKits: List<AbstractKit>,
page: Int,
player: Player
) {
val startIndex = ( page - 1 ) * kitsPerPage
val endIndex = ( startIndex + kitsPerPage ).coerceAtMost( allKits.size )
val kitsOnPage = allKits.subList( startIndex, endIndex )
val selectedKit = kitManager.getSelectedKit( player )
val kitSlots = listOf(
10, 11, 12, 13, 14, 15, 16,
19, 20, 21, 22, 23, 24, 25,
28, 29, 30, 31, 32, 33, 34,
37, 38, 39, 40, 41, 42, 43
)
kitsOnPage.forEachIndexed { index, kit ->
if ( index < kitSlots.size )
{
val isSelected = selectedKit?.id == kit.id
val kitItem = createKitItem( kit, isSelected, player )
inventory.setItem(kitSlots[ index ], kitItem )
}
}
}
private fun fillNavigationItems(
inventory: org.bukkit.inventory.Inventory,
page: Int,
totalPages: Int
) {
if ( page > 1 )
inventory.setItem( 45, createPreviousPageItem() )
inventory.setItem( 49, createCloseItem() )
if ( page < totalPages )
inventory.setItem( 53, createNextPageItem() )
}
private fun createBorderItem(): ItemStack
{
val item = ItemStack( Material.GRAY_STAINED_GLASS_PANE )
val meta = item.itemMeta
meta.displayName(Component.text( " " ))
item.itemMeta = meta
return item
}
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 ))
val lore = mutableListOf<Component>()
if ( isSelected ) {
lore.add(
Component.text("✔ Currently Selected")
.color( NamedTextColor.GREEN )
.decoration( TextDecoration.ITALIC, false )
)
} else {
lore.add(
Component.text("Click to select")
.color( NamedTextColor.YELLOW )
.decoration( TextDecoration.ITALIC, false )
)
}
lore.add( Component.empty() )
kit.description.forEach { line ->
lore.add(
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 )
}
} else {
lore.add( Component.empty() )
lore.add(
Component.text("⚠ Locked")
.color( NamedTextColor.RED )
.decoration( TextDecoration.ITALIC, false )
.decoration( TextDecoration.BOLD, true )
)
}
meta.lore( lore )
meta.addItemFlags( ItemFlag.HIDE_ATTRIBUTES )
item.itemMeta = meta
return item
}
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 )
)
item.itemMeta = meta
return item
}
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 )
)
item.itemMeta = meta
return item
}
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 )
)
item.itemMeta = meta
return item
}
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

@@ -1,75 +0,0 @@
package club.mcscrims.speedhg.kit
import club.mcscrims.speedhg.SpeedHG
import org.bukkit.Material
import org.bukkit.Sound
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.block.BlockBreakEvent
import org.bukkit.event.entity.EntityDamageByEntityEvent
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.event.player.PlayerMoveEvent
class KitListener(
private val plugin: SpeedHG,
private val kitManager: KitManager
) : Listener {
@EventHandler
fun onDamage(
event: EntityDamageByEntityEvent
) {
val attacker = event.damager as? Player ?: return
val victim = event.entity as? Player ?: return
if (kitManager.getSelectedKit( attacker ) != null )
kitManager.triggerHit( attacker, victim, event )
if (kitManager.getSelectedKit( victim ) != null )
kitManager.triggerDamaged( victim, attacker, event )
}
@EventHandler
fun onPlayerInteract(
event: PlayerInteractEvent
) {
val player = event.player
if (kitManager.getSelectedKit( player ) != null )
kitManager.triggerInteract( player, event )
}
@EventHandler
fun onPlayerMove(
event: PlayerMoveEvent
) {
val player = event.player
if (kitManager.getSelectedKit( player ) != null )
kitManager.triggerMove( player, event )
}
@EventHandler
fun onAnvilBreak(
event: BlockBreakEvent
) {
if ( !plugin.gameManager.isRunning() )
return
val block = event.block
if ( block.type != Material.ANVIL ||
!block.hasMetadata( KitMetaData.IS_ANVIL.getKey() ))
return
event.isCancelled = true
block.type = Material.AIR
block.removeMetadata( KitMetaData.IS_ANVIL.getKey(), plugin )
block.world.playSound( block.location, Sound.ENTITY_IRON_GOLEM_DEATH, 3f, 3f )
plugin.chatManager.broadcast( "kits.anchor.messages.broken" )
}
}

View File

@@ -1,224 +0,0 @@
package club.mcscrims.speedhg.kit
import club.mcscrims.speedhg.SpeedHG
import club.mcscrims.speedhg.ability.AbilityContext
import club.mcscrims.speedhg.game.GameManager
import club.mcscrims.speedhg.kit.impl.AnchorKit
import club.mcscrims.speedhg.kit.impl.ArmorerKit
import club.mcscrims.speedhg.kit.impl.BlackPantherKit
import club.mcscrims.speedhg.kit.impl.BlitzcrankKit
import net.kyori.adventure.text.Component
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.event.entity.EntityDamageByEntityEvent
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.event.player.PlayerMoveEvent
import java.util.UUID
import java.util.concurrent.ConcurrentHashMap
class KitManager(
private val plugin: SpeedHG
) {
private val kits = ConcurrentHashMap<String, AbstractKit>()
private val selectedKits = ConcurrentHashMap<UUID, AbstractKit>()
fun initialize()
{
registerKit(
kitClass = AnchorKit::class.java,
id = "anchor",
displayName = plugin.chatFormatter.format( "kits.anchor.displayName" ),
description = plugin.chatFormatter.formatList( "kits.anchor.lore" ),
icon = Material.ANVIL
)
registerKit(
kitClass = ArmorerKit::class.java,
id = "armorer",
displayName = plugin.chatFormatter.format( "kits.armorer.displayName" ),
description = plugin.chatFormatter.formatList( "kits.armorer.lore" ),
icon = Material.IRON_CHESTPLATE
)
registerKit(
kitClass = BlackPantherKit::class.java,
id = "blackpanther",
displayName = plugin.chatFormatter.format( "kits.blackpanther.displayName" ),
description = plugin.chatFormatter.formatList( "kits.blackpanther.lore" ),
icon = Material.DRAGON_EGG
)
registerKit(
kitClass = BlitzcrankKit::class.java,
id = "blitzcrank",
displayName = plugin.chatFormatter.format( "kits.blitzcrank.displayName" ),
description = plugin.chatFormatter.formatList( "kits.blitzcrank.lore" ),
icon = Material.FISHING_ROD
)
}
fun registerKit(
kitClass: Class<out AbstractKit>,
id: String,
displayName: Component,
description: List<Component>,
icon: Material
) {
val constructor = kitClass.getDeclaredConstructor(
String::class.java,
Component::class.java,
List::class.java,
Material::class.java,
PlayStyle::class.java,
SpeedHG::class.java,
AbilityContext::class.java,
GameManager::class.java
)
val kit = constructor.newInstance(
id,
displayName,
description,
icon,
PlayStyle.DEFENSIVE,
plugin,
plugin.abilityContext,
plugin.gameManager
)
kit.config = plugin.kitConfig.data.getConfigForKit( kit.id )
kits[kit.id.lowercase()] = kit
plugin.logger.info("Registered kit: ${kit.displayName} (${kit.id})")
}
fun getKit(
id: String
): AbstractKit?
{
return kits[id.lowercase()]
}
fun getAllKits(): Collection<AbstractKit>
{
return kits.values
}
fun selectKit(
player: Player,
kitId: String
): Boolean
{
val kit = getKit( kitId ) ?: return false
val previousKit = selectedKits[player.uniqueId]
previousKit?.cleanup( player )
selectedKits[player.uniqueId] = kit
try {
kit.onSelect( player )
} catch (e: Exception) {
plugin.logger.severe("Error during onSelect for kit ${kit.id} and player ${player.name}: ${e.message}")
e.printStackTrace()
}
return true
}
fun getSelectedKit(
player: Player
): AbstractKit?
{
return selectedKits[player.uniqueId]
}
fun startKitForPlayer(
player: Player
) {
val kit = selectedKits[player.uniqueId] ?: return
try {
kit.onStart( player )
} catch (e: Exception) {
plugin.logger.severe("Error during onStart for kit ${kit.id} and player ${player.name}: ${e.message}")
e.printStackTrace()
}
}
fun triggerHit(
attacker: Player,
victim: Player,
event: EntityDamageByEntityEvent
) {
val kit = selectedKits[attacker.uniqueId] ?: return
try {
kit.onHit( attacker, victim, event )
} catch (e: Exception) {
plugin.logger.severe("Error during onHit for kit ${kit.id} and player ${attacker.name}: ${e.message}")
e.printStackTrace()
}
}
fun triggerDamaged(
attacker: Player,
victim: Player,
event: EntityDamageByEntityEvent
) {
val kit = selectedKits[victim.uniqueId] ?: return
try {
kit.onDamaged( attacker, victim, event )
} catch (e: Exception) {
plugin.logger.severe("Error during onDamaged for kit ${kit.id} and player ${victim.name}: ${e.message}")
e.printStackTrace()
}
}
fun triggerInteract(
player: Player,
event: PlayerInteractEvent
) {
val kit = selectedKits[player.uniqueId] ?: return
try {
kit.onInteract( player, event )
} catch (e: Exception) {
plugin.logger.severe("Error during onInteract for kit ${kit.id} and player ${player.name}: ${e.message}")
e.printStackTrace()
}
}
fun triggerMove(
player: Player,
event: PlayerMoveEvent
) {
val kit = selectedKits[player.uniqueId] ?: return
try {
kit.onMove( player, event )
} catch (e: Exception) {
plugin.logger.severe("Error during onMove for kit ${kit.id} and player ${player.name}: ${e.message}")
e.printStackTrace()
}
}
fun clearPlayerSelection(
player: Player
) {
val kit = selectedKits.remove( player.uniqueId )
kit?.cleanup( player )
}
fun clearAll()
{
selectedKits.values.forEach { kit ->
plugin.server.onlinePlayers.forEach { player ->
if ( selectedKits[player.uniqueId] == kit ) kit.cleanup( player )
}
}
selectedKits.clear()
}
}

View File

@@ -1,168 +0,0 @@
package club.mcscrims.speedhg.kit.impl
import club.mcscrims.speedhg.SpeedHG
import club.mcscrims.speedhg.SpeedHG.Companion.content
import club.mcscrims.speedhg.ability.AbilityContext
import club.mcscrims.speedhg.game.GameManager
import club.mcscrims.speedhg.kit.AbstractKit
import club.mcscrims.speedhg.kit.KitMetaData
import club.mcscrims.speedhg.kit.PlayStyle
import club.mcscrims.spigot.item.ItemBuilder
import net.kyori.adventure.text.Component
import org.bukkit.Location
import org.bukkit.Material
import org.bukkit.Sound
import org.bukkit.entity.Player
import org.bukkit.event.block.Action
import org.bukkit.event.entity.EntityDamageByEntityEvent
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.event.player.PlayerMoveEvent
import org.bukkit.inventory.ItemStack
import org.bukkit.metadata.FixedMetadataValue
import java.util.UUID
import java.util.concurrent.ConcurrentHashMap
class AnchorKit(
id: String,
displayName: Component,
description: List<Component>,
icon: Material,
playStyle: PlayStyle,
plugin: SpeedHG,
abilityContext: AbilityContext,
gameManager: GameManager
) : AbstractKit( id, displayName, description, icon, playStyle, plugin, abilityContext, gameManager ) {
private lateinit var anvilItem: ItemStack
private val extraDamage: Double = plugin.kitConfig.data.anchor[ "offensive extra damage" ]!!
private val radius = if ( playStyle == PlayStyle.DEFENSIVE ) 7.5 else 5.0
private val anvilList = ConcurrentHashMap<UUID, Location>()
override fun onSelect( player: Player ) {}
override fun onStart(
player: Player
) {
anvilItem = ItemBuilder( plugin, Material.ANVIL )
.name(plugin.messageConfig.data.getKitItemNames( "anchor", "anvil" )!![ playStyle.name.lowercase() ]!!)
.unbreakable( true )
.hideAttributes()
.build()
items.add( anvilItem )
player.inventory.setItem( 0, anvilItem )
}
override fun onHit(
attacker: Player,
victim: Player,
event: EntityDamageByEntityEvent
) {
if ( !gameManager.isRunning() )
return
if (!anvilList.contains( attacker.uniqueId ))
return
if ( playStyle != PlayStyle.OFFENSIVE )
return
event.damage += extraDamage
}
override fun onDamaged(
attacker: Player,
victim: Player,
event: EntityDamageByEntityEvent
) {
if ( !gameManager.isRunning() )
return
if (!anvilList.contains( attacker.uniqueId ))
return
victim.velocity.setX( 0.0 )
victim.velocity.setZ( 0.0 )
victim.world.playSound( victim.location, Sound.BLOCK_ANVIL_HIT, 3f, 3f )
}
override fun onInteract(
player: Player,
event: PlayerInteractEvent
) {
if ( !gameManager.isRunning() )
return
val action = event.action
if ( action != Action.RIGHT_CLICK_AIR &&
action != Action.RIGHT_CLICK_BLOCK )
return
val item = event.item ?: return
if ( item != anvilItem )
return
event.isCancelled = true
val eyeLocation = player.eyeLocation
if (eyeLocation.distance( player.location ) > radius )
{
plugin.chatManager.sendMessage( player, "kits.anchor.messages.tooFarAway" )
return
}
if (anvilList.contains( player.uniqueId ))
{
plugin.chatManager.sendMessage( player, "kits.anchor.messages.alreadyActivated" )
return
}
val result = abilityContext.canUseAbility( player, "anchor-anvil", 15 )
if ( result.missingHits > 0 )
{
plugin.chatManager.sendMessage( player, "kits.missingHits", "{hits]" to result.missingHits.toString() )
return
}
val anvilLoc = eyeLocation.toBlockLocation()
anvilLoc.add( 0.0, 1.0, 0.0 )
anvilLoc.block.type = Material.ANVIL
anvilLoc.block.setMetadata( KitMetaData.IS_ANVIL.getKey(), FixedMetadataValue( plugin, true ))
anvilList[ player.uniqueId ]= anvilLoc
plugin.schedulerManager.runLater( 20 * 30L ) {
if (anvilList.contains( player.uniqueId ))
{
anvilList.remove( player.uniqueId )
anvilLoc.block.type = Material.AIR
anvilLoc.block.removeMetadata( KitMetaData.IS_ANVIL.getKey(), plugin )
}
}
}
override fun onMove(
player: Player,
event: PlayerMoveEvent
) {
if ( !gameManager.isRunning() )
return
val anvilLoc = anvilList[ player.uniqueId ]
?: return
if (player.location.distance( anvilLoc ) <= radius )
return
player.teleport( player.location )
player.playSound( player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f )
}
}

View File

@@ -1,114 +0,0 @@
package club.mcscrims.speedhg.kit.impl
import club.mcscrims.speedhg.SpeedHG
import club.mcscrims.speedhg.ability.AbilityContext
import club.mcscrims.speedhg.game.GameManager
import club.mcscrims.speedhg.kit.AbstractKit
import club.mcscrims.speedhg.kit.PlayStyle
import net.kyori.adventure.text.Component
import org.bukkit.Material
import org.bukkit.Sound
import org.bukkit.Statistic
import org.bukkit.enchantments.Enchantment
import org.bukkit.entity.Player
import org.bukkit.event.entity.EntityDamageByEntityEvent
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.event.player.PlayerMoveEvent
import org.bukkit.inventory.ItemStack
import kotlin.math.roundToInt
class ArmorerKit(
id: String,
displayName: Component,
description: List<Component>,
icon: Material,
playStyle: PlayStyle,
plugin: SpeedHG,
abilityContext: AbilityContext,
gameManager: GameManager
) : AbstractKit( id, displayName, description, icon, playStyle, plugin, abilityContext, gameManager ) {
private val killsUntilNew: Double = plugin.kitConfig.data.armorer[ "kills until new armor" ]!!
override fun onSelect( player: Player ) {}
override fun onStart( player: Player ) {}
override fun onHit(
attacker: Player,
victim: Player,
event: EntityDamageByEntityEvent
) {
if ( !gameManager.isRunning() )
return
if ( victim.health > 0.0 )
return
val kills = attacker.getStatistic( Statistic.PLAYER_KILLS )
if (( kills.toDouble() / killsUntilNew ) % 2 != 0.0 )
return
upgradeArmor( attacker, kills )
attacker.playSound( attacker, Sound.BLOCK_NOTE_BLOCK_PLING, 1f, 1f )
}
override fun onDamaged( attacker: Player, victim: Player, event: EntityDamageByEntityEvent ) {}
override fun onInteract( player: Player, event: PlayerInteractEvent ) {}
override fun onMove( player: Player, event: PlayerMoveEvent ) {}
private fun upgradeArmor(
player: Player,
killCount: Int
) {
val kills = killsUntilNew.roundToInt()
val armorType = when( killCount / kills )
{
1, 2 -> ArmorType.LEATHER
3, 4 -> ArmorType.CHAINMAIL
5, 6 -> ArmorType.GOLD
7, 8 -> ArmorType.IRON
else -> return
}
val enchanted = ( killCount / kills ) % 2 == 0
val armor = createArmor( armorType, enchanted )
player.inventory.armorContents = arrayOf( null, armor[0], null, armor[1] )
if ( !enchanted )
{
plugin.chatManager.sendMessage( player, "kits.armorer.messages.upgrade.normal", "{armorType}" to armorType.name )
return
}
plugin.chatManager.sendMessage( player, "kits.armorer.upgrade.enchanted" )
}
private fun createArmor(
type: ArmorType,
enchanted: Boolean
) = listOf(
ItemStack( type.materialChestplate ).apply {
if ( enchanted ) addEnchantment( Enchantment.PROTECTION, 1 )
},
ItemStack( type.materialBoots ).apply {
if ( enchanted ) addEnchantment( Enchantment.PROTECTION, 1 )
}
)
enum class ArmorType(
val materialChestplate: Material,
val materialBoots: Material
) {
LEATHER( Material.LEATHER_CHESTPLATE, Material.LEATHER_BOOTS ),
CHAINMAIL( Material.CHAINMAIL_CHESTPLATE, Material.CHAINMAIL_BOOTS ),
GOLD( Material.GOLDEN_CHESTPLATE, Material.GOLDEN_BOOTS ),
IRON( Material.IRON_CHESTPLATE, Material.IRON_BOOTS )
}
}

View File

@@ -1,276 +0,0 @@
package club.mcscrims.speedhg.kit.impl
import club.mcscrims.speedhg.SpeedHG
import club.mcscrims.speedhg.ability.AbilityContext
import club.mcscrims.speedhg.game.GameManager
import club.mcscrims.speedhg.kit.AbstractKit
import club.mcscrims.speedhg.kit.KitMetaData
import club.mcscrims.speedhg.kit.PlayStyle
import club.mcscrims.spigot.item.ItemBuilder
import club.mcscrims.spigot.util.GroundDetector
import net.kyori.adventure.text.Component
import org.bukkit.Bukkit
import org.bukkit.GameMode
import org.bukkit.Material
import org.bukkit.Particle
import org.bukkit.entity.EnderPearl
import org.bukkit.entity.EntityType
import org.bukkit.entity.Player
import org.bukkit.event.block.Action
import org.bukkit.event.entity.EntityDamageByEntityEvent
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.event.player.PlayerMoveEvent
import org.bukkit.inventory.ItemStack
import org.bukkit.metadata.FixedMetadataValue
import org.bukkit.potion.PotionEffect
import org.bukkit.potion.PotionEffectType
import org.bukkit.scheduler.BukkitRunnable
import org.bukkit.util.Vector
import kotlin.math.max
import kotlin.math.roundToInt
class BlackPantherKit(
id: String,
displayName: Component,
description: List<Component>,
icon: Material,
playStyle: PlayStyle,
plugin: SpeedHG,
abilityContext: AbilityContext,
gameManager: GameManager
) : AbstractKit( id, displayName, description, icon, playStyle, plugin, abilityContext, gameManager ) {
private lateinit var blackDye: ItemStack
private lateinit var blazePowder: ItemStack
private val extraDamageAddition = plugin.kitConfig.data.blackPanther[ "extra damage on top" ]!!
private val defaultRadius = plugin.kitConfig.data.blackPanther[ "default hit radius" ]!!
private val explosionMultiplier = plugin.kitConfig.data.blackPanther[ "explosion multiplier" ]!!
override fun onSelect( player: Player ) {}
override fun onStart(
player: Player
) {
when( playStyle )
{
PlayStyle.DEFENSIVE ->
{
blackDye = ItemBuilder( plugin, Material.BLACK_DYE )
.name(plugin.messageConfig.data.getKitItemNames( "blackpanther", "blackDye" )!![ "null" ]!!)
.unbreakable( true )
.hideAttributes()
.build()
items.add( blackDye )
player.inventory.setItem( 0, blackDye )
}
PlayStyle.OFFENSIVE ->
{
blackDye = ItemBuilder( plugin, Material.BLACK_DYE )
.name(plugin.messageConfig.data.getKitItemNames( "blackpanther", "blackDye" )!![ playStyle.name.lowercase() ]!!)
.unbreakable( true )
.hideAttributes()
.build()
blazePowder = ItemBuilder( plugin, Material.BLAZE_POWDER )
.name(plugin.messageConfig.data.getKitItemNames( "blackpanther", "blazePowder" )!![ playStyle.name.lowercase() ]!!)
.unbreakable( true )
.hideAttributes()
.build()
items.addAll(listOf( blackDye, blazePowder ))
player.inventory.setItem( 0, blackDye )
player.inventory.setItem( 1, blazePowder )
}
}
}
override fun onHit(
attacker: Player,
victim: Player,
event: EntityDamageByEntityEvent
) {
if ( !gameManager.isRunning() )
return
if (!attacker.hasMetadata( KitMetaData.BP_EXTRA_DAMAGE.getKey() ))
return
event.damage += extraDamageAddition
}
override fun onDamaged( attacker: Player, victim: Player, event: EntityDamageByEntityEvent ) {}
override fun onInteract(
player: Player,
event: PlayerInteractEvent
) {
if ( !gameManager.isRunning() )
return
val action = event.action
if ( action != Action.RIGHT_CLICK_AIR &&
action != Action.RIGHT_CLICK_BLOCK )
return
val item = event.item ?: return
if ( item != blackDye &&
item != blazePowder )
return
event.isCancelled = true
when( item.type )
{
Material.BLACK_DYE ->
{
val result = abilityContext.canUseAbility( player, "blackDye-blackPanther", 15 )
if ( result.missingHits > 0 )
{
plugin.chatManager.sendMessage( player, "kits.missingHits", "{hits]" to result.missingHits.toString() )
return
}
if ( playStyle == PlayStyle.DEFENSIVE )
{
launchAndDash( player )
return
}
push( player )
}
Material.BLAZE_POWDER ->
{
val result = abilityContext.canUseAbility( player, "blazePowder-blackPanther", 15 )
if ( result.missingHits > 0 )
{
plugin.chatManager.sendMessage( player, "kits.missingHits", "{hits]" to result.missingHits.toString() )
return
}
extraDamage( player )
}
else -> return
}
}
override fun onMove( player: Player, event: PlayerMoveEvent ) {}
private fun push(
player: Player
) {
plugin.getAlivePlayers().stream()
.filter { it != player }
.filter { it.location.distance( player.location ) <= defaultRadius }
.forEach { nearby ->
val pushDirection = nearby.location.toVector().subtract( player.location.toVector() ).normalize()
pushDirection.multiply( 1.0 )
pushDirection.setY( 0.5 )
nearby.velocity = pushDirection
val enderPearl = player.world.spawnEntity( player.location, EntityType.ENDER_PEARL ) as EnderPearl
enderPearl.velocity = pushDirection
enderPearl.setMetadata( KitMetaData.IS_BLACK_PANTHER.getKey(), FixedMetadataValue( plugin, true ))
object : BukkitRunnable()
{
override fun run()
{
if (GroundDetector.isOnGround( nearby ))
{
this.cancel()
return
}
nearby.world.spawnParticle( Particle.END_ROD, nearby.location, 5, 0.2, 0.2, 0.2 )
}
}.runTaskTimer( plugin, 0L, 2L )
}
}
private fun launchAndDash(
player: Player,
upwardVelocity: Double = 2.2,
waitTicks: Long = 60L,
dashSpeed: Double = 2.8,
horizontalOnly: Boolean = true,
yBoost: Double = 0.2,
noFallDamageMillis: Double = 1.0
) {
if ( !player.isOnline ) return
if ( player.isInsideVehicle ) player.leaveVehicle()
if ( player.gameMode == GameMode.SPECTATOR ) return
player.velocity = Vector( 0.0, upwardVelocity, 0.0 )
player.fallDistance = 0f
if ( noFallDamageMillis > 0 )
player.addPotionEffect(PotionEffect( PotionEffectType.RESISTANCE, ( noFallDamageMillis * 20 ).toInt(), 999, false, false, false ))
Bukkit.getScheduler().runTaskLater( plugin, { ->
val p = Bukkit.getPlayer( player.uniqueId ) ?: return@runTaskLater
if ( !p.isOnline ) return@runTaskLater
var dir = p.eyeLocation.direction
if ( horizontalOnly ) dir = Vector( dir.x, 0.0, dir.z )
dir = if ( dir.lengthSquared() < 1e-6 ) Vector( 0, 0, 0 ) else dir.normalize()
val dash = dir.multiply( dashSpeed ).add(Vector( 0.0, yBoost, 0.0 ))
p.velocity = dash
}, max( 0L, waitTicks ))
object : BukkitRunnable()
{
override fun run()
{
if (GroundDetector.isOnGround( player ))
{
player.world.createExplosion(
player.location,
explosionMultiplier.roundToInt().toFloat(),
false, true
)
val alivePlayers = plugin.getAlivePlayers().stream()
.filter { it != player }
.filter { it.location.distance( player.location ) <= defaultRadius }
.toList()
alivePlayers.forEach { nearby ->
nearby.damage( 6.0, player )
}
plugin.chatManager.sendMessage( player, "kits.blackPanther.messages.wakandaForever.hit", "{hit}" to alivePlayers.size.toString() )
this.cancel()
}
}
}.runTaskTimer( plugin, max( 0L, waitTicks ) + 5L, 5L )
}
private fun extraDamage(
player: Player
) {
player.setMetadata( KitMetaData.BP_EXTRA_DAMAGE.getKey(), FixedMetadataValue( plugin, true ))
plugin.chatManager.sendMessage( player, "kits.blackPanther.messages.extraDamage.activated" )
plugin.schedulerManager.runLater( 12 * 30L ) {
player.removeMetadata( KitMetaData.BP_EXTRA_DAMAGE.getKey(), plugin )
plugin.chatManager.sendMessage( player, "kits.blackPanther.messages.extraDamage.deactivated" )
}
}
}

View File

@@ -1,234 +0,0 @@
package club.mcscrims.speedhg.kit.impl
import club.mcscrims.speedhg.SpeedHG
import club.mcscrims.speedhg.SpeedHG.Companion.content
import club.mcscrims.speedhg.ability.AbilityContext
import club.mcscrims.speedhg.game.GameManager
import club.mcscrims.speedhg.kit.AbstractKit
import club.mcscrims.speedhg.kit.PlayStyle
import club.mcscrims.speedhg.util.DirectionUtil
import club.mcscrims.spigot.chat.getDisplayName
import club.mcscrims.spigot.item.ItemBuilder
import net.kyori.adventure.text.Component
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.event.block.Action
import org.bukkit.event.entity.EntityDamageByEntityEvent
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.event.player.PlayerMoveEvent
import org.bukkit.inventory.ItemStack
import org.bukkit.potion.PotionEffect
import org.bukkit.potion.PotionEffectType
import org.bukkit.util.Vector
class BlitzcrankKit(
id: String,
displayName: Component,
description: List<Component>,
icon: Material,
playStyle: PlayStyle,
plugin: SpeedHG,
abilityContext: AbilityContext,
gameManager: GameManager
) : AbstractKit( id, displayName, description, icon, playStyle, plugin, abilityContext, gameManager ) {
override fun onSelect( player: Player ) {}
private lateinit var hotsItem: ItemStack
private lateinit var fishingRodItem: ItemStack
private lateinit var pufferfishItem: ItemStack
override fun onStart(
player: Player
) {
hotsItem = ItemBuilder( plugin, Material.HEART_OF_THE_SEA )
.name(plugin.messageConfig.data.getKitItemNames( "blitzcrank", "hots" )!![ playStyle.name.lowercase() ]!!)
.unbreakable( true )
.hideAttributes()
.build()
items.add( hotsItem )
player.inventory.setItem( 0, hotsItem )
when( playStyle )
{
PlayStyle.DEFENSIVE ->
{
fishingRodItem = ItemBuilder( plugin, Material.FISHING_ROD )
.name(plugin.messageConfig.data.getKitItemNames( "blitzcrank", "fishingrod" )!![ playStyle.name.lowercase() ]!!)
.unbreakable( true )
.hideAttributes()
.build()
items.add( fishingRodItem )
player.inventory.setItem( 1, fishingRodItem )
}
PlayStyle.OFFENSIVE ->
{
pufferfishItem = ItemBuilder( plugin, Material.PUFFERFISH )
.name(plugin.messageConfig.data.getKitItemNames( "blitzcrank", "pufferfish" )!![ playStyle.name.lowercase() ]!!)
.unbreakable( true )
.hideAttributes()
.build()
items.add( pufferfishItem )
player.inventory.setItem( 1, pufferfishItem )
}
}
}
override fun onHit( attacker: Player, victim: Player, event: EntityDamageByEntityEvent ) {}
override fun onDamaged( attacker: Player, victim: Player, event: EntityDamageByEntityEvent ) {}
// Ultimate
private val ultimateDamage = plugin.kitConfig.data.blitzcrank[ "ultimate damage" ]!!
private val ultimateRadius = plugin.kitConfig.data.blitzcrank[ "ultimate radius" ]!!
private val ultimateStunDuration = plugin.kitConfig.data.blitzcrank[ "ultimate stun duration" ]!!
// Hook
private val hookRange = plugin.kitConfig.data.blitzcrank[ "hook range" ]!!
// Stun
private val stunHeight = plugin.kitConfig.data.blitzcrank[ "stun height" ]!!
private val stunRadius = plugin.kitConfig.data.blitzcrank[ "stun radius" ]!!
private val stunSlowDuration = plugin.kitConfig.data.blitzcrank[ "stun slow duration" ]!!
override fun onInteract(
player: Player,
event: PlayerInteractEvent
) {
if ( !gameManager.isRunning() )
return
val action = event.action
if ( action != Action.RIGHT_CLICK_AIR &&
action != Action.RIGHT_CLICK_BLOCK )
return
val item = event.item ?: return
if ( item != hotsItem &&
item != fishingRodItem &&
item != pufferfishItem )
return
when( item.type )
{
Material.HEART_OF_THE_SEA ->
{
val result = abilityContext.canUseAbility( player, "hots-blitzcrank", 15 )
if ( result.missingHits > 0 )
{
plugin.chatManager.sendMessage( player, "kits.missingHits", "{hits]" to result.missingHits.toString() )
return
}
ultimate( player, ultimateRadius )
}
Material.FISHING_ROD ->
{
val result = abilityContext.canUseAbility( player, "hook-blitzcrank", 15 )
if ( result.missingHits > 0 )
{
plugin.chatManager.sendMessage( player, "kits.missingHits", "{hits]" to result.missingHits.toString() )
return
}
hookPlayer( player )
}
Material.PUFFERFISH ->
{
val result = abilityContext.canUseAbility( player, "stun-blitzcrank", 15 )
if ( result.missingHits > 0 )
{
plugin.chatManager.sendMessage( player, "kits.missingHits", "{hits]" to result.missingHits.toString() )
return
}
stunNearby( player, stunRadius )
}
else -> return
}
}
override fun onMove( player: Player, event: PlayerMoveEvent ) {}
private fun ultimate(
player: Player,
radius: Double
) {
val nearbyPlayers = player.world.getNearbyPlayers( player.location, radius )
nearbyPlayers.forEach { nearby ->
nearby.damage( ultimateDamage, player )
nearby.addPotionEffect(PotionEffect(
PotionEffectType.SLOWNESS,
ultimateStunDuration.toInt() * 20,
255,
false,
false,
false
))
plugin.chatManager.sendMessage( nearby, "kits.blitzcrank.messages.ultimate.target", "{player}" to player.getDisplayName )
}
plugin.chatManager.sendMessage( player, "kits.blitzcrank.messages.ultimate.player", "{nearby}" to nearbyPlayers.size.toString() )
}
private fun hookPlayer(
player: Player
) {
val target = DirectionUtil.getTargetPlayerInLineOfSight( player, hookRange, 0.5 )
if ( target == null )
{
plugin.chatManager.sendMessage( player, "kits.blitzcrank.messages.no_player_in_sight" )
return
}
val hookDirection = target.location.toVector().add( player.location.toVector() ).normalize()
hookDirection.multiply( 1.0 )
hookDirection.setY( 0.5 )
target.velocity = hookDirection
plugin.chatManager.sendMessage( player, "kits.blitzcrank.messages.hook.player", "{player}" to target.getDisplayName )
plugin.chatManager.sendMessage( target, "kits.blitzcrank.messages.hook.target" )
}
private fun stunNearby(
player: Player,
radius: Double
) {
val nearbyPlayers = player.world.getNearbyPlayers( player.location, radius )
nearbyPlayers.forEach { nearby ->
val velocity = nearby.velocity
velocity.add(Vector( 0.0, stunHeight, 0.0 ))
nearby.velocity = velocity
nearby.addPotionEffect(PotionEffect(
PotionEffectType.SLOWNESS,
20 * stunSlowDuration.toInt(),
4, false, false, false
))
plugin.chatManager.sendMessage( nearby, "kits.blitzcrank.messages.stun.target" )
}
plugin.chatManager.sendMessage( player, "kits.blitzcrank.messages.stun.player", "{nearby}" to nearbyPlayers.size.toString() )
}
}