forked from SteamWar/SteamWar
Add TNTLeague Module
This commit is contained in:
@@ -0,0 +1,259 @@
|
||||
package de.steamwar.tntleague.game
|
||||
|
||||
import de.steamwar.scoreboard.SWScoreboard
|
||||
import de.steamwar.sql.Fight
|
||||
import de.steamwar.sql.FightPlayer
|
||||
import de.steamwar.sql.SteamwarUser
|
||||
import de.steamwar.tntleague.config.TNTLeagueConfig
|
||||
import de.steamwar.tntleague.config.TNTLeagueWorldConfig
|
||||
import de.steamwar.tntleague.config.world
|
||||
import de.steamwar.tntleague.events.DummyListener
|
||||
import de.steamwar.tntleague.events.IngameListener
|
||||
import de.steamwar.tntleague.events.LobbyListener
|
||||
import de.steamwar.tntleague.inventory.DealerInventory
|
||||
import de.steamwar.tntleague.plugin
|
||||
import de.steamwar.tntleague.util.*
|
||||
import net.kyori.adventure.bossbar.BossBar
|
||||
import net.kyori.adventure.sound.Sound
|
||||
import org.bukkit.GameMode
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.block.data.type.TNT
|
||||
import org.bukkit.entity.Entity
|
||||
import org.bukkit.entity.Item
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.entity.TNTPrimed
|
||||
import org.bukkit.entity.Villager
|
||||
import org.bukkit.event.HandlerList
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.scheduler.BukkitTask
|
||||
import java.sql.Timestamp
|
||||
import java.time.Instant
|
||||
|
||||
object TNTLeagueGame {
|
||||
var state: GameState = GameState.LOBBY
|
||||
set(value) {
|
||||
if (field.listener != value.listener) {
|
||||
HandlerList.unregisterAll(field.listener)
|
||||
plugin.server.pluginManager.registerEvents(value.listener, plugin)
|
||||
}
|
||||
field = value
|
||||
}
|
||||
|
||||
var gameTimeRemaining: Int = TNTLeagueConfig.config.gameTime
|
||||
|
||||
val blueTeam = TNTLeagueTeam(TNTLeagueWorldConfig.blueTeam, TNTLeagueTeam.Team.BLUE)
|
||||
val redTeam = TNTLeagueTeam(TNTLeagueWorldConfig.redTeam, TNTLeagueTeam.Team.RED)
|
||||
|
||||
private lateinit var start: Timestamp
|
||||
|
||||
private var task: Int? = null
|
||||
private lateinit var spawnerTask: BukkitTask
|
||||
private lateinit var timerTask: BukkitTask
|
||||
|
||||
private fun setup() {
|
||||
assert(state == GameState.STARTING) { "Game is already running" }
|
||||
|
||||
state = GameState.RUNNING
|
||||
|
||||
plugin.server.onlinePlayers.forEach { SWScoreboard.createScoreboard(it, TNTLeagueScoreboard(it)) }
|
||||
|
||||
blueTeam.start()
|
||||
redTeam.start()
|
||||
|
||||
plugin.server.broadcast(translate("gameStarted").success())
|
||||
|
||||
val tnt = ItemStack(Material.TNT)
|
||||
|
||||
start = Timestamp.from(Instant.now())
|
||||
|
||||
spawnerTask = plugin.server.scheduler.runTaskTimer(plugin, bukkit {
|
||||
if (world.getNearbyEntitiesByType(Item::class.java, TNTLeagueWorldConfig.blueTeam.itemSpawn, 3.0).sumOf { it.itemStack.amount } <= 256) {
|
||||
spawnItems(TNTLeagueWorldConfig.blueTeam.itemSpawn, tnt)
|
||||
spawnItems(TNTLeagueWorldConfig.blueTeam.itemSpawn, DealerInventory.coins)
|
||||
}
|
||||
if (world.getNearbyEntitiesByType(Item::class.java, TNTLeagueWorldConfig.redTeam.itemSpawn, 3.0).sumOf { it.itemStack.amount } <= 256) {
|
||||
spawnItems(TNTLeagueWorldConfig.redTeam.itemSpawn, tnt)
|
||||
spawnItems(TNTLeagueWorldConfig.redTeam.itemSpawn, DealerInventory.coins)
|
||||
}
|
||||
}, 5, 10)
|
||||
|
||||
timerTask = plugin.server.scheduler.runTaskTimer(plugin, bukkit {
|
||||
gameTimeRemaining--
|
||||
if (gameTimeRemaining == 0) {
|
||||
draw(WinReason.TIMEOUT)
|
||||
return@bukkit
|
||||
}
|
||||
|
||||
if (gameTimeRemaining % 300 == 0) {
|
||||
plugin.server.broadcast(translate("timeRemaining", (gameTimeRemaining / 60).toString().yellow()).basic())
|
||||
plugin.server.onlinePlayers.forEach { it.playSound(Sound.sound(org.bukkit.Sound.BLOCK_NOTE_BLOCK_PLING.key, Sound.Source.MASTER, 1f, 1f)) }
|
||||
}
|
||||
}, 20, 20)
|
||||
}
|
||||
|
||||
private fun bukkit(f: () -> Unit): () -> Unit = f
|
||||
|
||||
private fun end() {
|
||||
if(state != GameState.RUNNING) return
|
||||
state = GameState.END
|
||||
|
||||
plugin.server.onlinePlayers.forEach {
|
||||
it.gameMode = GameMode.SPECTATOR
|
||||
SWScoreboard.removeScoreboard(it)
|
||||
it.playSound(Sound.sound(org.bukkit.Sound.ENTITY_ENDER_DRAGON_DEATH.key, Sound.Source.MASTER, 1f, 1f))
|
||||
}
|
||||
|
||||
plugin.server.broadcast(translate("gameEnded").success())
|
||||
|
||||
spawnerTask.cancel()
|
||||
|
||||
var shutdown = 10
|
||||
|
||||
plugin.server.scheduler.runTaskTimer(plugin, bukkit {
|
||||
if (shutdown == 0) {
|
||||
plugin.server.shutdown()
|
||||
}
|
||||
|
||||
plugin.server.broadcast(translate("shutdown", shutdown.toString().yellow()).basic())
|
||||
|
||||
shutdown--
|
||||
}, 20, 20)
|
||||
}
|
||||
|
||||
private fun spawnItems(loc: Location, item: ItemStack) = plugin.server.worlds.first().dropItem(loc, item)
|
||||
|
||||
fun getTeam(player: Player) = if (player in blueTeam.members) blueTeam else if (player in redTeam.members) redTeam else null
|
||||
|
||||
fun getFreeTeam() = if (blueTeam.leader == null) blueTeam else if (redTeam.leader == null) redTeam else null
|
||||
|
||||
fun checkStart() {
|
||||
if (blueTeam.isReady && redTeam.isReady) {
|
||||
blueTeam.leader?.inventory?.clear()
|
||||
redTeam.leader?.inventory?.clear()
|
||||
state = GameState.STARTING
|
||||
|
||||
var countdown = TNTLeagueConfig.config.startDelay
|
||||
plugin.server.broadcast(translate("gameStarting", countdown.toString().yellow()).basic())
|
||||
val bar = BossBar.bossBar(translate("gameStart", countdown.toString().yellow()).gray(), (TNTLeagueConfig.config.startDelay - countdown) / TNTLeagueConfig.config.startDelay.toFloat(), BossBar.Color.GREEN, BossBar.Overlay.NOTCHED_10)
|
||||
plugin.server.onlinePlayers.forEach { bar.addViewer(it) }
|
||||
task = plugin.server.scheduler.scheduleSyncRepeatingTask(plugin, {
|
||||
plugin.server.onlinePlayers.forEach { it.playSound(Sound.sound(org.bukkit.Sound.ENTITY_EXPERIENCE_ORB_PICKUP.key, Sound.Source.MASTER, 1f, 1f)) }
|
||||
if (countdown-- == 0) {
|
||||
plugin.server.onlinePlayers.forEach { it.hideBossBar(bar) }
|
||||
task = task?.also { plugin.server.scheduler.cancelTask(it) }.let { null }
|
||||
setup()
|
||||
} else {
|
||||
bar.name(translate("gameStart", countdown.toString().yellow()).gray())
|
||||
bar.progress((TNTLeagueConfig.config.startDelay - countdown) / TNTLeagueConfig.config.startDelay.toFloat())
|
||||
plugin.server.onlinePlayers.filter { !it.activeBossBars().contains(bar) }.forEach { bar.addViewer(it) }
|
||||
}
|
||||
}, 20, 20)
|
||||
|
||||
if (task == -1) {
|
||||
error("Failed to start countdown task")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun playerLeave(player: Player) {
|
||||
blueTeam.invites.remove(player)
|
||||
redTeam.invites.remove(player)
|
||||
getTeam(player)?.apply {
|
||||
members.remove(player)
|
||||
if (leader == player) {
|
||||
win(this.opposite, WinReason.LEAVE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
assert(state == GameState.LOBBY || state == GameState.STARTING) { "Game is not in lobby or starting state" }
|
||||
|
||||
if (state == GameState.STARTING) {
|
||||
task = task?.also { plugin.server.scheduler.cancelTask(it) }.let { null }
|
||||
plugin.server.onlinePlayers.forEach { p -> p.activeBossBars().forEach { it.removeViewer(p) } }
|
||||
state = GameState.LOBBY
|
||||
}
|
||||
}
|
||||
|
||||
fun win(tntLeagueTeam: TNTLeagueTeam, reason: WinReason) {
|
||||
if (state != GameState.RUNNING) return
|
||||
end()
|
||||
plugin.server.broadcast(translate("teamWin", translate(tntLeagueTeam.name).color(tntLeagueTeam.color)).success())
|
||||
statistic(tntLeagueTeam, reason)
|
||||
explode(tntLeagueTeam.opposite)
|
||||
}
|
||||
|
||||
fun draw(reason: WinReason) {
|
||||
if (state != GameState.RUNNING) return
|
||||
end()
|
||||
plugin.server.broadcast(translate("draw").success())
|
||||
statistic(null, reason)
|
||||
}
|
||||
|
||||
fun explode(team: TNTLeagueTeam) {
|
||||
Area(team.config.spawnLocation.clone().add(20.0, 30.0, 20.0), team.config.spawnLocation.clone().subtract(20.0, 0.0, 20.0).add(0.0, 30.0, 0.0))
|
||||
.locations
|
||||
.filterIndexed { index, _ -> index % 7 == 0 }
|
||||
.forEachIndexed { index, location ->
|
||||
world.spawn(location, TNTPrimed::class.java).apply {
|
||||
fuseTicks = index + 40
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun statistic(winTeam: TNTLeagueTeam?, reason: WinReason) {
|
||||
val fightId = Fight.create(
|
||||
"TNTLeague",
|
||||
world.name,
|
||||
start,
|
||||
TNTLeagueConfig.config.gameTime - gameTimeRemaining,
|
||||
SteamwarUser.get(blueTeam.leader!!.uniqueId).id,
|
||||
SteamwarUser.get(redTeam.leader!!.uniqueId).id,
|
||||
null,
|
||||
null,
|
||||
when (winTeam) {
|
||||
blueTeam -> 1
|
||||
redTeam -> 2
|
||||
else -> 0
|
||||
},
|
||||
when (reason) {
|
||||
WinReason.TIMEOUT -> "TIMEOUT"
|
||||
WinReason.DESTROYED -> "DESTROYED"
|
||||
WinReason.LEAVE -> "LEAVE"
|
||||
}
|
||||
)
|
||||
|
||||
addTeamMember(blueTeam, fightId)
|
||||
addTeamMember(redTeam, fightId)
|
||||
}
|
||||
|
||||
private fun addTeamMember(team: TNTLeagueTeam, fightId: Int) {
|
||||
team.members.filter { team.leader != it }
|
||||
.forEach {
|
||||
FightPlayer.create(
|
||||
fightId,
|
||||
SteamwarUser.get(it.uniqueId).id,
|
||||
team == blueTeam,
|
||||
"TNTLeague",
|
||||
0,
|
||||
false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
enum class GameState(val listener: Listener) {
|
||||
LOBBY(LobbyListener),
|
||||
STARTING(LobbyListener),
|
||||
RUNNING(IngameListener),
|
||||
END(DummyListener);
|
||||
}
|
||||
|
||||
enum class WinReason {
|
||||
TIMEOUT,
|
||||
DESTROYED,
|
||||
LEAVE
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user