BlastingCrisis/src/main/kotlin/cc/maxmc/blastingcrisis/game/Game.kt

98 lines
2.7 KiB
Kotlin

package cc.maxmc.blastingcrisis.game
import cc.maxmc.blastingcrisis.map.GameMap
import cc.maxmc.blastingcrisis.misc.debug
import org.bukkit.Material
import org.bukkit.entity.Player
import taboolib.common.platform.function.submit
import taboolib.platform.util.sendLang
import java.time.Duration
class Game(
val map: GameMap,
) {
val teams = map.teams.map { GameTeam(this, it) }
val scoreboard: GameScoreboard = GameScoreboard(this)
val timer: GameTimer = GameTimer(this)
val players = ArrayList<Player>()
val placeBreakRule = GamePlaceBreakRule(this)
var state: GameState = GameState.WAITING
private fun autoJoinTeam() {
players.filter { it.team == null }.shuffled().forEach {
teams.minBy { team -> team.players.size }.join(it)
}
}
fun join(player: Player) {
players += player
broadcast {
it.sendLang("game_join", player.name)
}
scoreboard.sendScoreboard()
checkStart()
}
fun leave(player: Player) {
if (state == GameState.WAITING || state == GameState.COUNTING_DOWN) {
players.remove(player)
player.team?.removePlayer(player)
broadcast { it.sendLang("game_leave", player.name) }
checkStart()
}
val team =
player.team ?: throw IllegalStateException("Player ${player.name} has no team, which shouldn't happen.")
team.removePlayer(player)
checkEnd()
}
fun start() {
debug("game ${map.name} started.")
placeBreakRule.loadDefaultRule()
state = GameState.START
timer.startTimer()
timer.submitEvent("wall_fall", Duration.ofMinutes(1)) {
broadcast { it.sendLang("game_wall_fall") }
placeBreakRule.addRule("allow_center_wall") { _, _, loc, _ ->
map.wall.contains(loc)
}
submit {
map.wall.forBlocksInArea().forEach {
it.block.type = Material.AIR
}
}
}
autoJoinTeam()
teams.forEach {
it.start()
}
}
private fun checkStart() {
if (players.size < map.maxPlayer * 0.5 && state == GameState.COUNTING_DOWN) {
state = GameState.WAITING
timer.resetCountdown()
}
if (players.size > map.maxPlayer * 0.75) {
state = GameState.COUNTING_DOWN
timer.beginCountdown()
}
}
fun checkEnd() {
if (teams.filter { it.teamSurvive }.size > 1) {
return
}
broadcast { it.sendLang("game_end") }
//TODO restart game logic
}
fun broadcast(action: (Player) -> Unit) {
players.forEach(action)
}
}