蚯嫁嚎坏事做尽!*2

This commit is contained in:
tony_all 2022-11-01 14:07:56 +08:00
parent 4f37b3e2b9
commit 5124478878
10 changed files with 93 additions and 22 deletions

View File

@ -6,6 +6,7 @@ import cc.maxmc.blastingcrisis.game.GameState
import cc.maxmc.blastingcrisis.map.GameMap import cc.maxmc.blastingcrisis.map.GameMap
import cc.maxmc.blastingcrisis.map.MapTeam import cc.maxmc.blastingcrisis.map.MapTeam
import cc.maxmc.blastingcrisis.misc.Area import cc.maxmc.blastingcrisis.misc.Area
import cc.maxmc.blastingcrisis.misc.GameManager
import cc.maxmc.blastingcrisis.packet.BEntityVillager import cc.maxmc.blastingcrisis.packet.BEntityVillager
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import org.bukkit.Bukkit import org.bukkit.Bukkit
@ -60,11 +61,16 @@ object DebugCommand {
), ),
) )
val map = GameMap( val map = GameMap(
"test", Area(location(20, 70, -49), location(-20, 79, 49)), listOf( "test",
Area(location(20, 70, -49), location(-20, 79, 49)),
Area(location(-13, 78, 0), location(13, 72, 0)),
listOf(
teamRed, teamGreen teamRed, teamGreen
), 4 ),
1
) )
game = Game(map) game = Game(map)
GameManager.currentGame = game
} }
literal("join") { literal("join") {

View File

@ -2,8 +2,12 @@ package cc.maxmc.blastingcrisis.game
import cc.maxmc.blastingcrisis.map.GameMap import cc.maxmc.blastingcrisis.map.GameMap
import cc.maxmc.blastingcrisis.misc.debug import cc.maxmc.blastingcrisis.misc.debug
import org.bukkit.Bukkit
import org.bukkit.Material
import org.bukkit.entity.Player import org.bukkit.entity.Player
import taboolib.common.platform.function.submit
import taboolib.platform.util.sendLang import taboolib.platform.util.sendLang
import java.time.Duration
class Game( class Game(
val map: GameMap, val map: GameMap,
@ -26,6 +30,7 @@ class Game(
it.sendLang("game_join", player.name) it.sendLang("game_join", player.name)
} }
scoreboard.sendScoreboard() scoreboard.sendScoreboard()
checkStart()
} }
fun leave(player: Player) { fun leave(player: Player) {
@ -43,7 +48,16 @@ class Game(
fun start() { fun start() {
debug("game ${map.name} started.") debug("game ${map.name} started.")
state = GameState.START
timer.startTimer() timer.startTimer()
timer.submitEvent("wall_fall", Duration.ofMinutes(1)) {
broadcast { it.sendLang("game_wall_fall") }
submit(now = true) {
map.wall.forBlocksInArea().forEach {
it.block.type = Material.AIR
}
}
}
autoJoinTeam() autoJoinTeam()
teams.forEach { teams.forEach {
it.start() it.start()
@ -68,6 +82,7 @@ class Game(
} }
broadcast { it.sendLang("game_end") } broadcast { it.sendLang("game_end") }
//TODO restart game logic
} }
fun broadcast(action: (Player) -> Unit) { fun broadcast(action: (Player) -> Unit) {

View File

@ -23,8 +23,24 @@ class GameScoreboard(val game: Game) {
COUNTING_DOWN -> { COUNTING_DOWN -> {
player.asLangText("scoreboard_counting_down", game.players.size, game.map.maxPlayer, game.timer.current) player.asLangText("scoreboard_counting_down", game.players.size, game.map.maxPlayer, game.timer.current)
} }
START -> TODO()
WALL_FALL -> TODO() START -> {
val event = game.timer.nextEvent
val teamMessage = buildString {
game.teams.forEach {
appendLine(player.asLangText("scoreboard_team_info", it.teamInfo.name, it.villager.health))
}
}
player.asLangText(
"scoreboard_start",
event.second,
"${event.first.inWholeMinutes}:${event.first.inWholeSeconds}",
teamMessage,
player.team?.villager?.health ?: throw IllegalStateException("player ${player.name} has no team."),
0, // TODO Kill counter
)
}
FINISH -> TODO() FINISH -> TODO()
} }

View File

@ -4,8 +4,7 @@ enum class GameState {
WAITING, WAITING,
COUNTING_DOWN, COUNTING_DOWN,
START, START,
WALL_FALL,
FINISH; FINISH;
fun isStarted(): Boolean = this == START || this == WALL_FALL fun isStarted(): Boolean = this == START
} }

View File

@ -2,6 +2,7 @@ package cc.maxmc.blastingcrisis.game
import cc.maxmc.blastingcrisis.listener.GameListener import cc.maxmc.blastingcrisis.listener.GameListener
import cc.maxmc.blastingcrisis.map.MapTeam import cc.maxmc.blastingcrisis.map.MapTeam
import cc.maxmc.blastingcrisis.misc.debug
import org.bukkit.entity.Player import org.bukkit.entity.Player
import taboolib.platform.util.sendLang import taboolib.platform.util.sendLang
@ -16,7 +17,7 @@ class GameTeam(val game: Game, val teamInfo: MapTeam) {
players.forEach { it.teleport(teamInfo.spawn) } players.forEach { it.teleport(teamInfo.spawn) }
villager.spawn() villager.spawn()
GameListener.interactSubscribed[teamInfo.upgrade] = { GameListener.interactSubscribed[teamInfo.upgrade] = {
debug("interact team ${teamInfo.name} upgrade.")
} }
} }

View File

@ -1,6 +1,7 @@
package cc.maxmc.blastingcrisis.game package cc.maxmc.blastingcrisis.game
import cc.maxmc.blastingcrisis.configuration.GlobalSettings import cc.maxmc.blastingcrisis.configuration.GlobalSettings
import cc.maxmc.blastingcrisis.misc.info
import cc.maxmc.blastingcrisis.misc.pluginScope import cc.maxmc.blastingcrisis.misc.pluginScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -9,10 +10,18 @@ import kotlinx.coroutines.launch
import taboolib.common.platform.function.adaptCommandSender import taboolib.common.platform.function.adaptCommandSender
import taboolib.module.lang.getLocaleFile import taboolib.module.lang.getLocaleFile
import taboolib.platform.util.sendLang import taboolib.platform.util.sendLang
import kotlin.time.Duration
import kotlin.time.DurationUnit
import kotlin.time.toDuration
class GameTimer(private val game: Game) { class GameTimer(private val game: Game) {
lateinit var countdownJob: Job private val events = ArrayList<Triple<Long, String, () -> Unit>>()
private lateinit var timerJob: Job
private lateinit var countdownJob: Job
private var start: Long = 0
var current = GlobalSettings.timeToStart var current = GlobalSettings.timeToStart
lateinit var nextEvent: Triple<Duration, String, () -> Unit>
private set
fun beginCountdown() { fun beginCountdown() {
countdownJob = pluginScope.launch { countdownJob = pluginScope.launch {
@ -46,6 +55,26 @@ class GameTimer(private val game: Game) {
} }
fun startTimer() { fun startTimer() {
start = System.nanoTime()
timerJob = pluginScope.launch {
while (true) {
val toDos = events.filter { it.first <= System.nanoTime() }
toDos.forEach { (_, _, toDo) -> toDo() }
events.removeAll(toDos.toSet())
events.minByOrNull { it.first }?.also {
val duration = (it.first - System.nanoTime()).toDuration(DurationUnit.NANOSECONDS)
nextEvent = Triple(duration, it.second, it.third)
} ?: let { nextEvent = Triple(Duration.INFINITE, "end") {} }
game.scoreboard.sendScoreboard()
delay(1000)
} }
}
}
fun submitEvent(name: String, time: java.time.Duration, `do`: () -> Unit) {
events.add(Triple(time.toNanos() + start, name, `do`))
}
} }

View File

@ -2,6 +2,7 @@ package cc.maxmc.blastingcrisis.listener
import cc.maxmc.blastingcrisis.game.team import cc.maxmc.blastingcrisis.game.team
import cc.maxmc.blastingcrisis.misc.GameManager import cc.maxmc.blastingcrisis.misc.GameManager
import cc.maxmc.blastingcrisis.misc.debug
import org.bukkit.Location import org.bukkit.Location
import org.bukkit.event.block.BlockExplodeEvent import org.bukkit.event.block.BlockExplodeEvent
import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.event.player.PlayerInteractEvent
@ -17,7 +18,8 @@ object GameListener {
val player = event.player val player = event.player
val team = player.team ?: return val team = player.team ?: return
if (!team.teamInfo.teleport.isInArea(event.to)) return if (!team.teamInfo.teleport.isInArea(event.to)) return
debug("teleporting ${event.player} to battle field")
player.teleport(team.teamInfo.mine.randomLocation())
} }
@SubscribeEvent @SubscribeEvent
@ -28,11 +30,13 @@ object GameListener {
@SubscribeEvent @SubscribeEvent
fun onTNT(tntExplode: BlockExplodeEvent) { fun onTNT(tntExplode: BlockExplodeEvent) {
GameManager.currentGame.teams.forEach { debug("tnt exploded at ${tntExplode.block.location}")
if (!it.teamSurvive) return tntExplode.blockList().clear()
if (!it.teamInfo.home.isInArea(tntExplode.block.location)) return GameManager.currentGame.teams.findLast {
it.teamSurvive && it.teamInfo.home.isInArea(tntExplode.block.location)
it.villager.damage() }?.apply {
} villager.damage()
debug("team ${teamInfo.name}'s villager damaged")
} ?: throw IllegalStateException("TNT Exploded at no team, which shouldn't happen")
} }
} }

View File

@ -2,7 +2,7 @@ package cc.maxmc.blastingcrisis.map
import cc.maxmc.blastingcrisis.misc.Area import cc.maxmc.blastingcrisis.misc.Area
class GameMap(val name: String, val area: Area, val teams: List<MapTeam>, val maxPlayersPerTeam: Int) { class GameMap(val name: String, val area: Area, val wall: Area, val teams: List<MapTeam>, val maxPlayersPerTeam: Int) {
val maxPlayer: Int val maxPlayer: Int
get() = maxPlayersPerTeam * teams.size get() = maxPlayersPerTeam * teams.size
} }

View File

@ -30,10 +30,10 @@ class Area(loc1: Location, loc2: Location) : ConfigurationSerializable {
* @return true if the location is in this area * @return true if the location is in this area
*/ */
fun isInArea(location: Location): Boolean { fun isInArea(location: Location): Boolean {
if (location.world != locTop.world) return false if (location.world != locTop.world) return debug("world").let { false }
if (location.x !in locTop.x..locMin.x) return false if (location.x !in locTop.x..locMin.x) return debug("x").let { false }
if (location.y !in locTop.y..locMin.y) return false if (location.y !in locTop.y..locMin.y) return debug("y").let { false }
if (location.z !in locTop.z..locMin.z) return false if (location.z !in locTop.z..locMin.z) return debug("z").let { false }
return true return true
} }

View File

@ -15,7 +15,7 @@ scoreboard_counting_down: |-
§a| §7游戏还有 §a{2} §7秒开始. §a| §7游戏还有 §a{2} §7秒开始.
§6Play.MaxMC.cc §6Play.MaxMC.cc
scoreboard_counting_start: |- scoreboard_start: |-
§6Blasting§7Crisis §6Blasting§7Crisis
§a| §7{0}: §a{1} §a| §7{0}: §a{1}
@ -63,6 +63,7 @@ game_end: |-
§e| §e|
§e| 游戏结束 §e| 游戏结束
§e| §e|
game_wall_fall: "§c| §7战争之墙倒下了!"
## end part game ## end part game
## part team ## part team