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() 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.addRuleLast("allow_center_wall") { (_, _, loc, _) -> if (map.wall.contains(loc)) GamePlaceBreakRule.MatchResult.ALLOW else GamePlaceBreakRule.MatchResult.DEFAULT } 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) } }