From 2c10e3e7fd8ec28368ad67fdce4b541c638beb14 Mon Sep 17 00:00:00 2001 From: Laurin <100531026+TDSTOS@users.noreply.github.com> Date: Thu, 4 Dec 2025 15:01:10 +0100 Subject: [PATCH] Add new game states --- build.gradle.kts | 4 +- .../kotlin/club/mcscrims/speedhg/SpeedHG.kt | 5 + .../mcscrims/speedhg/config/PluginConfig.kt | 62 ++++- .../club/mcscrims/speedhg/game/GameManager.kt | 22 +- .../club/mcscrims/speedhg/game/GameState.kt | 10 +- .../speedhg/game/impl/ImmunityState.kt | 252 ++++++++++++++++++ .../speedhg/game/impl/PreStartState.kt | 194 ++++++++++++++ .../speedhg/game/impl/WaitingState.kt | 121 +++++++++ .../mcscrims/speedhg/util/DirectionUtil.kt | 50 ++++ src/main/resources/config.yml | 30 ++- 10 files changed, 724 insertions(+), 26 deletions(-) create mode 100644 src/main/kotlin/club/mcscrims/speedhg/game/impl/ImmunityState.kt create mode 100644 src/main/kotlin/club/mcscrims/speedhg/game/impl/PreStartState.kt create mode 100644 src/main/kotlin/club/mcscrims/speedhg/game/impl/WaitingState.kt create mode 100644 src/main/kotlin/club/mcscrims/speedhg/util/DirectionUtil.kt diff --git a/build.gradle.kts b/build.gradle.kts index 35098f3..7c01a6d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -37,8 +37,8 @@ dependencies { compileOnly("net.luckperms:api:5.4") - implementation("club.mcscrims:core:1.4.1") - implementation("club.mcscrims:spigot:1.4.1") + implementation("club.mcscrims:core:1.4.2") + implementation("club.mcscrims:spigot:1.4.2") compileOnly("io.papermc.paper:paper-api:1.21.1-R0.1-SNAPSHOT") paperweight.paperDevBundle("1.21.1-R0.1-SNAPSHOT") diff --git a/src/main/kotlin/club/mcscrims/speedhg/SpeedHG.kt b/src/main/kotlin/club/mcscrims/speedhg/SpeedHG.kt index 6b962c0..216ae65 100644 --- a/src/main/kotlin/club/mcscrims/speedhg/SpeedHG.kt +++ b/src/main/kotlin/club/mcscrims/speedhg/SpeedHG.kt @@ -12,6 +12,7 @@ import club.mcscrims.speedhg.game.GameManager import club.mcscrims.spigot.chat.ChatFormatter import club.mcscrims.spigot.chat.ChatManager import club.mcscrims.spigot.network.SpigotNetworkManager +import club.mcscrims.spigot.scheduler.SchedulerManager import com.mongodb.client.model.Indexes import kotlinx.coroutines.runBlocking import net.luckperms.api.LuckPerms @@ -35,6 +36,7 @@ class SpeedHG : JavaPlugin() { internal lateinit var statsRepository: StatsRepository internal lateinit var networkManager: SpigotNetworkManager + internal lateinit var schedulerManager: SchedulerManager internal lateinit var gameManager: GameManager @@ -57,7 +59,10 @@ class SpeedHG : JavaPlugin() { chatManager = ChatManager.withCustomConfig( this, chatFormatter ) chatManager.initialize() + schedulerManager = SchedulerManager( this ) + gameManager = GameManager( this ) + gameManager.initialize() setupLuckPerms() } diff --git a/src/main/kotlin/club/mcscrims/speedhg/config/PluginConfig.kt b/src/main/kotlin/club/mcscrims/speedhg/config/PluginConfig.kt index 4dabb9d..c9a6c6c 100644 --- a/src/main/kotlin/club/mcscrims/speedhg/config/PluginConfig.kt +++ b/src/main/kotlin/club/mcscrims/speedhg/config/PluginConfig.kt @@ -1,9 +1,13 @@ package club.mcscrims.speedhg.config +import club.mcscrims.core.config.ConfigData +import club.mcscrims.core.config.DurationEntry +import club.mcscrims.core.config.DurationType import club.mcscrims.core.config.annotations.ConfigClass import club.mcscrims.core.config.annotations.ConfigField import club.mcscrims.core.config.annotations.DefaultValue import club.mcscrims.core.network.NetworkConfig +import club.mcscrims.speedhg.SpeedHG @ConfigClass( name = "config", @@ -55,7 +59,7 @@ data class PluginConfig( val minimumPlayers: Int = 8, val competitiveGame: Boolean = false, val competitiveCommands: List = emptyList(), - val playerState: Map = getPlayerStates(), + val playerStates: Map = getPlayerStates(), val recraftNerf: Map = getRecraftNerf(), val teams: Map = getTeams(), val blockedKits: List = emptyList(), @@ -63,16 +67,56 @@ data class PluginConfig( val perks: Map = getPerks() ) + fun isDurationIncreasing( + entry: DurationEntry + ): Boolean + { + return entry.type == DurationType.INCREASING + } + + fun getDuration( + playerState: String + ): DurationEntry + { + return SpeedHG.instance.pluginConfig.parseDuration( "game.playerStates.$playerState.duration" ) + } + + data class StateConfig( + val duration: Any, + val scoreboard: String + ) + } private fun getPlayerStates() = mapOf( - "waiting" to "Waiting - %time%", - "pre_start" to "Waiting - %time%", - "immunity" to "Playing - %time%", - "battle" to "Playing - %time%", - "feast" to "Playing - %time%", - "deathmatch" to "Playing - %time%", - "end" to "Ending - %time%", + "waiting" to PluginConfig.StateConfig( + DurationEntry( DurationType.FIXED, -1 ), + "Waiting - %time%" + ), + "pre_start" to PluginConfig.StateConfig( + DurationEntry( DurationType.FIXED, 300 ), + "Waiting - %time%" + ), + "immunity" to PluginConfig.StateConfig( + DurationEntry( DurationType.FIXED, 90 ), + "Playing - %time%" + ), + "battle" to PluginConfig.StateConfig( + DurationEntry( DurationType.INCREASING ), + "Playing - %time%" + ), + "feast" to PluginConfig.StateConfig( + DurationEntry( DurationType.FIXED, 300 ), + "Playing - %time%" + ), + "deathmatch" to PluginConfig.StateConfig( + DurationEntry( DurationType.INCREASING ), + "Playing - %time%" + ), + "end" to PluginConfig.StateConfig( + DurationEntry( DurationType.FIXED, 60 ), + "Ending - %time%" + ), ) private fun getRecraftNerf() = mapOf( @@ -101,4 +145,4 @@ private fun getAnnouncementConfiguration() = mapOf( "enabled" to true, "after" to 10, "minimumPlayers" to 6 -) +) \ No newline at end of file diff --git a/src/main/kotlin/club/mcscrims/speedhg/game/GameManager.kt b/src/main/kotlin/club/mcscrims/speedhg/game/GameManager.kt index 42e0094..c568108 100644 --- a/src/main/kotlin/club/mcscrims/speedhg/game/GameManager.kt +++ b/src/main/kotlin/club/mcscrims/speedhg/game/GameManager.kt @@ -1,13 +1,31 @@ package club.mcscrims.speedhg.game -import org.bukkit.plugin.java.JavaPlugin +import club.mcscrims.speedhg.SpeedHG +import club.mcscrims.speedhg.game.impl.WaitingState class GameManager( - private val plugin: JavaPlugin + private val plugin: SpeedHG ) { private var currentState: GameState? = null + fun initialize() + { + currentState = WaitingState( + this, + plugin, + plugin.schedulerManager, + plugin.pluginConfig.data.getDuration( "waiting" ).seconds + ) + + try { + currentState?.onEnter( null ) + } catch ( e: Exception ) { + plugin.logger.severe("Error during onEnter for state ${currentState?.name}: ${e.message}") + e.printStackTrace() + } + } + fun transitionTo( nextState: GameState ) { diff --git a/src/main/kotlin/club/mcscrims/speedhg/game/GameState.kt b/src/main/kotlin/club/mcscrims/speedhg/game/GameState.kt index 5561a20..bf6d5de 100644 --- a/src/main/kotlin/club/mcscrims/speedhg/game/GameState.kt +++ b/src/main/kotlin/club/mcscrims/speedhg/game/GameState.kt @@ -8,7 +8,7 @@ import org.bukkit.entity.Player import org.bukkit.event.HandlerList import org.bukkit.event.Listener -open class GameState( +abstract class GameState( val name: String, protected val gameManager: GameManager, protected val plugin: SpeedHG, @@ -31,11 +31,11 @@ open class GameState( startTicking() } - open fun onTick() {} + abstract fun onTick() - open fun onEndOfDuration() {} + abstract fun onEndOfDuration() - open fun onExit( + open fun onExit( next: GameState? ) { isActive = false @@ -64,7 +64,7 @@ open class GameState( { remainingSeconds-- - if ( remainingSeconds <= 0) + if ( remainingSeconds == 0) try { onEndOfDuration() } catch ( e: Exception ) { diff --git a/src/main/kotlin/club/mcscrims/speedhg/game/impl/ImmunityState.kt b/src/main/kotlin/club/mcscrims/speedhg/game/impl/ImmunityState.kt new file mode 100644 index 0000000..8165400 --- /dev/null +++ b/src/main/kotlin/club/mcscrims/speedhg/game/impl/ImmunityState.kt @@ -0,0 +1,252 @@ +package club.mcscrims.speedhg.game.impl + +import club.mcscrims.speedhg.SpeedHG +import club.mcscrims.speedhg.game.GameManager +import club.mcscrims.speedhg.game.GameState +import club.mcscrims.speedhg.game.impl.PreStartState.AnnouncementType +import club.mcscrims.speedhg.util.DirectionUtil +import club.mcscrims.spigot.scheduler.SchedulerManager +import org.bukkit.Bukkit +import org.bukkit.Material +import org.bukkit.Sound +import org.bukkit.entity.Player +import org.bukkit.event.Event +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.block.Action +import org.bukkit.event.block.BlockBreakEvent +import org.bukkit.event.entity.EntityDamageEvent +import org.bukkit.event.entity.FoodLevelChangeEvent +import org.bukkit.event.inventory.CraftItemEvent +import org.bukkit.event.player.PlayerDropItemEvent +import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.inventory.ItemStack +import org.bukkit.potion.PotionEffect +import org.bukkit.potion.PotionEffectType + +class ImmunityState( + gameManager: GameManager, + plugin: SpeedHG, + schedulerManager: SchedulerManager, + durationSeconds: Int? = null +) : GameState( "immunity", gameManager, plugin, schedulerManager, durationSeconds ), Listener { + + override fun onEnter( + previous: GameState? + ) { + super.onEnter( previous ) + registerListener( this ) + + val effects = listOf( + PotionEffect( PotionEffectType.HASTE, durationSeconds?.times( 20 ) ?: 0, 0 ), + PotionEffect( PotionEffectType.SPEED, durationSeconds?.times( 20 ) ?: 0, 0 ) + ) + + val players = Bukkit.getOnlinePlayers() + players.forEach { it.addPotionEffects( effects ) } + + for ( player in players ) + { + player.inventory.clear() + player.inventory.armorContents = emptyArray() + + player.inventory.setItem( 8, ItemStack( Material.COMPASS )) + + TODO( "Give kits and perks" ) + } + + broadcast( "gameStates.immunity.warnings.butterfly" ) + + TODO( "register kits & perks" ) + } + + override fun onTick() + { + when( durationSeconds ) + { + 180 -> announce( AnnouncementType.MINUTES, 3 ) + 120 -> announce( AnnouncementType.MINUTES, 2 ) + 60 -> announce( AnnouncementType.MINUTES, 1 ) + 30 -> announce( AnnouncementType.SECONDS, 30 ) + 15 -> announce( AnnouncementType.SECONDS, 15 ) + 10 -> announce( AnnouncementType.SECONDS, 10 ) + 5 -> announce( AnnouncementType.SECONDS, 5 ) + 4 -> announce( AnnouncementType.SECONDS, 4 ) + 3 -> announce( AnnouncementType.SECONDS, 3 ) + 2 -> announce( AnnouncementType.SECONDS, 2 ) + 1 -> announce( AnnouncementType.SECONDS, 1 ) + 0 -> + { + broadcast( "gameStates.immunity.ended" ) + gameManager.transitionTo( TODO() ) + } + } + } + + override fun onEndOfDuration() {} + + private fun announce( + type: AnnouncementType, + time: Int + ) { + val arg = if ( type == AnnouncementType.MINUTES ) "M" else "S" + broadcast( "gameStates.immunity.ending$arg", "{time}" to time.toString() ) + } + + @EventHandler + fun onInteractCompass( + event: PlayerInteractEvent + ) { + val player = event.player + val action = event.action + + if ( action != Action.RIGHT_CLICK_BLOCK && + action != Action.RIGHT_CLICK_AIR ) + return + + val item = event.item + ?: return + + if ( item.type != Material.COMPASS ) + return + + val nearestPlayer = Bukkit.getOnlinePlayers().stream() + .filter { other -> other != player } + .map { other -> other.location.distance( player.location ) to other } + .filter { pair -> pair.first > 5.0 } + .toList() + .firstOrNull() + ?.second + + if ( nearestPlayer == null ) + { + plugin.chatManager.sendMessage( player, "compass.no_nearby_players" ) + return + } + + player.compassTarget = nearestPlayer.location + + val direction = DirectionUtil.getDirectionToPlayer( player, nearestPlayer ) + val actionBar = plugin.chatFormatter.format( "compass.actionBar" ) + actionBar.replaceText { it.match( "" ).replacement( direction ).once() } + plugin.chatManager.sendInteractiveMessage( player, actionBar ) + } + + @EventHandler + fun onDropItem( + event: PlayerDropItemEvent + ) { + val player = event.player + + TODO( "Add kit & perk check" ) + } + + @EventHandler + fun onCraftItem( + event: CraftItemEvent + ) { + val player = event.whoClicked + + if ( player !is Player ) + return + + val item = event.recipe.result + + if ( item.type == Material.SHIELD ) + { + if ( event.isShiftClick ) + { + plugin.chatManager.sendMessage( player, "craft.no_siftclick" ) + player.playSound( player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f ) + return + } + + event.result = Event.Result.DENY + + plugin.chatManager.sendMessage( player, "craft.no_shield" ) + player.playSound( player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f ) + return + } + + if (!item.type.name.contains( "iron", true )) + return + + if ( event.isShiftClick ) + { + plugin.chatManager.sendMessage( player, "craft.no_siftclick" ) + player.playSound( player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f ) + return + } + + event.result = Event.Result.DENY + + plugin.chatManager.sendMessage( player, "craft.no_iron_before_feast" ) + player.playSound( player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f ) + } + + @EventHandler + fun onBlockBreak( + event: BlockBreakEvent + ) { + val player = event.player + val block = event.block + + if ( block.type == Material.DIAMOND_ORE ) + { + event.isCancelled = true + block.type = Material.AIR + block.tick() + + plugin.chatManager.sendMessage( player, "build.no_diamonds" ) + player.playSound( player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f ) + return + } + + if ( block.type == Material.IRON_ORE ) + { + event.isCancelled = true + + plugin.chatManager.sendMessage( player, "build.no_iron_before_feast" ) + player.playSound( player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f ) + return + } + } + + @EventHandler + fun onInteract( + event: PlayerInteractEvent + ) { + val player = event.player + val action = event.action + + if ( action != Action.RIGHT_CLICK_BLOCK && + action != Action.RIGHT_CLICK_AIR ) + return + + val item = event.item + ?: return + + TODO( "Check for kit items" ) + } + + @EventHandler + fun onEntityDamage( + event: EntityDamageEvent + ) { + if ( gameManager.getCurrentState() != this ) + return + + event.isCancelled = true + } + + @EventHandler + fun onFoodLevelChange( + event: FoodLevelChangeEvent + ) { + if ( gameManager.getCurrentState() != this ) + return + + event.isCancelled = true + } + +} \ No newline at end of file diff --git a/src/main/kotlin/club/mcscrims/speedhg/game/impl/PreStartState.kt b/src/main/kotlin/club/mcscrims/speedhg/game/impl/PreStartState.kt new file mode 100644 index 0000000..45798aa --- /dev/null +++ b/src/main/kotlin/club/mcscrims/speedhg/game/impl/PreStartState.kt @@ -0,0 +1,194 @@ +package club.mcscrims.speedhg.game.impl + +import club.mcscrims.speedhg.SpeedHG +import club.mcscrims.speedhg.game.GameManager +import club.mcscrims.speedhg.game.GameState +import club.mcscrims.spigot.scheduler.SchedulerManager +import org.bukkit.Bukkit +import org.bukkit.Location +import org.bukkit.Sound +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.block.BlockBreakEvent +import org.bukkit.event.block.BlockPlaceEvent +import org.bukkit.event.block.LeavesDecayEvent +import org.bukkit.event.entity.EntityDamageEvent +import org.bukkit.event.entity.FoodLevelChangeEvent +import org.bukkit.event.player.PlayerAttemptPickupItemEvent +import org.bukkit.event.player.PlayerDropItemEvent + +class PreStartState( + gameManager: GameManager, + plugin: SpeedHG, + schedulerManager: SchedulerManager, + durationSeconds: Int? = null +) : GameState( "pre_start", gameManager, plugin, schedulerManager, durationSeconds ), Listener { + + private lateinit var previous: GameState + + override fun onEnter( + previous: GameState? + ) { + super.onEnter( previous ) + registerListener( this ) + + if ( previous != null ) + this.previous = previous + } + + var isStarting: Boolean = false + + override fun onTick() + { + val playerSize = Bukkit.getOnlinePlayers().size + + if ( playerSize < plugin.pluginConfig.data.game.minimumPlayers ) + { + isStarting = false + transitionToPrevious() + } + else isStarting = true + + if ( !isStarting ) + return + + if ( durationSeconds == 15 ) + teleport() + + when( durationSeconds ) + { + 300 -> announce( AnnouncementType.MINUTES, 5 ) + 240 -> announce( AnnouncementType.MINUTES, 4 ) + 180 -> announce( AnnouncementType.MINUTES, 3 ) + 120 -> announce( AnnouncementType.MINUTES, 2 ) + 60 -> announce( AnnouncementType.MINUTES, 1 ) + 30 -> announce( AnnouncementType.SECONDS, 30 ) + 15 -> announce( AnnouncementType.SECONDS, 15 ) + 10 -> announce( AnnouncementType.SECONDS, 10 ) + 5 -> announce( AnnouncementType.SECONDS, 5 ) + 4 -> announce( AnnouncementType.SECONDS, 4 ) + 3 -> announce( AnnouncementType.SECONDS, 3 ) + 2 -> announce( AnnouncementType.SECONDS, 2 ) + 1 -> announce( AnnouncementType.SECONDS, 1 ) + 0 -> + { + broadcast( "gameStates.preStart.started" ) + isStarting = false + gameManager.transitionTo(ImmunityState( gameManager, plugin, schedulerManager, plugin.pluginConfig.data.getDuration( "immunity" ).seconds )) + } + } + } + + override fun onExit( + next: GameState? + ) { + super.onExit( next ) + Bukkit.getOnlinePlayers().forEach { it.inventory.clear() } + } + + override fun onEndOfDuration() {} + + private fun announce( + type: AnnouncementType, + time: Int + ) { + val arg = if ( type == AnnouncementType.MINUTES ) "M" else "S" + broadcast( "gameStates.preStart.starting$arg", "{time}" to time.toString() ) + } + + private fun teleport() + { + for ( player in Bukkit.getOnlinePlayers() ) + { + val world = player.world + val loc = Location( world, 0.0, world.getHighestBlockYAt( 0, 0 ).toDouble(), 0.0 ) + player.teleport( loc ) + } + } + + private fun transitionToPrevious() + { + if ( ::previous.isInitialized ) + { + gameManager.transitionTo( previous ) + return + } + + gameManager.transitionTo(WaitingState( gameManager, plugin, schedulerManager, plugin.pluginConfig.data.getDuration( "waiting" ).seconds )) + } + + @EventHandler + fun onLeavesDecay( + event: LeavesDecayEvent + ) { + event.isCancelled = true + } + + @EventHandler + fun onBlockBreak( + event: BlockBreakEvent + ) { + if ( gameManager.getCurrentState() != this ) + return + + event.isCancelled = true + event.player.playSound( event.player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f ) + } + + @EventHandler + fun onBlockPlace( + event: BlockPlaceEvent + ) { + if ( gameManager.getCurrentState() != this ) + return + + event.isCancelled = true + event.player.playSound( event.player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f ) + } + + @EventHandler + fun onPlayerPickupItem( + event: PlayerAttemptPickupItemEvent + ) { + if ( gameManager.getCurrentState() != this ) + return + + event.isCancelled = true + } + + @EventHandler + fun onPlayerDropItem( + event: PlayerDropItemEvent + ) { + if ( gameManager.getCurrentState() != this ) + return + + event.isCancelled = true + event.player.playSound( event.player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f ) + } + + @EventHandler + fun onEntityDamage( + event: EntityDamageEvent + ) { + if ( gameManager.getCurrentState() != this ) + return + + event.isCancelled = true + } + + @EventHandler + fun onFoodLevelChange( + event: FoodLevelChangeEvent + ) { + if ( gameManager.getCurrentState() != this ) + return + + event.isCancelled = true + } + + internal enum class AnnouncementType { + MINUTES, SECONDS + } + +} \ No newline at end of file diff --git a/src/main/kotlin/club/mcscrims/speedhg/game/impl/WaitingState.kt b/src/main/kotlin/club/mcscrims/speedhg/game/impl/WaitingState.kt new file mode 100644 index 0000000..fdefbc1 --- /dev/null +++ b/src/main/kotlin/club/mcscrims/speedhg/game/impl/WaitingState.kt @@ -0,0 +1,121 @@ +package club.mcscrims.speedhg.game.impl + +import club.mcscrims.speedhg.SpeedHG +import club.mcscrims.speedhg.game.GameManager +import club.mcscrims.speedhg.game.GameState +import club.mcscrims.spigot.scheduler.SchedulerManager +import org.bukkit.Bukkit +import org.bukkit.Sound +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.block.BlockBreakEvent +import org.bukkit.event.block.BlockPlaceEvent +import org.bukkit.event.block.LeavesDecayEvent +import org.bukkit.event.entity.EntityDamageEvent +import org.bukkit.event.entity.FoodLevelChangeEvent +import org.bukkit.event.player.PlayerAttemptPickupItemEvent +import org.bukkit.event.player.PlayerDropItemEvent + +class WaitingState( + gameManager: GameManager, + plugin: SpeedHG, + schedulerManager: SchedulerManager, + durationSeconds: Int? = null +) : GameState( "waiting", gameManager, plugin, schedulerManager, durationSeconds ), Listener { + + override fun onEnter( + previous: GameState? + ) { + super.onEnter( previous ) + registerListener( this ) + } + + private var secondsCounter: Int = 0 + + override fun onTick() + { + val playerSize = Bukkit.getOnlinePlayers().size + + if ( playerSize < plugin.pluginConfig.data.game.minimumPlayers ) + if ( secondsCounter == 15 ) + { + broadcast( "gameStates.waiting.awaiting_players", "{min_players}" to plugin.pluginConfig.data.game.minimumPlayers.toString() ) + secondsCounter = 0 + } + else secondsCounter++ + else gameManager.transitionTo(PreStartState( gameManager, plugin, schedulerManager, plugin.pluginConfig.data.getDuration( "pre_start" ).seconds )) + } + + override fun onEndOfDuration() {} + + @EventHandler + fun onLeavesDecay( + event: LeavesDecayEvent + ) { + event.isCancelled = true + } + + @EventHandler + fun onBlockBreak( + event: BlockBreakEvent + ) { + if ( gameManager.getCurrentState() != this ) + return + + event.isCancelled = true + event.player.playSound( event.player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f ) + } + + @EventHandler + fun onBlockPlace( + event: BlockPlaceEvent + ) { + if ( gameManager.getCurrentState() != this ) + return + + event.isCancelled = true + event.player.playSound( event.player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f ) + } + + @EventHandler + fun onPlayerPickupItem( + event: PlayerAttemptPickupItemEvent + ) { + if ( gameManager.getCurrentState() != this ) + return + + event.isCancelled = true + } + + @EventHandler + fun onPlayerDropItem( + event: PlayerDropItemEvent + ) { + if ( gameManager.getCurrentState() != this ) + return + + event.isCancelled = true + event.player.playSound( event.player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f ) + } + + @EventHandler + fun onEntityDamage( + event: EntityDamageEvent + ) { + if ( gameManager.getCurrentState() != this ) + return + + event.isCancelled = true + } + + @EventHandler + fun onFoodLevelChange( + event: FoodLevelChangeEvent + ) { + if ( gameManager.getCurrentState() != this ) + return + + event.isCancelled = true + } + +} \ No newline at end of file diff --git a/src/main/kotlin/club/mcscrims/speedhg/util/DirectionUtil.kt b/src/main/kotlin/club/mcscrims/speedhg/util/DirectionUtil.kt new file mode 100644 index 0000000..28c5fa1 --- /dev/null +++ b/src/main/kotlin/club/mcscrims/speedhg/util/DirectionUtil.kt @@ -0,0 +1,50 @@ +package club.mcscrims.speedhg.util + +import club.mcscrims.speedhg.SpeedHG +import net.kyori.adventure.text.Component +import org.bukkit.entity.Player +import org.bukkit.util.Vector +import kotlin.math.atan2 + +object DirectionUtil { + + private val plugin = SpeedHG.instance + private val directions = arrayOf("north", "northEast", "east", "southEast", "south", "southWest", "west", "northWest") + + fun getDirectionToPlayer( + player: Player, + nearestPlayer: Player + ): Component + { + val yaw = getDirection( player, nearestPlayer ) + var normalizedYaw = yaw % 360 + + if ( normalizedYaw < 0 ) + normalizedYaw += 360 + + val index = (( normalizedYaw + 22.5 ) / 45 ).toInt() % 8 + return plugin.chatFormatter.format( "compass.directions.${directions[ index ]}" ) + } + + private fun getDirection( + fromPlayer: Player, + toPlayer: Player + ): Double + { + val fromLocation = fromPlayer.location + val toLocation = toPlayer.location + + val directionVector = Vector( toLocation.x - fromLocation.x, 0.0, toLocation.z - fromLocation.z ).normalize() + + val angle = atan2( directionVector.x, directionVector.z ) + val yaw = Math.toDegrees( angle ) + + var adjustedYaw = yaw + 180 + + if ( adjustedYaw < 0) + adjustedYaw += 360 + + return adjustedYaw + } + +} \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 077a6a3..52a8338 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -54,14 +54,28 @@ game: - 'lobby' - 'l' - playerState: - waiting: 'Waiting - %time%' - preStart: 'Waiting - %time%' - immunity: 'Playing - %time%' - battle: 'Playing - %time%' - feast: 'Playing - %time%' - deathmatch: 'Playing - %time%' - end: 'Ending - %time%' + playerStates: + waiting: + scoreboard: 'Waiting - %time%' + duration: FIXED:-1 + preStart: + scoreboard: 'Waiting - %time%' + duration: FIXED:300 + immunity: + scoreboard: 'Playing - %time%' + duration: FIXED:90 + battle: + scoreboard: 'Playing - %time%' + duration: INCREASING + feast: + scoreboard: 'Playing - %time%' + duration: FIXED:300 + deathmatch: + scoreboard: 'Playing - %time%' + duration: INCREASING + end: + scoreboard: 'Ending - %time%' + duration: FIXED:60 recraftNerf: enabled: false