Update game states & world management
This commit is contained in:
@@ -17,6 +17,7 @@ repositories {
|
||||
maven("https://oss.sonatype.org/content/repositories/snapshots/")
|
||||
maven("https://libraries.minecraft.net/")
|
||||
maven("https://repo.codemc.io/repository/maven-public/")
|
||||
maven("https://repo.lunarclient.dev")
|
||||
|
||||
maven {
|
||||
url = uri("https://maven.pkg.github.com/McScrims-Network/Main-CoreSystem")
|
||||
@@ -37,6 +38,11 @@ dependencies {
|
||||
|
||||
compileOnly("net.luckperms:api:5.4")
|
||||
|
||||
compileOnly("com.lunarclient:apollo-api:1.2.0")
|
||||
compileOnly("com.lunarclient:apollo-extra-adventure4:1.2.0")
|
||||
|
||||
compileOnly("org.popcraft:chunky-common:1.3.38")
|
||||
|
||||
implementation("club.mcscrims:core:1.4.2")
|
||||
implementation("club.mcscrims:spigot:1.4.2")
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@ import club.mcscrims.speedhg.config.MessageConfig
|
||||
import club.mcscrims.speedhg.config.PluginConfig
|
||||
import club.mcscrims.speedhg.database.StatsRepository
|
||||
import club.mcscrims.speedhg.game.GameManager
|
||||
import club.mcscrims.speedhg.listener.GameStateListener
|
||||
import club.mcscrims.speedhg.listener.LunarClientListener
|
||||
import club.mcscrims.speedhg.world.WorldManager
|
||||
import club.mcscrims.spigot.chat.ChatFormatter
|
||||
import club.mcscrims.spigot.chat.ChatManager
|
||||
import club.mcscrims.spigot.network.SpigotNetworkManager
|
||||
@@ -39,10 +42,12 @@ class SpeedHG : JavaPlugin() {
|
||||
internal lateinit var schedulerManager: SchedulerManager
|
||||
|
||||
internal lateinit var gameManager: GameManager
|
||||
internal lateinit var worldManager: WorldManager
|
||||
|
||||
internal lateinit var luckPerms: LuckPerms
|
||||
internal var isReady: Boolean = false
|
||||
|
||||
override fun onEnable()
|
||||
override fun onLoad()
|
||||
{
|
||||
instance = this
|
||||
|
||||
@@ -50,6 +55,14 @@ class SpeedHG : JavaPlugin() {
|
||||
setupDatabase()
|
||||
networkManager = SpigotNetworkManager.getInstance()!!
|
||||
|
||||
worldManager = WorldManager( this )
|
||||
worldManager.deleteWorld()
|
||||
}
|
||||
|
||||
override fun onEnable()
|
||||
{
|
||||
worldManager.setupWorld()
|
||||
|
||||
chatFormatter = ChatFormatter.create(
|
||||
plugin = this,
|
||||
configClass = MessageConfig::class,
|
||||
@@ -65,6 +78,7 @@ class SpeedHG : JavaPlugin() {
|
||||
gameManager.initialize()
|
||||
|
||||
setupLuckPerms()
|
||||
registerListener()
|
||||
}
|
||||
|
||||
override fun onDisable()
|
||||
@@ -73,6 +87,12 @@ class SpeedHG : JavaPlugin() {
|
||||
networkManager.shutdown()
|
||||
}
|
||||
|
||||
private fun registerListener()
|
||||
{
|
||||
server.pluginManager.registerEvents(GameStateListener( this, gameManager ), this )
|
||||
LunarClientListener( this )
|
||||
}
|
||||
|
||||
/*
|
||||
* LUCKPERMS >>
|
||||
*/
|
||||
|
||||
@@ -1,13 +1,28 @@
|
||||
package club.mcscrims.speedhg.game
|
||||
|
||||
import club.mcscrims.speedhg.SpeedHG
|
||||
import club.mcscrims.speedhg.game.impl.BattleState
|
||||
import club.mcscrims.speedhg.game.impl.FeastState
|
||||
import club.mcscrims.speedhg.game.impl.ImmunityState
|
||||
import club.mcscrims.speedhg.game.impl.PreStartState
|
||||
import club.mcscrims.speedhg.game.impl.WaitingState
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.util.BoundingBox
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
class GameManager(
|
||||
private val plugin: SpeedHG
|
||||
) {
|
||||
|
||||
private var currentState: GameState? = null
|
||||
private val gameStateTypes = ConcurrentHashMap<GameStateTypes, GameState>()
|
||||
|
||||
private val winners = ArrayList<Player>()
|
||||
|
||||
internal lateinit var feastLocation: Location
|
||||
internal lateinit var feastBox: BoundingBox
|
||||
internal var feastHeight: Int = 1
|
||||
|
||||
fun initialize()
|
||||
{
|
||||
@@ -24,12 +39,21 @@ class GameManager(
|
||||
plugin.logger.severe("Error during onEnter for state ${currentState?.name}: ${e.message}")
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
gameStateTypes[ GameStateTypes.WAITING ] = currentState!!
|
||||
gameStateTypes[ GameStateTypes.PRE_START ] = PreStartState( this, plugin, plugin.schedulerManager, plugin.pluginConfig.data.getDuration( "pre_start" ).seconds )
|
||||
gameStateTypes[ GameStateTypes.IMMUNITY ] = ImmunityState( this, plugin, plugin.schedulerManager, plugin.pluginConfig.data.getDuration( "immunity" ).seconds )
|
||||
gameStateTypes[ GameStateTypes.BATTLE ] = BattleState( this, plugin, plugin.schedulerManager, plugin.pluginConfig.data.getDuration( "battle" ).seconds )
|
||||
gameStateTypes[ GameStateTypes.FEAST ] = FeastState( this, plugin, plugin.schedulerManager, plugin.pluginConfig.data.getDuration( "feast" ).seconds )
|
||||
gameStateTypes[ GameStateTypes.DEATHMATCH ] = TODO()
|
||||
gameStateTypes[ GameStateTypes.END ] = TODO()
|
||||
}
|
||||
|
||||
fun transitionTo(
|
||||
nextState: GameState
|
||||
stateType: GameStateTypes
|
||||
) {
|
||||
val previousState = currentState
|
||||
val nextState = gameStateTypes[ stateType ]!!
|
||||
|
||||
try {
|
||||
currentState?.onExit( nextState )
|
||||
@@ -38,6 +62,13 @@ class GameManager(
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
if ( nextState is FeastState )
|
||||
{
|
||||
feastLocation = nextState.feastLocation
|
||||
feastBox = nextState.feastBox
|
||||
feastHeight = nextState.feastHeight
|
||||
}
|
||||
|
||||
currentState = nextState
|
||||
|
||||
try {
|
||||
@@ -48,8 +79,33 @@ class GameManager(
|
||||
}
|
||||
}
|
||||
|
||||
fun addWinners(
|
||||
vararg winners: Player
|
||||
) {
|
||||
winners.forEach { this.winners.add( it ) }
|
||||
}
|
||||
|
||||
fun getCurrentState(): GameState? = currentState
|
||||
|
||||
fun getCurrentStateType(): GameStateTypes? = gameStateTypes.filter { it.value.name == currentState?.name }.keys.firstOrNull()
|
||||
|
||||
fun isRunning(): Boolean
|
||||
{
|
||||
return getCurrentStateType() == GameStateTypes.IMMUNITY ||
|
||||
getCurrentStateType() == GameStateTypes.BATTLE ||
|
||||
getCurrentStateType() == GameStateTypes.FEAST ||
|
||||
getCurrentStateType() == GameStateTypes.DEATHMATCH
|
||||
}
|
||||
|
||||
fun isBeforeFeast(): Boolean
|
||||
{
|
||||
return getCurrentStateType() == GameStateTypes.WAITING ||
|
||||
getCurrentStateType() == GameStateTypes.PRE_START ||
|
||||
getCurrentStateType() == GameStateTypes.IMMUNITY ||
|
||||
(getCurrentStateType() == GameStateTypes.BATTLE &&
|
||||
!( currentState as BattleState ).afterFeast )
|
||||
}
|
||||
|
||||
fun shutdown()
|
||||
{
|
||||
currentState?.onExit( null )
|
||||
@@ -57,3 +113,7 @@ class GameManager(
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum class GameStateTypes {
|
||||
WAITING, PRE_START, IMMUNITY, BATTLE, FEAST, DEATHMATCH, END
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package club.mcscrims.speedhg.game
|
||||
|
||||
import club.mcscrims.core.config.DurationType
|
||||
import club.mcscrims.speedhg.SpeedHG
|
||||
import club.mcscrims.spigot.scheduler.SchedulerManager
|
||||
import club.mcscrims.spigot.scheduler.TaskRegistration
|
||||
@@ -18,7 +19,7 @@ abstract class GameState(
|
||||
|
||||
private val listeners = mutableListOf<Listener>()
|
||||
private var tickTask: TaskRegistration? = null
|
||||
private var remainingSeconds: Int = durationSeconds ?: 0
|
||||
var remainingSeconds: Int = durationSeconds ?: 0
|
||||
private var isActive: Boolean = false
|
||||
|
||||
open fun onEnter(
|
||||
@@ -62,6 +63,12 @@ abstract class GameState(
|
||||
|
||||
if ( durationSeconds != null && remainingSeconds > 0 )
|
||||
{
|
||||
if (plugin.pluginConfig.data.getDuration( name ).type == DurationType.INCREASING)
|
||||
{
|
||||
remainingSeconds++
|
||||
return@runRepeating
|
||||
}
|
||||
|
||||
remainingSeconds--
|
||||
|
||||
if ( remainingSeconds == 0)
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
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.GameStateTypes
|
||||
import club.mcscrims.spigot.scheduler.SchedulerManager
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class BattleState(
|
||||
gameManager: GameManager,
|
||||
plugin: SpeedHG,
|
||||
schedulerManager: SchedulerManager,
|
||||
durationSeconds: Int? = null
|
||||
) : GameState( "battle", gameManager, plugin, schedulerManager, durationSeconds ) {
|
||||
|
||||
var afterFeast: Boolean = false
|
||||
|
||||
override fun onEnter(
|
||||
previous: GameState?
|
||||
) {
|
||||
super.onEnter( previous )
|
||||
Bukkit.getOnlinePlayers().forEach( Player::clearActivePotionEffects )
|
||||
}
|
||||
|
||||
override fun onTick()
|
||||
{
|
||||
val win = checkForWinners()
|
||||
|
||||
when( remainingSeconds )
|
||||
{
|
||||
300 ->
|
||||
{
|
||||
gameManager.transitionTo( GameStateTypes.FEAST )
|
||||
afterFeast = true
|
||||
}
|
||||
|
||||
1800 ->
|
||||
{
|
||||
if ( !win )
|
||||
{
|
||||
gameManager.transitionTo( GameStateTypes.DEATHMATCH )
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onEndOfDuration() {}
|
||||
|
||||
private fun checkForWinners(): Boolean
|
||||
{
|
||||
val players = Bukkit.getOnlinePlayers()
|
||||
|
||||
if ( players.size > 1 )
|
||||
return false
|
||||
|
||||
gameManager.addWinners( players.first() )
|
||||
gameManager.transitionTo( GameStateTypes.END )
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
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.Location
|
||||
import org.bukkit.util.BoundingBox
|
||||
import java.util.Random
|
||||
|
||||
class FeastState(
|
||||
gameManager: GameManager,
|
||||
plugin: SpeedHG,
|
||||
schedulerManager: SchedulerManager,
|
||||
durationSeconds: Int? = null
|
||||
) : GameState( "feast", gameManager, plugin, schedulerManager, durationSeconds ) {
|
||||
|
||||
private val world = plugin.worldManager.getWorld()
|
||||
private val random = Random()
|
||||
|
||||
internal lateinit var feastLocation: Location
|
||||
internal lateinit var feastBox: BoundingBox
|
||||
internal var feastHeight: Int = 1
|
||||
|
||||
override fun onTick()
|
||||
{
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onEndOfDuration()
|
||||
{
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,23 +3,11 @@ 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.GameStateTypes
|
||||
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
|
||||
@@ -29,13 +17,12 @@ class ImmunityState(
|
||||
plugin: SpeedHG,
|
||||
schedulerManager: SchedulerManager,
|
||||
durationSeconds: Int? = null
|
||||
) : GameState( "immunity", gameManager, plugin, schedulerManager, durationSeconds ), Listener {
|
||||
) : GameState( "immunity", gameManager, plugin, schedulerManager, durationSeconds ) {
|
||||
|
||||
override fun onEnter(
|
||||
previous: GameState?
|
||||
) {
|
||||
super.onEnter( previous )
|
||||
registerListener( this )
|
||||
|
||||
val effects = listOf(
|
||||
PotionEffect( PotionEffectType.HASTE, durationSeconds?.times( 20 ) ?: 0, 0 ),
|
||||
@@ -62,7 +49,7 @@ class ImmunityState(
|
||||
|
||||
override fun onTick()
|
||||
{
|
||||
when( durationSeconds )
|
||||
when( remainingSeconds )
|
||||
{
|
||||
180 -> announce( AnnouncementType.MINUTES, 3 )
|
||||
120 -> announce( AnnouncementType.MINUTES, 2 )
|
||||
@@ -78,7 +65,7 @@ class ImmunityState(
|
||||
0 ->
|
||||
{
|
||||
broadcast( "gameStates.immunity.ended" )
|
||||
gameManager.transitionTo( TODO() )
|
||||
gameManager.transitionTo( GameStateTypes.BATTLE )
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,160 +80,4 @@ class ImmunityState(
|
||||
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( "<direction>" ).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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,26 +3,17 @@ 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.GameStateTypes
|
||||
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 {
|
||||
) : GameState( "pre_start", gameManager, plugin, schedulerManager, durationSeconds ) {
|
||||
|
||||
private lateinit var previous: GameState
|
||||
|
||||
@@ -30,7 +21,6 @@ class PreStartState(
|
||||
previous: GameState?
|
||||
) {
|
||||
super.onEnter( previous )
|
||||
registerListener( this )
|
||||
|
||||
if ( previous != null )
|
||||
this.previous = previous
|
||||
@@ -45,17 +35,17 @@ class PreStartState(
|
||||
if ( playerSize < plugin.pluginConfig.data.game.minimumPlayers )
|
||||
{
|
||||
isStarting = false
|
||||
transitionToPrevious()
|
||||
gameManager.transitionTo( GameStateTypes.WAITING )
|
||||
}
|
||||
else isStarting = true
|
||||
|
||||
if ( !isStarting )
|
||||
return
|
||||
|
||||
if ( durationSeconds == 15 )
|
||||
if ( remainingSeconds == 15 )
|
||||
teleport()
|
||||
|
||||
when( durationSeconds )
|
||||
when( remainingSeconds )
|
||||
{
|
||||
300 -> announce( AnnouncementType.MINUTES, 5 )
|
||||
240 -> announce( AnnouncementType.MINUTES, 4 )
|
||||
@@ -74,7 +64,7 @@ class PreStartState(
|
||||
{
|
||||
broadcast( "gameStates.preStart.started" )
|
||||
isStarting = false
|
||||
gameManager.transitionTo(ImmunityState( gameManager, plugin, schedulerManager, plugin.pluginConfig.data.getDuration( "immunity" ).seconds ))
|
||||
gameManager.transitionTo( GameStateTypes.IMMUNITY )
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,87 +96,6 @@ class PreStartState(
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -3,32 +3,16 @@ 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.GameStateTypes
|
||||
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 )
|
||||
}
|
||||
) : GameState( "waiting", gameManager, plugin, schedulerManager, durationSeconds ) {
|
||||
|
||||
private var secondsCounter: Int = 0
|
||||
|
||||
@@ -43,79 +27,9 @@ class WaitingState(
|
||||
secondsCounter = 0
|
||||
}
|
||||
else secondsCounter++
|
||||
else gameManager.transitionTo(PreStartState( gameManager, plugin, schedulerManager, plugin.pluginConfig.data.getDuration( "pre_start" ).seconds ))
|
||||
else gameManager.transitionTo( GameStateTypes.PRE_START )
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,545 @@
|
||||
package club.mcscrims.speedhg.listener
|
||||
|
||||
import club.mcscrims.speedhg.SpeedHG
|
||||
import club.mcscrims.speedhg.game.GameManager
|
||||
import club.mcscrims.speedhg.game.GameStateTypes
|
||||
import club.mcscrims.speedhg.util.DirectionUtil
|
||||
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.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.block.BlockPlaceEvent
|
||||
import org.bukkit.event.block.BlockSpreadEvent
|
||||
import org.bukkit.event.block.LeavesDecayEvent
|
||||
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.inventory.ClickType
|
||||
import org.bukkit.event.inventory.CraftItemEvent
|
||||
import org.bukkit.event.inventory.InventoryClickEvent
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent
|
||||
import org.bukkit.event.inventory.InventoryOpenEvent
|
||||
import org.bukkit.event.inventory.InventoryType
|
||||
import org.bukkit.event.player.PlayerAttemptPickupItemEvent
|
||||
import org.bukkit.event.player.PlayerBucketEmptyEvent
|
||||
import org.bukkit.event.player.PlayerDropItemEvent
|
||||
import org.bukkit.event.player.PlayerInteractEvent
|
||||
import org.bukkit.event.player.PlayerItemDamageEvent
|
||||
import org.bukkit.event.player.PlayerJoinEvent
|
||||
import org.bukkit.event.player.PlayerQuitEvent
|
||||
import org.bukkit.inventory.EnchantingInventory
|
||||
import org.bukkit.inventory.EquipmentSlot
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.inventory.meta.Damageable
|
||||
import java.util.Random
|
||||
import kotlin.math.min
|
||||
|
||||
class GameStateListener(
|
||||
private val plugin: SpeedHG,
|
||||
private val gameManager: GameManager
|
||||
) : Listener {
|
||||
|
||||
@EventHandler
|
||||
fun onLeavesDecay(
|
||||
event: LeavesDecayEvent
|
||||
) {
|
||||
if ( gameManager.isRunning() )
|
||||
return
|
||||
|
||||
event.isCancelled = true
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onBlockPlace(
|
||||
event: BlockPlaceEvent
|
||||
) {
|
||||
val player = event.player
|
||||
|
||||
if ( gameManager.getCurrentStateType() == GameStateTypes.FEAST )
|
||||
{
|
||||
val block = event.block
|
||||
|
||||
if (!gameManager.feastBox.contains( block.location.toVector() ))
|
||||
return
|
||||
|
||||
event.isCancelled = true
|
||||
player.playSound( player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f )
|
||||
return
|
||||
}
|
||||
|
||||
if ( gameManager.isRunning() )
|
||||
return
|
||||
|
||||
event.isCancelled = true
|
||||
player.playSound( player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f )
|
||||
}
|
||||
|
||||
private val beforeInvisMaterials = setOf(
|
||||
Material.OAK_LOG,
|
||||
Material.DARK_OAK_LOG,
|
||||
Material.BIRCH_LOG,
|
||||
Material.ACACIA_LOG,
|
||||
Material.JUNGLE_LOG,
|
||||
Material.SPRUCE_LOG,
|
||||
Material.STONE
|
||||
)
|
||||
|
||||
private val alwaysMaterials = setOf(
|
||||
Material.RED_MUSHROOM,
|
||||
Material.BROWN_MUSHROOM,
|
||||
Material.COCOA_BEANS,
|
||||
Material.CACTUS
|
||||
)
|
||||
|
||||
@EventHandler
|
||||
fun onBlockBreak(
|
||||
event: BlockBreakEvent
|
||||
) {
|
||||
val player = event.player
|
||||
|
||||
if ( !gameManager.isRunning() )
|
||||
{
|
||||
event.isCancelled = true
|
||||
player.playSound( player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f )
|
||||
return
|
||||
}
|
||||
|
||||
val block = event.block
|
||||
|
||||
if ( gameManager.getCurrentStateType() == GameStateTypes.FEAST )
|
||||
{
|
||||
if (!gameManager.feastBox.contains( block.location.toVector() ))
|
||||
return
|
||||
|
||||
event.isCancelled = true
|
||||
player.playSound( player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f )
|
||||
return
|
||||
}
|
||||
|
||||
if ( gameManager.getCurrentStateType() == GameStateTypes.IMMUNITY &&
|
||||
beforeInvisMaterials.contains( block.type ))
|
||||
{
|
||||
pickup( event, player )
|
||||
return
|
||||
}
|
||||
|
||||
if (alwaysMaterials.contains( block.type ))
|
||||
{
|
||||
pickup( event, player )
|
||||
return
|
||||
}
|
||||
|
||||
if ( block.type == Material.DIAMOND_ORE )
|
||||
{
|
||||
event.isCancelled = true
|
||||
event.block.type = Material.AIR
|
||||
event.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 && gameManager.isBeforeFeast() )
|
||||
{
|
||||
event.isCancelled = true
|
||||
plugin.chatManager.sendMessage( player, "build.no_iron_before_feast" )
|
||||
player.playSound( player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f )
|
||||
}
|
||||
else if ( block.type == Material.IRON_ORE && !gameManager.isBeforeFeast() )
|
||||
{
|
||||
runBlocking { plugin.statsRepository.addIronFarmed( player.uniqueId, 0.1 ) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun pickup(
|
||||
event: BlockBreakEvent,
|
||||
player: Player
|
||||
) {
|
||||
event.isCancelled = true
|
||||
|
||||
if (!hasInventorySpace( player ))
|
||||
{
|
||||
event.block.drops.forEach { player.world.dropItem( event.block.location, it ) }
|
||||
event.block.type = Material.AIR
|
||||
return
|
||||
}
|
||||
|
||||
event.block.drops.forEach { player.inventory.addItem( it ) }
|
||||
event.block.type = Material.AIR
|
||||
}
|
||||
|
||||
private fun hasInventorySpace(
|
||||
player: Player
|
||||
): Boolean
|
||||
{
|
||||
return player.inventory.any { it == null || it.type == Material.AIR }
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onDropItem(
|
||||
event: PlayerDropItemEvent
|
||||
) {
|
||||
val player = event.player
|
||||
|
||||
if ( !gameManager.isRunning() )
|
||||
{
|
||||
event.isCancelled = true
|
||||
player.playSound( player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f )
|
||||
return
|
||||
}
|
||||
|
||||
TODO( "Kit & perk items" )
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onPickupItem(
|
||||
event: PlayerAttemptPickupItemEvent
|
||||
) {
|
||||
if ( gameManager.isRunning() )
|
||||
return
|
||||
|
||||
event.isCancelled = true
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onInteractCompass(
|
||||
event: PlayerInteractEvent
|
||||
) {
|
||||
if ( !gameManager.isRunning() )
|
||||
return
|
||||
|
||||
val player = event.player
|
||||
val action = event.action
|
||||
|
||||
if ( action != Action.RIGHT_CLICK_AIR &&
|
||||
action != Action.RIGHT_CLICK_BLOCK )
|
||||
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 )
|
||||
var actionBar = plugin.chatFormatter.format( "compass.actionBar" )
|
||||
actionBar = actionBar.replaceText { it.match( "<direction>" ).replacement( direction ).once() }
|
||||
plugin.chatManager.getAudience( player ).sendActionBar( actionBar )
|
||||
}
|
||||
|
||||
private val swordNerf = 0.5
|
||||
private val otherNerf = 0.2
|
||||
|
||||
private val nerfedItems = listOf(
|
||||
"_AXE", "_SHOVEL", "_PICKAXE"
|
||||
)
|
||||
|
||||
@EventHandler
|
||||
fun onDamageEntity(
|
||||
event: EntityDamageByEntityEvent
|
||||
) {
|
||||
val damager = event.damager
|
||||
|
||||
if ( damager !is Player )
|
||||
return
|
||||
|
||||
val itemName = damager.inventory.itemInMainHand.type.name
|
||||
|
||||
if (itemName.endsWith( "_SWORD" ))
|
||||
{
|
||||
event.damage *= swordNerf
|
||||
return
|
||||
}
|
||||
|
||||
for ( nerfedItem in nerfedItems )
|
||||
if (itemName.endsWith( nerfedItem ))
|
||||
event.damage *= otherNerf
|
||||
}
|
||||
|
||||
private val random = Random()
|
||||
|
||||
@EventHandler
|
||||
fun onPlayerItemDamage(
|
||||
event: PlayerItemDamageEvent
|
||||
) {
|
||||
val item = event.item
|
||||
|
||||
if (!item.type.name.endsWith( "_SWORD" ) &&
|
||||
!item.type.name.endsWith( "_AXE" ))
|
||||
return
|
||||
|
||||
if ( random.nextBoolean() )
|
||||
event.isCancelled = true
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onJoin(
|
||||
event: PlayerJoinEvent
|
||||
) {
|
||||
disableCooldown( event.player )
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onQuit(
|
||||
event: PlayerQuitEvent
|
||||
) {
|
||||
disableCooldown( event.player )
|
||||
}
|
||||
|
||||
private fun disableCooldown(
|
||||
player: Player
|
||||
) {
|
||||
val attackSpeed = player.getAttribute( Attribute.GENERIC_ATTACK_SPEED )
|
||||
|
||||
if ( attackSpeed != null )
|
||||
attackSpeed.baseValue = 40.0
|
||||
}
|
||||
|
||||
private val lapisLazuli = Material.LAPIS_LAZULI
|
||||
|
||||
@EventHandler
|
||||
fun onEnchant(
|
||||
event: EnchantItemEvent
|
||||
) {
|
||||
val enchInv = event.inventory as EnchantingInventory
|
||||
enchInv.secondary = ItemStack( lapisLazuli, 64 )
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onInventoryClick(
|
||||
event: InventoryClickEvent
|
||||
) {
|
||||
if ( event.inventory.type != InventoryType.ENCHANTING )
|
||||
return
|
||||
|
||||
val item = event.currentItem
|
||||
?: return
|
||||
|
||||
// prevent taking it out
|
||||
if ( item.type == lapisLazuli && event.rawSlot == 1 )
|
||||
event.isCancelled = true
|
||||
else if ( event.cursor.type == lapisLazuli && event.click == ClickType.DOUBLE_CLICK)
|
||||
event.isCancelled = true
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onInventoryClose(
|
||||
event: InventoryCloseEvent
|
||||
) {
|
||||
val inventory = event.inventory
|
||||
|
||||
if ( inventory.type != InventoryType.ENCHANTING )
|
||||
return
|
||||
|
||||
( inventory as EnchantingInventory ).secondary = null
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onInventoryOpen(
|
||||
event: InventoryOpenEvent
|
||||
) {
|
||||
val inventory = event.inventory
|
||||
|
||||
if ( inventory.type != InventoryType.ENCHANTING )
|
||||
return
|
||||
|
||||
( inventory as EnchantingInventory ).secondary = ItemStack( lapisLazuli, 64 )
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onInteractSoup(
|
||||
event: PlayerInteractEvent
|
||||
) {
|
||||
val player = event.player
|
||||
val action = event.action
|
||||
|
||||
if ( action != Action.RIGHT_CLICK_AIR &&
|
||||
action != Action.RIGHT_CLICK_BLOCK )
|
||||
return
|
||||
|
||||
if ( !event.hasItem() ||
|
||||
event.material != Material.MUSHROOM_STEW )
|
||||
return
|
||||
|
||||
if ( event.hand == EquipmentSlot.OFF_HAND )
|
||||
return
|
||||
|
||||
if ( player.health < requireNotNull(player.getAttribute( Attribute.GENERIC_MAX_HEALTH )!!.defaultValue))
|
||||
{
|
||||
player.health = min( player.health + 7, requireNotNull(player.getAttribute( Attribute.GENERIC_MAX_HEALTH )!!.defaultValue))
|
||||
player.inventory.setItemInMainHand(ItemStack( Material.BOWL ))
|
||||
}
|
||||
else if ( player.foodLevel < 20 )
|
||||
{
|
||||
player.foodLevel += 6
|
||||
player.saturation += 7
|
||||
player.inventory.setItemInMainHand(ItemStack( Material.BOWL ))
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onEntityDamage(
|
||||
event: EntityDamageEvent
|
||||
) {
|
||||
if ( gameManager.isRunning() )
|
||||
return
|
||||
|
||||
event.isCancelled = true
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onFoodLevelChange(
|
||||
event: FoodLevelChangeEvent
|
||||
) {
|
||||
if ( gameManager.isRunning() )
|
||||
return
|
||||
|
||||
event.foodLevel = 20
|
||||
event.isCancelled = true
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onCraftItem(
|
||||
event: CraftItemEvent
|
||||
) {
|
||||
if ( !gameManager.isRunning() )
|
||||
return
|
||||
|
||||
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_shift_click" )
|
||||
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 ( gameManager.isBeforeFeast() )
|
||||
{
|
||||
event.result = Event.Result.DENY
|
||||
plugin.chatManager.sendMessage( player, "craft.no_iron_before_feast" )
|
||||
player.playSound( player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f )
|
||||
return
|
||||
}
|
||||
|
||||
if ( item.type.maxDurability > 0 )
|
||||
{
|
||||
item.editMeta { meta -> ( meta as Damageable ).damage /= 2 }
|
||||
plugin.chatManager.sendMessage( player, "craft.iron_nerf" )
|
||||
}
|
||||
|
||||
runBlocking { plugin.statsRepository.addIronFarmed( player.uniqueId, 0.1 ) }
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onInteractCleanse(
|
||||
event: PlayerInteractEvent
|
||||
) {
|
||||
if ( gameManager.isBeforeFeast() )
|
||||
return
|
||||
|
||||
val player = event.player
|
||||
val action = event.action
|
||||
|
||||
val item = event.item ?: return
|
||||
val block = event.clickedBlock
|
||||
|
||||
if ( block != null && gameManager.feastBox.contains( block.location.toVector() ))
|
||||
{
|
||||
event.isCancelled = true
|
||||
player.playSound( player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f )
|
||||
return
|
||||
}
|
||||
|
||||
if ( action != Action.RIGHT_CLICK_AIR &&
|
||||
action != Action.RIGHT_CLICK_BLOCK )
|
||||
return
|
||||
|
||||
if ( item.type != Material.SUGAR ||
|
||||
!item.itemMeta.isUnbreakable )
|
||||
return
|
||||
|
||||
event.isCancelled = true
|
||||
|
||||
player.inventory.removeItemAnySlot( item )
|
||||
player.clearActivePotionEffects()
|
||||
|
||||
plugin.chatManager.sendMessage( player, "feast.cleanser.cleaned" )
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onBucketEmpty(
|
||||
event: PlayerBucketEmptyEvent
|
||||
) {
|
||||
if ( gameManager.getCurrentStateType() != GameStateTypes.FEAST )
|
||||
return
|
||||
|
||||
val location = event.blockClicked.location.toVector()
|
||||
|
||||
if (!gameManager.feastBox.contains( location ))
|
||||
return
|
||||
|
||||
event.isCancelled = true
|
||||
event.player.playSound( event.player, Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f )
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onLiquidSpread(
|
||||
event: BlockSpreadEvent
|
||||
) {
|
||||
if ( gameManager.getCurrentStateType() != GameStateTypes.FEAST )
|
||||
return
|
||||
|
||||
val block = event.block
|
||||
|
||||
if ( !block.isLiquid )
|
||||
return
|
||||
|
||||
if (!gameManager.feastBox.contains( block.location.toVector() ))
|
||||
return
|
||||
|
||||
event.isCancelled = true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package club.mcscrims.speedhg.listener
|
||||
|
||||
import club.mcscrims.speedhg.SpeedHG
|
||||
import club.mcscrims.speedhg.game.GameStateTypes
|
||||
import club.mcscrims.speedhg.util.LuckPermsUtils
|
||||
import club.mcscrims.speedhg.util.TimeUtils
|
||||
import com.lunarclient.apollo.Apollo
|
||||
import com.lunarclient.apollo.event.ApolloListener
|
||||
import com.lunarclient.apollo.event.Listen
|
||||
import com.lunarclient.apollo.event.player.ApolloRegisterPlayerEvent
|
||||
import com.lunarclient.apollo.mods.impl.ModFreelook
|
||||
import com.lunarclient.apollo.mods.impl.ModMinimap
|
||||
import com.lunarclient.apollo.mods.impl.ModSnaplook
|
||||
import com.lunarclient.apollo.mods.impl.ModTeamView
|
||||
import com.lunarclient.apollo.mods.impl.ModWaypoints
|
||||
import com.lunarclient.apollo.module.modsetting.ModSettingModule
|
||||
import com.lunarclient.apollo.module.richpresence.RichPresenceModule
|
||||
import com.lunarclient.apollo.module.richpresence.ServerRichPresence
|
||||
import com.lunarclient.apollo.module.serverrule.ServerRuleModule
|
||||
import com.lunarclient.apollo.module.staffmod.StaffMod
|
||||
import com.lunarclient.apollo.module.staffmod.StaffModModule
|
||||
import com.lunarclient.apollo.player.ApolloPlayer
|
||||
|
||||
class LunarClientListener(
|
||||
private val plugin: SpeedHG
|
||||
) : ApolloListener {
|
||||
|
||||
private val modSettingModule = Apollo.getModuleManager().getModule( ModSettingModule::class.java )
|
||||
private val staffModModule = Apollo.getModuleManager().getModule( StaffModModule::class.java )
|
||||
|
||||
private val richPresenceModule = Apollo.getModuleManager().getModule( RichPresenceModule::class.java )
|
||||
|
||||
private val serverRuleModule = Apollo.getModuleManager().getModule( ServerRuleModule::class.java )
|
||||
|
||||
init {
|
||||
this.handle( ApolloRegisterPlayerEvent::class.java, this::onApolloRegister )
|
||||
}
|
||||
|
||||
@Listen
|
||||
fun onApolloRegister(
|
||||
event: ApolloRegisterPlayerEvent
|
||||
) {
|
||||
val player = event.player
|
||||
|
||||
setModSettings( player )
|
||||
setRichPresence( player )
|
||||
setServerRules( player )
|
||||
}
|
||||
|
||||
private fun setServerRules(
|
||||
player: ApolloPlayer
|
||||
) {
|
||||
serverRuleModule.options.set( player, ServerRuleModule.COMPETITIVE_GAME, plugin.pluginConfig.data.game.competitiveGame )
|
||||
serverRuleModule.options.set( player, ServerRuleModule.COMPETITIVE_COMMANDS, plugin.pluginConfig.data.game.competitiveCommands )
|
||||
serverRuleModule.options.set( player, ServerRuleModule.ANTI_PORTAL_TRAPS, true )
|
||||
}
|
||||
|
||||
private fun setRichPresence(
|
||||
player: ApolloPlayer
|
||||
) {
|
||||
val teamMaxSize = plugin.pluginConfig.data.game.teams["maximum_players"] as? Int ?: 2
|
||||
|
||||
val playerState = when( plugin.gameManager.getCurrentStateType() )
|
||||
{
|
||||
GameStateTypes.WAITING -> plugin.pluginConfig.data.game.playerStates[ "waiting" ]?.scoreboard ?: "N/A"
|
||||
GameStateTypes.PRE_START -> plugin.pluginConfig.data.game.playerStates[ "pre_start" ]?.scoreboard ?: "N/A"
|
||||
GameStateTypes.IMMUNITY -> plugin.pluginConfig.data.game.playerStates[ "immunity" ]?.scoreboard ?: "N/A"
|
||||
GameStateTypes.BATTLE -> plugin.pluginConfig.data.game.playerStates[ "battle" ]?.scoreboard ?: "N/A"
|
||||
GameStateTypes.FEAST -> plugin.pluginConfig.data.game.playerStates[ "feast" ]?.scoreboard ?: "N/A"
|
||||
GameStateTypes.DEATHMATCH -> plugin.pluginConfig.data.game.playerStates[ "deathmatch" ]?.scoreboard ?: "N/A"
|
||||
GameStateTypes.END -> plugin.pluginConfig.data.game.playerStates[ "end" ]?.scoreboard ?: "N/A"
|
||||
else -> throw IllegalStateException("Current game state is null!")
|
||||
}
|
||||
|
||||
val presence = ServerRichPresence.builder()
|
||||
.gameName( plugin.pluginConfig.data.game.name )
|
||||
.gameState( plugin.gameManager.getCurrentStateType()!!.name )
|
||||
.gameVariantName( plugin.pluginConfig.data.game.variantName )
|
||||
.playerState(playerState.replace( "%time%", TimeUtils.scoreboardTimeFromState() ))
|
||||
.teamCurrentSize( 0 ) // TODO: Add team manager
|
||||
.teamMaxSize( teamMaxSize )
|
||||
.build()
|
||||
|
||||
richPresenceModule.overrideServerRichPresence( player, presence )
|
||||
}
|
||||
|
||||
private fun setModSettings(
|
||||
player: ApolloPlayer
|
||||
) {
|
||||
if (LuckPermsUtils.hasPermission( player.uniqueId, "mcscrims.staff" ))
|
||||
staffModModule.enableStaffMods( player, listOf( StaffMod.XRAY ))
|
||||
else
|
||||
staffModModule.disableAllStaffMods( player )
|
||||
|
||||
if (LuckPermsUtils.hasPermission( player.uniqueId, "speedhg.bypass.modSettings" ))
|
||||
return
|
||||
|
||||
modSettingModule.options.set( player, ModMinimap.ENABLED, false )
|
||||
modSettingModule.options.set( player, ModFreelook.ENABLED, false )
|
||||
modSettingModule.options.set( player, ModSnaplook.ENABLED, false )
|
||||
modSettingModule.options.set( player, ModWaypoints.ENABLED, false )
|
||||
modSettingModule.options.set( player, ModTeamView.ENABLED, true )
|
||||
}
|
||||
|
||||
}
|
||||
61
src/main/kotlin/club/mcscrims/speedhg/util/LuckPermsUtils.kt
Normal file
61
src/main/kotlin/club/mcscrims/speedhg/util/LuckPermsUtils.kt
Normal file
@@ -0,0 +1,61 @@
|
||||
package club.mcscrims.speedhg.util
|
||||
|
||||
import club.mcscrims.speedhg.SpeedHG
|
||||
import net.luckperms.api.cacheddata.CachedDataManager
|
||||
import net.luckperms.api.model.group.Group
|
||||
import net.luckperms.api.model.user.User
|
||||
import org.bukkit.entity.Player
|
||||
import java.util.UUID
|
||||
|
||||
object LuckPermsUtils {
|
||||
|
||||
private val plugin = SpeedHG.instance
|
||||
private val luckPerms = plugin.luckPerms
|
||||
|
||||
fun getUser(
|
||||
player: Player
|
||||
): User?
|
||||
{
|
||||
return luckPerms.userManager.getUser( player.uniqueId )
|
||||
}
|
||||
|
||||
fun editUser(
|
||||
player: Player,
|
||||
action: (User) -> Unit
|
||||
) {
|
||||
luckPerms.userManager.loadUser( player.uniqueId ).thenAcceptAsync( action )
|
||||
}
|
||||
|
||||
fun getGroup(
|
||||
groupName: String
|
||||
): Group?
|
||||
{
|
||||
return luckPerms.groupManager.getGroup( groupName )
|
||||
}
|
||||
|
||||
fun getCachedData(
|
||||
player: Player
|
||||
): CachedDataManager?
|
||||
{
|
||||
return getUser( player )?.cachedData
|
||||
}
|
||||
|
||||
fun hasPermission(
|
||||
uniqueId: UUID,
|
||||
permission: String
|
||||
): Boolean
|
||||
{
|
||||
val cachedData = luckPerms.userManager.loadUser( uniqueId ).get().cachedData
|
||||
return cachedData.permissionData.checkPermission( permission ).asBoolean()
|
||||
}
|
||||
|
||||
fun hasPermission(
|
||||
player: Player,
|
||||
permission: String
|
||||
): Boolean
|
||||
{
|
||||
return getCachedData( player )?.permissionData?.checkPermission( permission )?.asBoolean()
|
||||
?: player.hasPermission( permission )
|
||||
}
|
||||
|
||||
}
|
||||
29
src/main/kotlin/club/mcscrims/speedhg/util/TimeUtils.kt
Normal file
29
src/main/kotlin/club/mcscrims/speedhg/util/TimeUtils.kt
Normal file
@@ -0,0 +1,29 @@
|
||||
package club.mcscrims.speedhg.util
|
||||
|
||||
import club.mcscrims.speedhg.SpeedHG
|
||||
|
||||
object TimeUtils {
|
||||
|
||||
private val plugin = SpeedHG.instance
|
||||
|
||||
fun scoreboardTimeFromState(): String
|
||||
{
|
||||
val currentTime = plugin.gameManager.getCurrentState()?.remainingSeconds
|
||||
?: throw IllegalArgumentException("Remaining seconds for state is null!")
|
||||
return scoreboardTime( currentTime )
|
||||
}
|
||||
|
||||
fun scoreboardTime(
|
||||
totalSeconds: Int
|
||||
): String
|
||||
{
|
||||
val hours = totalSeconds / 3600
|
||||
val minutes = (totalSeconds % 3600) / 60
|
||||
val seconds = totalSeconds % 60
|
||||
|
||||
if ( totalSeconds > 3600 )
|
||||
return String.format( "%02d:%02d:%02d", hours, minutes, seconds )
|
||||
return String.format( "%02d:%02d", minutes, seconds )
|
||||
}
|
||||
|
||||
}
|
||||
157
src/main/kotlin/club/mcscrims/speedhg/world/WorldManager.kt
Normal file
157
src/main/kotlin/club/mcscrims/speedhg/world/WorldManager.kt
Normal file
@@ -0,0 +1,157 @@
|
||||
package club.mcscrims.speedhg.world
|
||||
|
||||
import club.mcscrims.speedhg.SpeedHG
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.GameRule
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.World
|
||||
import org.popcraft.chunky.api.ChunkyAPI
|
||||
import java.io.File
|
||||
|
||||
class WorldManager(
|
||||
private val plugin: SpeedHG
|
||||
) {
|
||||
|
||||
private lateinit var worldName: String
|
||||
private lateinit var world: World
|
||||
|
||||
fun highestLocationWithRadius(
|
||||
center: Location,
|
||||
radius: Int
|
||||
): Location
|
||||
{
|
||||
getWorld()
|
||||
val minX = center.blockX - radius
|
||||
val minZ = center.blockZ - radius
|
||||
val maxX = center.blockX + radius
|
||||
val maxZ = center.blockZ + radius
|
||||
|
||||
var highestY = center.blockY
|
||||
var highestX = minX
|
||||
var highestZ = minZ
|
||||
|
||||
for ( x in minX..maxX )
|
||||
for ( z in minZ..maxZ )
|
||||
{
|
||||
val y = world.getHighestBlockYAt( x, z )
|
||||
|
||||
if ( y > highestY )
|
||||
{
|
||||
highestY = y
|
||||
highestX = x
|
||||
highestZ = z
|
||||
}
|
||||
}
|
||||
|
||||
val highest = Location( world, highestX.toDouble(), highestY.toDouble(), highestZ.toDouble() )
|
||||
return highest
|
||||
}
|
||||
|
||||
/*
|
||||
* DELETION >>
|
||||
*/
|
||||
|
||||
fun deleteWorld()
|
||||
{
|
||||
getWorld()
|
||||
Bukkit.unloadWorld( worldName, false )
|
||||
val folder = File( worldName )
|
||||
deleteFolder( folder )
|
||||
}
|
||||
|
||||
private fun deleteFolder(
|
||||
folder: File
|
||||
) {
|
||||
val files = folder.listFiles()
|
||||
|
||||
if ( files != null )
|
||||
for ( f in files )
|
||||
{
|
||||
if ( f.isDirectory )
|
||||
deleteFolder( f )
|
||||
else
|
||||
f.delete()
|
||||
}
|
||||
|
||||
folder.delete()
|
||||
}
|
||||
|
||||
/*
|
||||
* WORLD >>
|
||||
*/
|
||||
|
||||
lateinit var spawnLocation: Location
|
||||
var borderDecrease: Double = 100.0
|
||||
|
||||
fun setupWorld()
|
||||
{
|
||||
val world = getWorld() ?: return
|
||||
plugin.logger.info("Setting up world...")
|
||||
|
||||
// BORDER >>
|
||||
|
||||
plugin.logger.info("Setting up world... [STAGE [1]: WORLDBORDER]")
|
||||
|
||||
spawnLocation = Location( world, 0.0, world.getHighestBlockYAt( 0, 0).toDouble(), 0.0 )
|
||||
world.worldBorder.center = spawnLocation
|
||||
|
||||
world.worldBorder.size = plugin.pluginConfig.data.world.border["size"]!!
|
||||
world.worldBorder.warningDistance = plugin.pluginConfig.data.world.border["warning_distance"]!!.toInt()
|
||||
world.worldBorder.damageAmount = plugin.pluginConfig.data.world.border["damage"]!!
|
||||
|
||||
borderDecrease = plugin.pluginConfig.data.world.border["decrease"]!!
|
||||
|
||||
// GAMERULES >>
|
||||
|
||||
plugin.logger.info("Setting up world... [Stage [2]: GAMERULES]")
|
||||
|
||||
world.setGameRule( GameRule.ANNOUNCE_ADVANCEMENTS, false )
|
||||
world.setGameRule( GameRule.DO_INSOMNIA, false )
|
||||
world.setGameRule( GameRule.DISABLE_RAIDS, true )
|
||||
world.setGameRule( GameRule.DO_PATROL_SPAWNING, false )
|
||||
world.setGameRule( GameRule.DO_TRADER_SPAWNING, false )
|
||||
|
||||
// CHUNKY >>
|
||||
|
||||
plugin.logger.info("Setting up world... [Stage [3]: CHUNKY]")
|
||||
val chunky = Bukkit.getServicesManager().load( ChunkyAPI::class.java )
|
||||
|
||||
if ( chunky == null || chunky.version() != 0 )
|
||||
{
|
||||
plugin.isReady = true
|
||||
return
|
||||
}
|
||||
|
||||
val radius = world.worldBorder.size / 2
|
||||
|
||||
chunky.startTask( worldName, "square", 0.0, 0.0, radius, radius, "concentric" )
|
||||
chunky.onGenerationComplete { plugin.isReady = true }
|
||||
|
||||
plugin.server.dispatchCommand( Bukkit.getConsoleSender(), "chunky silent" )
|
||||
|
||||
// FINISH >>
|
||||
|
||||
plugin.logger.info("World has been set up!")
|
||||
}
|
||||
|
||||
private fun setWorld(
|
||||
worldName: String
|
||||
): World?
|
||||
{
|
||||
this.worldName = worldName
|
||||
val world = Bukkit.getWorld( worldName )
|
||||
|
||||
if ( world != null )
|
||||
this.world = world
|
||||
|
||||
return world
|
||||
}
|
||||
|
||||
fun getWorld(): World?
|
||||
{
|
||||
return if ( !::world.isInitialized )
|
||||
setWorld( plugin.pluginConfig.data.world.name )
|
||||
else this.world
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user