diff --git a/.gitignore b/.gitignore index ba3cf2a..99a59e2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .idea build/ +test_server \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 3fe608c..2ab5096 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -40,7 +40,7 @@ taboolib { // classifier = null // options("skip-kotlin-relocate") version { - taboolib = "6.1.1" + taboolib = "6.1.2-beta2" } } diff --git a/src/main/kotlin/cc/maxmc/blastingcrisis/BlastingCrisis.kt b/src/main/kotlin/cc/maxmc/blastingcrisis/BlastingCrisis.kt index db65edd..3fa17d3 100644 --- a/src/main/kotlin/cc/maxmc/blastingcrisis/BlastingCrisis.kt +++ b/src/main/kotlin/cc/maxmc/blastingcrisis/BlastingCrisis.kt @@ -48,16 +48,16 @@ object BlastingCrisis : Plugin() { Location(Bukkit.getWorlds().first(), x.toDouble(), y.toDouble(), z.toDouble()) val teamRed = MapTeam( - "红队", - ChatColor.RED, - location(0, 72, -44), - location(0, 72, -44), - location(-8, 73, -47), - Area(location(14, 72, -48), location(-14, 78, -34)), - Area(location(-13, 78, -33), location(13, 72, -33)), - Area(location(-13, 78, -32), location(13, 72, -1)), - Area(location(7, 72, -45), location(9, 74, -48)), - listOf( + name = "红队", + color = ChatColor.RED, + spawn = location(0, 72, -44), + villager = location(0, 72, -44), + upgrade = location(-8, 73, -47), + home = Area(location(14, 72, -48), location(-14, 78, -34)), + wall = Area(location(-13, 78, -33), location(13, 72, -33)), + mine = Area(location(-13, 78, -32), location(13, 72, -1)), + teleport = Area(location(7, 72, -45), location(9, 74, -48)), + sides = listOf( 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(13, 78, 33), location(-13, 72, 33)), 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( Area(location(-15, 72, 1), location(-19, 78, 48)), Area(location(19, 78, 48), location(15, 72, 1)) ), diff --git a/src/main/kotlin/cc/maxmc/blastingcrisis/command/DebugCommand.kt b/src/main/kotlin/cc/maxmc/blastingcrisis/command/DebugCommand.kt index 7d5fe5c..c93580d 100644 --- a/src/main/kotlin/cc/maxmc/blastingcrisis/command/DebugCommand.kt +++ b/src/main/kotlin/cc/maxmc/blastingcrisis/command/DebugCommand.kt @@ -2,8 +2,11 @@ package cc.maxmc.blastingcrisis.command import cc.maxmc.blastingcrisis.game.Game 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.misc.Area +import cc.maxmc.blastingcrisis.misc.GameManager import cc.maxmc.blastingcrisis.misc.UniArea import cc.maxmc.blastingcrisis.packet.BEntityVillager import kotlinx.coroutines.cancel @@ -15,13 +18,28 @@ import taboolib.common.platform.function.adaptCommandSender import taboolib.common.platform.function.getDataFolder import taboolib.module.configuration.Configuration import taboolib.platform.BukkitPlugin +import taboolib.platform.util.broadcast import taboolib.platform.util.sendActionBar import java.io.File +import java.util.UUID +import cc.maxmc.blastingcrisis.misc.debug as debuglog object DebugCommand { lateinit var game: Game lateinit var villager: BEntityVillager + var autoRespawn = false + val builders = ArrayList() + 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) { + literal("game") { literal("join") { execute { sender, _, _ -> @@ -80,7 +98,15 @@ object DebugCommand { literal("respawn") { execute { sender, _, _ -> - villager.spawnForPlayer(sender) + villager.removeViewer(sender) + villager.addViewer(sender) + } + } + + literal("autoRespawn") { + execute { sender, _, _ -> + autoRespawn = !autoRespawn + sender.sendMessage("Auto Respawn is now $autoRespawn.") } } @@ -129,5 +155,18 @@ object DebugCommand { }, 60 * 20) } } + + literal("build_mode") { + execute { 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) + } + } } } \ No newline at end of file diff --git a/src/main/kotlin/cc/maxmc/blastingcrisis/debug/DListener.kt b/src/main/kotlin/cc/maxmc/blastingcrisis/debug/DListener.kt index e5ab5dd..e0cd103 100644 --- a/src/main/kotlin/cc/maxmc/blastingcrisis/debug/DListener.kt +++ b/src/main/kotlin/cc/maxmc/blastingcrisis/debug/DListener.kt @@ -1,9 +1,13 @@ 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.PacketPlayOutSpawnEntityLiving import org.bukkit.Bukkit +import org.bukkit.event.player.PlayerRespawnEvent import taboolib.common.platform.event.SubscribeEvent +import taboolib.common.platform.function.submit import taboolib.library.reflex.Reflex.Companion.getProperty import taboolib.module.nms.PacketSendEvent 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) + } + } + } } \ No newline at end of file diff --git a/src/main/kotlin/cc/maxmc/blastingcrisis/game/Game.kt b/src/main/kotlin/cc/maxmc/blastingcrisis/game/Game.kt index 24716f2..abb1e35 100644 --- a/src/main/kotlin/cc/maxmc/blastingcrisis/game/Game.kt +++ b/src/main/kotlin/cc/maxmc/blastingcrisis/game/Game.kt @@ -32,6 +32,10 @@ class Game( } fun join(player: Player) { + if (players.map { it.uniqueId }.contains(player.uniqueId)) { + player.sendLang("game_already_join") + return + } players += player broadcast { it.sendLang("game_join", player.name) @@ -54,14 +58,16 @@ class Game( } fun respawnPlayer(player: Player) { - teams.forEach { it.villager.respawn(player) } + submit(delay = 1L) { + teams.forEach { it.villager.respawn(player) } + } } fun start() { debug("game ${map.name} started.") placeBreakRule.loadDefaultRule() -// startOreGen() -// startItemGen() + startOreGen() + startItemGen() state = GameState.START timer.startTimer() timer.submitEvent("wall_fall", Duration.ofMinutes(1)) { @@ -115,12 +121,13 @@ class Game( return } - broadcast { it.sendLang("game_end") } + broadcast { + it.sendLang("game_end") + } //TODO restart game logic } fun broadcast(action: (Player) -> Unit) { players.forEach(action) } - } \ No newline at end of file diff --git a/src/main/kotlin/cc/maxmc/blastingcrisis/game/GamePlaceBreakRule.kt b/src/main/kotlin/cc/maxmc/blastingcrisis/game/GamePlaceBreakRule.kt index 97a4d11..2f89c30 100644 --- a/src/main/kotlin/cc/maxmc/blastingcrisis/game/GamePlaceBreakRule.kt +++ b/src/main/kotlin/cc/maxmc/blastingcrisis/game/GamePlaceBreakRule.kt @@ -1,5 +1,6 @@ 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.PLACE import cc.maxmc.blastingcrisis.misc.EnhancedLinkedList @@ -15,17 +16,19 @@ typealias PlaceBreakRule = (GamePlaceBreakRule.GamePlaceBreakEvent) -> GamePlace class GamePlaceBreakRule(val game: Game) { enum class ActionType { - PLACE, - BREAK + PLACE, BREAK } enum class MatchResult { - DEFAULT, - ALLOW, - DENY + DEFAULT, 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() private val rulesPriority = EnhancedLinkedList() @@ -52,25 +55,21 @@ class GamePlaceBreakRule(val game: Game) { } fun addRuleLast( - name: String, - rule: PlaceBreakRule + name: String, rule: PlaceBreakRule ) { recordRule(name, rule) rulesPriority.addLast(name) } fun addRuleFirst( - name: String, - rule: PlaceBreakRule + name: String, rule: PlaceBreakRule ) { recordRule(name, rule) rulesPriority.addFirst(name) } fun addRuleBefore( - base: String, - name: String, - rule: PlaceBreakRule + base: String, name: String, rule: PlaceBreakRule ) { recordRule(name, rule) rulesPriority.addBefore(base, name) @@ -78,9 +77,7 @@ class GamePlaceBreakRule(val game: Game) { fun addRuleAfter( - base: String, - name: String, - rule: PlaceBreakRule + base: String, name: String, rule: PlaceBreakRule ) { recordRule(name, rule) rulesPriority.addAfter(base, name) @@ -100,12 +97,10 @@ class GamePlaceBreakRule(val game: Game) { // allow enemy wall addRuleLast("allow_wall_conditional") { (player, actionType, loc, _) -> val team = player.team ?: return@addRuleLast MatchResult.DENY - val isWall = game.teams - .map { + val isWall = game.teams.map { it.teamInfo.wall.containsBlock(loc) .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 val isHome = team.teamInfo.wall.containsBlock(loc) 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) -> if (type != XMaterial.TNT) return@addRuleFirst MatchResult.DEFAULT val team = player.team ?: return@addRuleFirst MatchResult.DENY - val isHome = game.teams - .map { + val isHome = game.teams.map { it.teamInfo.home.containsBlock(loc) .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 val isSelf = team.teamInfo.home.containsBlock(loc) if ((actionType == PLACE) xor isSelf) MatchResult.ALLOW else MatchResult.DENY - } } } \ No newline at end of file diff --git a/src/main/kotlin/cc/maxmc/blastingcrisis/game/GameScoreboard.kt b/src/main/kotlin/cc/maxmc/blastingcrisis/game/GameScoreboard.kt index a1da8eb..ceca3b6 100644 --- a/src/main/kotlin/cc/maxmc/blastingcrisis/game/GameScoreboard.kt +++ b/src/main/kotlin/cc/maxmc/blastingcrisis/game/GameScoreboard.kt @@ -29,9 +29,10 @@ class GameScoreboard(val game: Game) { appendLine(player.asLangText("scoreboard_team_info", it.teamInfo.name, it.villager.health)) } } + val eventName = player.asLangText("event_${event.second}") player.asLangText( "scoreboard_start", - event.second, + eventName, "${event.first.inWholeMinutes}:${event.first.inWholeSeconds}", teamMessage, 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()) - } - } \ No newline at end of file diff --git a/src/main/kotlin/cc/maxmc/blastingcrisis/game/TeamVillager.kt b/src/main/kotlin/cc/maxmc/blastingcrisis/game/TeamVillager.kt index 000c55c..8da5fa2 100644 --- a/src/main/kotlin/cc/maxmc/blastingcrisis/game/TeamVillager.kt +++ b/src/main/kotlin/cc/maxmc/blastingcrisis/game/TeamVillager.kt @@ -1,6 +1,7 @@ package cc.maxmc.blastingcrisis.game import cc.maxmc.blastingcrisis.configuration.GlobalSettings +import cc.maxmc.blastingcrisis.misc.debug import cc.maxmc.blastingcrisis.misc.toEntityLocation import cc.maxmc.blastingcrisis.packet.BEntityVillager import org.bukkit.Bukkit @@ -42,6 +43,7 @@ class TeamVillager(private val team: GameTeam) { } fun respawn(player: Player) { + debug("respawning for ${player.name}") packetVillager.respawnForPlayer(player) } diff --git a/src/main/kotlin/cc/maxmc/blastingcrisis/listener/GameListener.kt b/src/main/kotlin/cc/maxmc/blastingcrisis/listener/GameListener.kt index 04ca913..5fbfcde 100644 --- a/src/main/kotlin/cc/maxmc/blastingcrisis/listener/GameListener.kt +++ b/src/main/kotlin/cc/maxmc/blastingcrisis/listener/GameListener.kt @@ -17,10 +17,12 @@ import org.bukkit.event.entity.ExplosionPrimeEvent import org.bukkit.event.entity.FoodLevelChangeEvent import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.event.player.PlayerMoveEvent +import org.bukkit.event.player.PlayerQuitEvent import org.bukkit.event.player.PlayerRespawnEvent import taboolib.common.platform.event.EventPriority import taboolib.common.platform.event.SubscribeEvent import taboolib.library.xseries.XMaterial +import taboolib.platform.util.buildItem import taboolib.platform.util.sendLang object GameListener { @@ -57,7 +59,7 @@ object GameListener { } } - @SubscribeEvent + @SubscribeEvent(priority = EventPriority.LOW) fun onBreak(breakEvent: BlockBreakEvent) { val loc = breakEvent.block.location ?: return val player = breakEvent.player ?: return @@ -72,7 +74,7 @@ object GameListener { player.sendLang("game_cant_break_block") } - @SubscribeEvent + @SubscribeEvent(priority = EventPriority.LOW) fun onPlace(placeEvent: BlockPlaceEvent) { val loc = placeEvent.block.location ?: return val player = placeEvent.player ?: return @@ -90,8 +92,8 @@ object GameListener { @SubscribeEvent fun onRespawn(respawnEvent: PlayerRespawnEvent) { val team = respawnEvent.player.team ?: return // ignore none game player - GameManager.currentGame.respawnPlayer(respawnEvent.player) respawnEvent.respawnLocation = team.teamInfo.spawn.toEntityLocation() + GameManager.currentGame.respawnPlayer(respawnEvent.player) } // @SubscribeEvent @@ -117,4 +119,25 @@ object GameListener { tntPlace.block.type = Material.AIR 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]!!)) + } + } \ No newline at end of file diff --git a/src/main/kotlin/cc/maxmc/blastingcrisis/misc/Area.kt b/src/main/kotlin/cc/maxmc/blastingcrisis/misc/Area.kt index 0fda3dd..dfee3f9 100644 --- a/src/main/kotlin/cc/maxmc/blastingcrisis/misc/Area.kt +++ b/src/main/kotlin/cc/maxmc/blastingcrisis/misc/Area.kt @@ -32,9 +32,9 @@ class Area(loc1: Location, loc2: Location) : ConfigurationSerializable { */ 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.x !in (locMin.x)..(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) + return location.z in (locMin.z)..(locTop.z + 1) } fun containsBlock(location: Location): Boolean { diff --git a/src/main/kotlin/cc/maxmc/blastingcrisis/packet/BEntity.kt b/src/main/kotlin/cc/maxmc/blastingcrisis/packet/BEntity.kt index 40fb4d2..2b9f515 100644 --- a/src/main/kotlin/cc/maxmc/blastingcrisis/packet/BEntity.kt +++ b/src/main/kotlin/cc/maxmc/blastingcrisis/packet/BEntity.kt @@ -1,11 +1,13 @@ package cc.maxmc.blastingcrisis.packet import cc.maxmc.blastingcrisis.listener.BEntityInteract +import cc.maxmc.blastingcrisis.misc.debug import gnu.trove.TDecorators import gnu.trove.map.hash.TIntObjectHashMap import net.minecraft.server.v1_8_R3.* import org.bukkit.Location import org.bukkit.entity.Player +import taboolib.common.platform.function.submit import taboolib.common.util.random import taboolib.library.reflex.Reflex.Companion.getProperty import taboolib.library.reflex.Reflex.Companion.setProperty @@ -73,9 +75,9 @@ abstract class BEntity(var loc: Location, val entityType: Int) { } fun respawnForPlayer(player: Player) { - println(viewers) + debug(viewers.toString()) if (!viewers.contains(player)) return - println("Respawning?") + debug("Respawning?") removeViewer(player) addViewer(player) } diff --git a/test_server/plugins/BlastingCrisis-1.0-SNAPSHOT.jar b/test_server/plugins/BlastingCrisis-1.0-SNAPSHOT.jar new file mode 100644 index 0000000..0f83700 Binary files /dev/null and b/test_server/plugins/BlastingCrisis-1.0-SNAPSHOT.jar differ