fix 重生后村民不可见

finish 方块禁止破坏
update 计分板显示
finish TNT自动点燃
finish 优化传送体验
finish 防止重复加入检测
This commit is contained in:
TONY_All 2024-08-08 20:11:55 +08:00
parent a063e8c6dd
commit ff96cf59da
Signed by: tony_all
GPG Key ID: 08A2261D5D6F746A
13 changed files with 134 additions and 53 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
.idea .idea
build/ build/
test_server

View File

@ -40,7 +40,7 @@ taboolib {
// classifier = null // classifier = null
// options("skip-kotlin-relocate") // options("skip-kotlin-relocate")
version { version {
taboolib = "6.1.1" taboolib = "6.1.2-beta2"
} }
} }

View File

@ -48,16 +48,16 @@ object BlastingCrisis : Plugin() {
Location(Bukkit.getWorlds().first(), x.toDouble(), y.toDouble(), z.toDouble()) Location(Bukkit.getWorlds().first(), x.toDouble(), y.toDouble(), z.toDouble())
val teamRed = MapTeam( val teamRed = MapTeam(
"红队", name = "红队",
ChatColor.RED, color = ChatColor.RED,
location(0, 72, -44), spawn = location(0, 72, -44),
location(0, 72, -44), villager = location(0, 72, -44),
location(-8, 73, -47), upgrade = location(-8, 73, -47),
Area(location(14, 72, -48), location(-14, 78, -34)), home = Area(location(14, 72, -48), location(-14, 78, -34)),
Area(location(-13, 78, -33), location(13, 72, -33)), wall = Area(location(-13, 78, -33), location(13, 72, -33)),
Area(location(-13, 78, -32), location(13, 72, -1)), mine = Area(location(-13, 78, -32), location(13, 72, -1)),
Area(location(7, 72, -45), location(9, 74, -48)), teleport = Area(location(7, 72, -45), location(9, 74, -48)),
listOf( sides = listOf(
Area(location(15, 72, -1), location(19, 78, -48)), Area(location(-19, 78, -48), location(-15, 72, -1)) Area(location(15, 72, -1), location(19, 78, -48)), Area(location(-19, 78, -48), location(-15, 72, -1))
), ),
) )
@ -70,7 +70,8 @@ object BlastingCrisis : Plugin() {
Area(location(-14, 72, 48), location(14, 78, 34)), Area(location(-14, 72, 48), location(14, 78, 34)),
Area(location(13, 78, 33), location(-13, 72, 33)), Area(location(13, 78, 33), location(-13, 72, 33)),
Area(location(13, 78, 32), location(-13, 72, 1)), Area(location(13, 78, 32), location(-13, 72, 1)),
Area(location(-7, 72, 45), location(-9, 74, 48)), Area(location(-7, 71, 48), location(-9, 71, 46)),
// Area(location(-7, 72, 45), location(-9, 74, 48)),
listOf( listOf(
Area(location(-15, 72, 1), location(-19, 78, 48)), Area(location(19, 78, 48), location(15, 72, 1)) Area(location(-15, 72, 1), location(-19, 78, 48)), Area(location(19, 78, 48), location(15, 72, 1))
), ),

View File

@ -2,8 +2,11 @@ package cc.maxmc.blastingcrisis.command
import cc.maxmc.blastingcrisis.game.Game import cc.maxmc.blastingcrisis.game.Game
import cc.maxmc.blastingcrisis.game.GameOreGenerator import cc.maxmc.blastingcrisis.game.GameOreGenerator
import cc.maxmc.blastingcrisis.game.GamePlaceBreakRule
import cc.maxmc.blastingcrisis.game.GamePlaceBreakRule.MatchResult
import cc.maxmc.blastingcrisis.game.GameState import cc.maxmc.blastingcrisis.game.GameState
import cc.maxmc.blastingcrisis.misc.Area import cc.maxmc.blastingcrisis.misc.Area
import cc.maxmc.blastingcrisis.misc.GameManager
import cc.maxmc.blastingcrisis.misc.UniArea import cc.maxmc.blastingcrisis.misc.UniArea
import cc.maxmc.blastingcrisis.packet.BEntityVillager import cc.maxmc.blastingcrisis.packet.BEntityVillager
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
@ -15,13 +18,28 @@ import taboolib.common.platform.function.adaptCommandSender
import taboolib.common.platform.function.getDataFolder import taboolib.common.platform.function.getDataFolder
import taboolib.module.configuration.Configuration import taboolib.module.configuration.Configuration
import taboolib.platform.BukkitPlugin import taboolib.platform.BukkitPlugin
import taboolib.platform.util.broadcast
import taboolib.platform.util.sendActionBar import taboolib.platform.util.sendActionBar
import java.io.File import java.io.File
import java.util.UUID
import cc.maxmc.blastingcrisis.misc.debug as debuglog
object DebugCommand { object DebugCommand {
lateinit var game: Game lateinit var game: Game
lateinit var villager: BEntityVillager lateinit var villager: BEntityVillager
var autoRespawn = false
val builders = ArrayList<UUID>()
private val init by lazy{
// allow builders
debuglog("init builder rule")
GameManager.currentGame.placeBreakRule.addRuleFirst("builder") { (player, _, _, _) ->
// cc.maxmc.blastingcrisis.misc.debug("matching builder rule")
if (builders.contains(player.uniqueId)) MatchResult.ALLOW else MatchResult.DEFAULT
}
}
fun debug(cmd: String) = command(cmd) { fun debug(cmd: String) = command(cmd) {
literal("game") { literal("game") {
literal("join") { literal("join") {
execute<Player> { sender, _, _ -> execute<Player> { sender, _, _ ->
@ -80,7 +98,15 @@ object DebugCommand {
literal("respawn") { literal("respawn") {
execute<Player> { sender, _, _ -> execute<Player> { sender, _, _ ->
villager.spawnForPlayer(sender) villager.removeViewer(sender)
villager.addViewer(sender)
}
}
literal("autoRespawn") {
execute<Player> { sender, _, _ ->
autoRespawn = !autoRespawn
sender.sendMessage("Auto Respawn is now $autoRespawn.")
} }
} }
@ -129,5 +155,18 @@ object DebugCommand {
}, 60 * 20) }, 60 * 20)
} }
} }
literal("build_mode") {
execute<Player> { sender, _ ,_ ->
init
if (builders.contains(sender.uniqueId)) {
builders.remove(sender.uniqueId)
sender.sendMessage("U r no longer in build mode")
return@execute
}
sender.sendMessage("U r now in build mode")
builders.add(sender.uniqueId)
}
}
} }
} }

View File

@ -1,9 +1,13 @@
package cc.maxmc.blastingcrisis.debug package cc.maxmc.blastingcrisis.debug
import cc.maxmc.blastingcrisis.command.DebugCommand
import cc.maxmc.blastingcrisis.command.DebugCommand.villager
import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy
import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntityLiving import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntityLiving
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.event.player.PlayerRespawnEvent
import taboolib.common.platform.event.SubscribeEvent import taboolib.common.platform.event.SubscribeEvent
import taboolib.common.platform.function.submit
import taboolib.library.reflex.Reflex.Companion.getProperty import taboolib.library.reflex.Reflex.Companion.getProperty
import taboolib.module.nms.PacketSendEvent import taboolib.module.nms.PacketSendEvent
import taboolib.platform.BukkitPlugin import taboolib.platform.BukkitPlugin
@ -29,4 +33,15 @@ object DListener {
} }
} }
} }
@SubscribeEvent
fun debugRespawn(respawnE: PlayerRespawnEvent) {
if (DebugCommand.autoRespawn) {
submit(delay = 1L) {
villager.removeViewer(respawnE.player)
"Respawning".broadcast()
villager.addViewer(respawnE.player)
}
}
}
} }

View File

@ -32,6 +32,10 @@ class Game(
} }
fun join(player: Player) { fun join(player: Player) {
if (players.map { it.uniqueId }.contains(player.uniqueId)) {
player.sendLang("game_already_join")
return
}
players += player players += player
broadcast { broadcast {
it.sendLang("game_join", player.name) it.sendLang("game_join", player.name)
@ -54,14 +58,16 @@ class Game(
} }
fun respawnPlayer(player: Player) { fun respawnPlayer(player: Player) {
teams.forEach { it.villager.respawn(player) } submit(delay = 1L) {
teams.forEach { it.villager.respawn(player) }
}
} }
fun start() { fun start() {
debug("game ${map.name} started.") debug("game ${map.name} started.")
placeBreakRule.loadDefaultRule() placeBreakRule.loadDefaultRule()
// startOreGen() startOreGen()
// startItemGen() startItemGen()
state = GameState.START state = GameState.START
timer.startTimer() timer.startTimer()
timer.submitEvent("wall_fall", Duration.ofMinutes(1)) { timer.submitEvent("wall_fall", Duration.ofMinutes(1)) {
@ -115,12 +121,13 @@ class Game(
return return
} }
broadcast { it.sendLang("game_end") } broadcast {
it.sendLang("game_end")
}
//TODO restart game logic //TODO restart game logic
} }
fun broadcast(action: (Player) -> Unit) { fun broadcast(action: (Player) -> Unit) {
players.forEach(action) players.forEach(action)
} }
} }

View File

@ -1,5 +1,6 @@
package cc.maxmc.blastingcrisis.game package cc.maxmc.blastingcrisis.game
import cc.maxmc.blastingcrisis.command.DebugCommand
import cc.maxmc.blastingcrisis.game.GamePlaceBreakRule.ActionType.BREAK import cc.maxmc.blastingcrisis.game.GamePlaceBreakRule.ActionType.BREAK
import cc.maxmc.blastingcrisis.game.GamePlaceBreakRule.ActionType.PLACE import cc.maxmc.blastingcrisis.game.GamePlaceBreakRule.ActionType.PLACE
import cc.maxmc.blastingcrisis.misc.EnhancedLinkedList import cc.maxmc.blastingcrisis.misc.EnhancedLinkedList
@ -15,17 +16,19 @@ typealias PlaceBreakRule = (GamePlaceBreakRule.GamePlaceBreakEvent) -> GamePlace
class GamePlaceBreakRule(val game: Game) { class GamePlaceBreakRule(val game: Game) {
enum class ActionType { enum class ActionType {
PLACE, PLACE, BREAK
BREAK
} }
enum class MatchResult { enum class MatchResult {
DEFAULT, DEFAULT, ALLOW, DENY
ALLOW,
DENY
} }
data class GamePlaceBreakEvent(val player: Player, val actionType: ActionType, val loc: Location, val type: XMaterial) data class GamePlaceBreakEvent(
val player: Player,
val actionType: ActionType,
val loc: Location,
val type: XMaterial
)
private val rules = HashMap<String, PlaceBreakRule>() private val rules = HashMap<String, PlaceBreakRule>()
private val rulesPriority = EnhancedLinkedList<String>() private val rulesPriority = EnhancedLinkedList<String>()
@ -52,25 +55,21 @@ class GamePlaceBreakRule(val game: Game) {
} }
fun addRuleLast( fun addRuleLast(
name: String, name: String, rule: PlaceBreakRule
rule: PlaceBreakRule
) { ) {
recordRule(name, rule) recordRule(name, rule)
rulesPriority.addLast(name) rulesPriority.addLast(name)
} }
fun addRuleFirst( fun addRuleFirst(
name: String, name: String, rule: PlaceBreakRule
rule: PlaceBreakRule
) { ) {
recordRule(name, rule) recordRule(name, rule)
rulesPriority.addFirst(name) rulesPriority.addFirst(name)
} }
fun addRuleBefore( fun addRuleBefore(
base: String, base: String, name: String, rule: PlaceBreakRule
name: String,
rule: PlaceBreakRule
) { ) {
recordRule(name, rule) recordRule(name, rule)
rulesPriority.addBefore(base, name) rulesPriority.addBefore(base, name)
@ -78,9 +77,7 @@ class GamePlaceBreakRule(val game: Game) {
fun addRuleAfter( fun addRuleAfter(
base: String, base: String, name: String, rule: PlaceBreakRule
name: String,
rule: PlaceBreakRule
) { ) {
recordRule(name, rule) recordRule(name, rule)
rulesPriority.addAfter(base, name) rulesPriority.addAfter(base, name)
@ -100,12 +97,10 @@ class GamePlaceBreakRule(val game: Game) {
// allow enemy wall // allow enemy wall
addRuleLast("allow_wall_conditional") { (player, actionType, loc, _) -> addRuleLast("allow_wall_conditional") { (player, actionType, loc, _) ->
val team = player.team ?: return@addRuleLast MatchResult.DENY val team = player.team ?: return@addRuleLast MatchResult.DENY
val isWall = game.teams val isWall = game.teams.map {
.map {
it.teamInfo.wall.containsBlock(loc) it.teamInfo.wall.containsBlock(loc)
.also { result -> debug("area ${it.teamInfo.wall} contains $loc is $result") } .also { result -> debug("area ${it.teamInfo.wall} contains $loc is $result") }
} }.reduce { a, b -> a || b }
.reduce { a, b -> a || b }
if (!isWall) return@addRuleLast MatchResult.DEFAULT if (!isWall) return@addRuleLast MatchResult.DEFAULT
val isHome = team.teamInfo.wall.containsBlock(loc) val isHome = team.teamInfo.wall.containsBlock(loc)
if ((actionType == BREAK) xor isHome) MatchResult.ALLOW else MatchResult.DENY if ((actionType == BREAK) xor isHome) MatchResult.ALLOW else MatchResult.DENY
@ -115,16 +110,13 @@ class GamePlaceBreakRule(val game: Game) {
addRuleFirst("allow_tnt_conditional") { (player, actionType, loc, type) -> addRuleFirst("allow_tnt_conditional") { (player, actionType, loc, type) ->
if (type != XMaterial.TNT) return@addRuleFirst MatchResult.DEFAULT if (type != XMaterial.TNT) return@addRuleFirst MatchResult.DEFAULT
val team = player.team ?: return@addRuleFirst MatchResult.DENY val team = player.team ?: return@addRuleFirst MatchResult.DENY
val isHome = game.teams val isHome = game.teams.map {
.map {
it.teamInfo.home.containsBlock(loc) it.teamInfo.home.containsBlock(loc)
.also { result -> debug("area ${it.teamInfo.home} contains $loc is $result") } .also { result -> debug("area ${it.teamInfo.home} contains $loc is $result") }
} }.reduce { a, b -> a || b }
.reduce { a, b -> a || b }
if (!isHome) return@addRuleFirst MatchResult.DENY if (!isHome) return@addRuleFirst MatchResult.DENY
val isSelf = team.teamInfo.home.containsBlock(loc) val isSelf = team.teamInfo.home.containsBlock(loc)
if ((actionType == PLACE) xor isSelf) MatchResult.ALLOW else MatchResult.DENY if ((actionType == PLACE) xor isSelf) MatchResult.ALLOW else MatchResult.DENY
} }
} }
} }

View File

@ -29,9 +29,10 @@ class GameScoreboard(val game: Game) {
appendLine(player.asLangText("scoreboard_team_info", it.teamInfo.name, it.villager.health)) appendLine(player.asLangText("scoreboard_team_info", it.teamInfo.name, it.villager.health))
} }
} }
val eventName = player.asLangText("event_${event.second}")
player.asLangText( player.asLangText(
"scoreboard_start", "scoreboard_start",
event.second, eventName,
"${event.first.inWholeMinutes}:${event.first.inWholeSeconds}", "${event.first.inWholeMinutes}:${event.first.inWholeSeconds}",
teamMessage, teamMessage,
player.team?.villager?.health ?: throw IllegalStateException("player ${player.name} has no team."), player.team?.villager?.health ?: throw IllegalStateException("player ${player.name} has no team."),
@ -43,7 +44,5 @@ class GameScoreboard(val game: Game) {
} }
player.sendScoreboard(*scoreboardText.lines().toTypedArray()) player.sendScoreboard(*scoreboardText.lines().toTypedArray())
} }
} }

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.debug
import cc.maxmc.blastingcrisis.misc.toEntityLocation import cc.maxmc.blastingcrisis.misc.toEntityLocation
import cc.maxmc.blastingcrisis.packet.BEntityVillager import cc.maxmc.blastingcrisis.packet.BEntityVillager
import org.bukkit.Bukkit import org.bukkit.Bukkit
@ -42,6 +43,7 @@ class TeamVillager(private val team: GameTeam) {
} }
fun respawn(player: Player) { fun respawn(player: Player) {
debug("respawning for ${player.name}")
packetVillager.respawnForPlayer(player) packetVillager.respawnForPlayer(player)
} }

View File

@ -17,10 +17,12 @@ import org.bukkit.event.entity.ExplosionPrimeEvent
import org.bukkit.event.entity.FoodLevelChangeEvent import org.bukkit.event.entity.FoodLevelChangeEvent
import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.event.player.PlayerMoveEvent import org.bukkit.event.player.PlayerMoveEvent
import org.bukkit.event.player.PlayerQuitEvent
import org.bukkit.event.player.PlayerRespawnEvent import org.bukkit.event.player.PlayerRespawnEvent
import taboolib.common.platform.event.EventPriority import taboolib.common.platform.event.EventPriority
import taboolib.common.platform.event.SubscribeEvent import taboolib.common.platform.event.SubscribeEvent
import taboolib.library.xseries.XMaterial import taboolib.library.xseries.XMaterial
import taboolib.platform.util.buildItem
import taboolib.platform.util.sendLang import taboolib.platform.util.sendLang
object GameListener { object GameListener {
@ -57,7 +59,7 @@ object GameListener {
} }
} }
@SubscribeEvent @SubscribeEvent(priority = EventPriority.LOW)
fun onBreak(breakEvent: BlockBreakEvent) { fun onBreak(breakEvent: BlockBreakEvent) {
val loc = breakEvent.block.location ?: return val loc = breakEvent.block.location ?: return
val player = breakEvent.player ?: return val player = breakEvent.player ?: return
@ -72,7 +74,7 @@ object GameListener {
player.sendLang("game_cant_break_block") player.sendLang("game_cant_break_block")
} }
@SubscribeEvent @SubscribeEvent(priority = EventPriority.LOW)
fun onPlace(placeEvent: BlockPlaceEvent) { fun onPlace(placeEvent: BlockPlaceEvent) {
val loc = placeEvent.block.location ?: return val loc = placeEvent.block.location ?: return
val player = placeEvent.player ?: return val player = placeEvent.player ?: return
@ -90,8 +92,8 @@ object GameListener {
@SubscribeEvent @SubscribeEvent
fun onRespawn(respawnEvent: PlayerRespawnEvent) { fun onRespawn(respawnEvent: PlayerRespawnEvent) {
val team = respawnEvent.player.team ?: return // ignore none game player val team = respawnEvent.player.team ?: return // ignore none game player
GameManager.currentGame.respawnPlayer(respawnEvent.player)
respawnEvent.respawnLocation = team.teamInfo.spawn.toEntityLocation() respawnEvent.respawnLocation = team.teamInfo.spawn.toEntityLocation()
GameManager.currentGame.respawnPlayer(respawnEvent.player)
} }
// @SubscribeEvent // @SubscribeEvent
@ -117,4 +119,25 @@ object GameListener {
tntPlace.block.type = Material.AIR tntPlace.block.type = Material.AIR
loc.world.spawnEntity(loc.clone().apply { y += 0.5 }, EntityType.PRIMED_TNT) loc.world.spawnEntity(loc.clone().apply { y += 0.5 }, EntityType.PRIMED_TNT)
} }
@SubscribeEvent
fun onLeft(leftEvent: PlayerQuitEvent) {
if (!GameManager.currentGame.players.contains(leftEvent.player)) return
GameManager.currentGame.leave(leftEvent.player)
}
private val ores = mapOf(Material.IRON_ORE to Material.IRON_INGOT, Material.GOLD_ORE to Material.GOLD_INGOT)
@SubscribeEvent(ignoreCancelled = true)
fun autoSmelt(breakEvent: BlockBreakEvent) {
if (!GameManager.currentGame.players.contains(breakEvent.player)) return
val type = breakEvent.block.type
val loc = breakEvent.block.location
if (!ores.containsKey(type)) return
debug("Auto Smelting: ${breakEvent.block.type}")
breakEvent.block.type = Material.AIR
breakEvent.isCancelled = true
loc.world.dropItemNaturally(loc.toEntityLocation().apply { y += 0.5 }, buildItem(ores[type]!!))
}
} }

View File

@ -32,9 +32,9 @@ class Area(loc1: Location, loc2: Location) : ConfigurationSerializable {
*/ */
fun contains(location: Location): Boolean { fun contains(location: Location): Boolean {
if (location.world != locTop.world) return false if (location.world != locTop.world) return false
if (location.x !in (locMin.x - 1)..(locTop.x + 1)) return false if (location.x !in (locMin.x)..(locTop.x + 1)) return false
if (location.y !in locMin.y..locTop.y + 1) return false if (location.y !in locMin.y..locTop.y + 1) return false
return location.z in (locMin.z - 1)..(locTop.z + 1) return location.z in (locMin.z)..(locTop.z + 1)
} }
fun containsBlock(location: Location): Boolean { fun containsBlock(location: Location): Boolean {

View File

@ -1,11 +1,13 @@
package cc.maxmc.blastingcrisis.packet package cc.maxmc.blastingcrisis.packet
import cc.maxmc.blastingcrisis.listener.BEntityInteract import cc.maxmc.blastingcrisis.listener.BEntityInteract
import cc.maxmc.blastingcrisis.misc.debug
import gnu.trove.TDecorators import gnu.trove.TDecorators
import gnu.trove.map.hash.TIntObjectHashMap import gnu.trove.map.hash.TIntObjectHashMap
import net.minecraft.server.v1_8_R3.* import net.minecraft.server.v1_8_R3.*
import org.bukkit.Location import org.bukkit.Location
import org.bukkit.entity.Player import org.bukkit.entity.Player
import taboolib.common.platform.function.submit
import taboolib.common.util.random import taboolib.common.util.random
import taboolib.library.reflex.Reflex.Companion.getProperty import taboolib.library.reflex.Reflex.Companion.getProperty
import taboolib.library.reflex.Reflex.Companion.setProperty import taboolib.library.reflex.Reflex.Companion.setProperty
@ -73,9 +75,9 @@ abstract class BEntity(var loc: Location, val entityType: Int) {
} }
fun respawnForPlayer(player: Player) { fun respawnForPlayer(player: Player) {
println(viewers) debug(viewers.toString())
if (!viewers.contains(player)) return if (!viewers.contains(player)) return
println("Respawning?") debug("Respawning?")
removeViewer(player) removeViewer(player)
addViewer(player) addViewer(player)
} }

Binary file not shown.