add break & place check
optimize code logic of Teleport Listener
This commit is contained in:
parent
97c5c1c9fb
commit
45882c8cb6
|
|
@ -15,6 +15,7 @@ class Game(
|
|||
val scoreboard: GameScoreboard = GameScoreboard(this)
|
||||
val timer: GameTimer = GameTimer(this)
|
||||
val players = ArrayList<Player>()
|
||||
val rule = GamePlaceBreakRule(this)
|
||||
var state: GameState = GameState.WAITING
|
||||
|
||||
private fun autoJoinTeam() {
|
||||
|
|
@ -47,6 +48,7 @@ class Game(
|
|||
|
||||
fun start() {
|
||||
debug("game ${map.name} started.")
|
||||
|
||||
state = GameState.START
|
||||
timer.startTimer()
|
||||
timer.submitEvent("wall_fall", Duration.ofMinutes(1)) {
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
package cc.maxmc.blastingcrisis.game
|
||||
|
||||
import org.bukkit.Location
|
||||
|
||||
class GameBreakRule(val rule: MutableList<(Location) -> Boolean>) {
|
||||
fun matchRule(location: Location) {
|
||||
|
||||
}
|
||||
|
||||
fun addRule(rule: (Location) -> Boolean) {
|
||||
|
||||
}
|
||||
|
||||
fun defaultRule() {
|
||||
rule.add {
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package cc.maxmc.blastingcrisis.game
|
||||
|
||||
import cc.maxmc.blastingcrisis.game.GamePlaceBreakRule.ActionType.BREAK
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class GamePlaceBreakRule(val game: Game) {
|
||||
enum class ActionType {
|
||||
PLACE,
|
||||
BREAK
|
||||
}
|
||||
|
||||
private val rule = ArrayList<(Player, ActionType, Location) -> Boolean>()
|
||||
fun matchRule(player: Player, actionType: ActionType, location: Location): Boolean {
|
||||
// match rules
|
||||
rule.forEach {
|
||||
if (it(player, actionType, location)) return true
|
||||
}
|
||||
|
||||
// fallback strategy
|
||||
return false
|
||||
}
|
||||
|
||||
fun addRule(rule: (Player, Location) -> Boolean) {
|
||||
|
||||
}
|
||||
|
||||
fun defaultRule(game: Game) {
|
||||
// allow mine
|
||||
rule.add { _, _, loc ->
|
||||
game.map.teams.flatMap {
|
||||
it.sides + it.mine
|
||||
}.map {
|
||||
it.containsBlock(loc)
|
||||
}.reduce { a, b -> a || b }
|
||||
}
|
||||
|
||||
// allow enemy wall
|
||||
rule.add { player, type, loc ->
|
||||
val team = player.team ?: return@add false
|
||||
val result = game.teams.filterNot { it == team }
|
||||
.map { team.teamInfo.wall.containsBlock(loc) }
|
||||
.reduce { a, b -> a || b }
|
||||
if (type == BREAK) result else !result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,12 @@ class GameTeam(val game: Game, val teamInfo: MapTeam) {
|
|||
GameListener.interactSubscribed[teamInfo.upgrade] = {
|
||||
debug("interact team ${teamInfo.name} upgrade.")
|
||||
}
|
||||
GameListener.moveSubscribed.add(teamInfo.teleport to {
|
||||
val player = it.player ?: throw IllegalStateException("Bukkit API LOL")
|
||||
debug("teleporting $player to battle field")
|
||||
val team = player.team ?: throw IllegalStateException("Player ${player.name} should have a team")
|
||||
player.teleport(team.teamInfo.mine.randomLocation().toPlayerLocation())
|
||||
})
|
||||
}
|
||||
|
||||
fun join(player: Player) {
|
||||
|
|
|
|||
|
|
@ -1,27 +1,29 @@
|
|||
package cc.maxmc.blastingcrisis.listener
|
||||
|
||||
import cc.maxmc.blastingcrisis.game.GamePlaceBreakRule
|
||||
import cc.maxmc.blastingcrisis.game.team
|
||||
import cc.maxmc.blastingcrisis.misc.Area
|
||||
import cc.maxmc.blastingcrisis.misc.GameManager
|
||||
import cc.maxmc.blastingcrisis.misc.debug
|
||||
import cc.maxmc.blastingcrisis.misc.toPlayerLocation
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.event.block.BlockBreakEvent
|
||||
import org.bukkit.event.block.BlockPlaceEvent
|
||||
import org.bukkit.event.entity.EntityExplodeEvent
|
||||
import org.bukkit.event.player.PlayerInteractEvent
|
||||
import org.bukkit.event.player.PlayerMoveEvent
|
||||
import taboolib.common.platform.event.SubscribeEvent
|
||||
import taboolib.platform.util.sendLang
|
||||
|
||||
object GameListener {
|
||||
val interactSubscribed = HashMap<Location, (PlayerInteractEvent) -> Unit>()
|
||||
val moveSubscribed = ArrayList<Pair<Area, (PlayerMoveEvent) -> Unit>>()
|
||||
|
||||
@SubscribeEvent
|
||||
fun portalTeleport(event: PlayerMoveEvent) {
|
||||
if (!GameManager.currentGame.players.contains(event.player)) return
|
||||
val player = event.player
|
||||
val team = player.team ?: return
|
||||
if (!team.teamInfo.teleport.isInArea(event.to)) return
|
||||
debug("teleporting ${event.player} to battle field")
|
||||
player.teleport(team.teamInfo.mine.randomLocation().toPlayerLocation())
|
||||
moveSubscribed.forEach { (area, func) ->
|
||||
if (area.contains(event.to)) func(event)
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
|
@ -36,7 +38,7 @@ object GameListener {
|
|||
tntExplode.blockList().clear()
|
||||
if (!GameManager.currentGame.state.isStarted()) return
|
||||
GameManager.currentGame.teams.findLast {
|
||||
it.teamSurvive && it.teamInfo.home.isInArea(tntExplode.location)
|
||||
it.teamSurvive && it.teamInfo.home.contains(tntExplode.location)
|
||||
}?.apply {
|
||||
villager.damage()
|
||||
debug("team ${teamInfo.name}'s villager damaged")
|
||||
|
|
@ -45,7 +47,19 @@ object GameListener {
|
|||
|
||||
@SubscribeEvent
|
||||
fun onBreak(breakEvent: BlockBreakEvent) {
|
||||
val loc = breakEvent.block.location
|
||||
val loc = breakEvent.block.location ?: return
|
||||
val player = breakEvent.player ?: return
|
||||
if (GameManager.currentGame.rule.matchRule(player, GamePlaceBreakRule.ActionType.BREAK, loc)) return
|
||||
breakEvent.isCancelled = true
|
||||
player.sendLang("game_cant_break_block")
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun onPlace(placeEvent: BlockPlaceEvent) {
|
||||
val loc = placeEvent.block.location ?: return
|
||||
val player = placeEvent.player ?: return
|
||||
if (GameManager.currentGame.rule.matchRule(player, GamePlaceBreakRule.ActionType.PLACE, loc)) return
|
||||
placeEvent.isCancelled = true
|
||||
player.sendLang("game_cant_place_block")
|
||||
}
|
||||
}
|
||||
|
|
@ -9,5 +9,4 @@ class MapInfo(
|
|||
var waitArea: Area,
|
||||
val teams: List<MapTeam>,
|
||||
val maxPlayersPerTeam: Int,
|
||||
|
||||
)
|
||||
|
|
@ -31,15 +31,14 @@ class Area(loc1: Location, loc2: Location) : ConfigurationSerializable {
|
|||
*
|
||||
* @return true if the location is in this area
|
||||
*/
|
||||
fun isInArea(location: Location): Boolean {
|
||||
fun contains(location: Location): Boolean {
|
||||
if (location.world != locTop.world) return false
|
||||
if (location.x !in (locMin.x - 1)..(locTop.x + 1)) return false
|
||||
if (location.y !in locMin.y..locTop.y + 1) return false
|
||||
return location.z in (locMin.z - 1)..(locTop.z + 1)
|
||||
}
|
||||
|
||||
fun isBlockInArea(block: Block): Boolean {
|
||||
val location = block.location
|
||||
fun containsBlock(location: Location): Boolean {
|
||||
if (location.world != locTop.world) return false
|
||||
if (location.x !in locMin.x..locTop.x) return false
|
||||
if (location.y !in locMin.y..locTop.y) return false
|
||||
|
|
|
|||
Loading…
Reference in New Issue