From c53a74bfb20d3fb9157b14e8cb1c7b9237a0fff1 Mon Sep 17 00:00:00 2001 From: Fortern Date: Sat, 1 Feb 2025 14:38:49 +0800 Subject: [PATCH] init 3 --- .gitignore | 2 +- build.gradle.kts | 2 +- .../kotlin/xyz/fortern/minehunt/Console.kt | 68 +++++++++++++------ .../kotlin/xyz/fortern/minehunt/Minehunt.kt | 2 + .../fortern/minehunt/command/GodCommand.kt | 2 +- .../fortern/minehunt/command/TestCommand.kt | 27 ++++++++ .../minehunt/listener/PlayerListener.kt | 52 +++++++------- src/main/resources/plugin.yml | 2 + 8 files changed, 106 insertions(+), 51 deletions(-) create mode 100644 src/main/kotlin/xyz/fortern/minehunt/command/TestCommand.kt diff --git a/.gitignore b/.gitignore index 8e5b89f..c4899a7 100644 --- a/.gitignore +++ b/.gitignore @@ -110,7 +110,7 @@ buildNumber.properties .flattened-pom.xml # Common working directory -run/ +run*/ # Gradle .gradle/ diff --git a/build.gradle.kts b/build.gradle.kts index 0fcfff8..0fcf278 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -19,7 +19,7 @@ repositories { dependencies { // Paper API compileOnly("io.papermc.paper:paper-api:1.21.3-R0.1-SNAPSHOT") - // Adventure API + // https://mvnrepository.com/artifact/net.kyori/adventure-api compileOnly("net.kyori:adventure-api:4.18.0") // Kotlin Stdlib https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-stdlib implementation(kotlin("stdlib")) diff --git a/src/main/kotlin/xyz/fortern/minehunt/Console.kt b/src/main/kotlin/xyz/fortern/minehunt/Console.kt index 9eb726a..1bc3bc5 100644 --- a/src/main/kotlin/xyz/fortern/minehunt/Console.kt +++ b/src/main/kotlin/xyz/fortern/minehunt/Console.kt @@ -28,36 +28,51 @@ class Console { /** * 猎人队伍 */ - private val hunterTeam: Team + val hunterTeam: Team /** * 观察者队伍 */ - private val spectatorTeam: Team + val spectatorTeam: Team + + // 玩家退出游戏后会自动离开Team,所以我们维护自己的玩家集合 /** - * 用于遍历的速通者列表 + * 速通者列表 */ - val speedrunnerList: MutableList = ArrayList() + val speedrunnerSet: MutableSet = HashSet() /** - * 插件维护的猎人玩家集合 + * 猎人玩家集合 */ val hunterSet: MutableSet = HashSet() /** - * 插件维护的旁观者玩家集合 + * 旁观者玩家集合 */ val spectatorSet: MutableSet = HashSet() + /** + * 存活中的速通者列表,用于指南针指向的遍历 + */ + val speedrunnerList: MutableList = ArrayList() + /** * 猎人持有的指南针指向的速通者在speedrunnerList中的index */ val trackRunnerMap: Map = HashMap() - var countdownTask: BukkitTask? = null + /** + * 游戏开始前的倒计时任务 + */ + var beginningCountdown: BukkitTask? = null private set + /** + * 猎人出生倒计时 + */ + var hunterSpawnCD: BukkitTask? = null + companion object { @JvmStatic private lateinit var instance: Console @@ -68,7 +83,7 @@ class Console { init { instance = this - // 设置游戏规则 + // 初始化游戏规则 val world = Bukkit.getWorld("world")!! world.worldBorder.size = 32.0 world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false) @@ -79,7 +94,7 @@ class Console { world.setGameRule(GameRule.SPECTATORS_GENERATE_CHUNKS, false) world.difficulty = Difficulty.HARD - // 配置队伍 + // 初始化队伍 val scoreboard = Bukkit.getScoreboardManager().mainScoreboard speedrunnerTeam = scoreboard.getTeam("speedrunner") ?: scoreboard.registerNewTeam("speedrunner") @@ -91,16 +106,23 @@ class Console { spectatorTeam.entries.forEach { spectatorTeam.removeEntries(it) } } - fun tryStart(): Boolean { - if (speedrunnerTeam.size == 0) return false - if (Bukkit.getOnlinePlayers().count { it.isDead } > 0) return false + /** + * 尝试开始游戏。如果满足条件,则返回空字符串,否则返回原因描述 + */ + fun tryStart(): String { + if (speedrunnerTeam.size == 0) return "速通者需要至少一位玩家" + + // 以后可能有其他需要判断的情况 + countdownToStart() - return true + return "" } + /** + * 游戏开始前的倒计时 + */ fun countdownToStart() { - // 进行开始前的倒计时 - countdownTask = Bukkit.getScheduler().runTaskTimerAsynchronously(Minehunt.instance(), object : Runnable { + beginningCountdown = Bukkit.getScheduler().runTaskTimerAsynchronously(Minehunt.instance(), object : Runnable { private var countdown = 6 override fun run() { if (--countdown > 0) { @@ -114,7 +136,8 @@ class Console { } } else { // 倒计时结束后开始游戏 - countdownTask = null + beginningCountdown!!.cancel() + beginningCountdown = null start() } } @@ -123,6 +146,8 @@ class Console { /** * 开始游戏 + * + * 游戏阶段由 PREPARING 变为 PROCESSING */ fun start() { // 修改游戏规则 @@ -150,18 +175,21 @@ class Console { // 通过Team遍历玩家很麻烦 // 速通者更改为生存模式 - speedrunnerList.forEach { it.gameMode = GameMode.SURVIVAL } + speedrunnerSet.forEach { it.gameMode = GameMode.SURVIVAL } // 将猎人传送到世界底部 hunterSet.forEach { it.teleport(Location(world, 0.0, -64.0, 0.0)) } - val scheduler = Bukkit.getScheduler() - val task = scheduler.runTaskTimerAsynchronously(Minehunt.instance(), Runnable { + // 猎人出生倒计时Task + hunterSpawnCD = Bukkit.getScheduler().runTaskTimerAsynchronously(Minehunt.instance(), Runnable { hunterSet.forEach { it.sendMessage(Component.text("你已到达出生点", NamedTextColor.RED)) it.gameMode = GameMode.SURVIVAL it.teleport(spawnLocation) + // TODO 给予猎人指南针 + } - }, 0, RuleItem.HUNTER_READY_CD.value * 20L) + speedrunnerSet.forEach { it.sendMessage(Component.text("猎人开始追杀", NamedTextColor.RED)) } + }, RuleItem.HUNTER_READY_CD.value * 20L, 0) } diff --git a/src/main/kotlin/xyz/fortern/minehunt/Minehunt.kt b/src/main/kotlin/xyz/fortern/minehunt/Minehunt.kt index 859283e..bff8895 100644 --- a/src/main/kotlin/xyz/fortern/minehunt/Minehunt.kt +++ b/src/main/kotlin/xyz/fortern/minehunt/Minehunt.kt @@ -3,6 +3,7 @@ package xyz.fortern.minehunt import org.bukkit.Bukkit import org.bukkit.plugin.java.JavaPlugin import xyz.fortern.minehunt.command.GodCommand +import xyz.fortern.minehunt.command.TestCommand import xyz.fortern.minehunt.listener.PlayerListener class Minehunt : JavaPlugin() { @@ -24,6 +25,7 @@ class Minehunt : JavaPlugin() { Bukkit.getPluginManager().registerEvents(PlayerListener(console), this) Bukkit.getPluginCommand("god")!!.setExecutor(GodCommand()) + Bukkit.getPluginCommand("test")!!.setExecutor(TestCommand()) } diff --git a/src/main/kotlin/xyz/fortern/minehunt/command/GodCommand.kt b/src/main/kotlin/xyz/fortern/minehunt/command/GodCommand.kt index 93a87a7..3592ca8 100644 --- a/src/main/kotlin/xyz/fortern/minehunt/command/GodCommand.kt +++ b/src/main/kotlin/xyz/fortern/minehunt/command/GodCommand.kt @@ -5,7 +5,7 @@ import org.bukkit.command.CommandExecutor import org.bukkit.command.CommandSender import org.bukkit.entity.Player -class GodCommand: CommandExecutor { +class GodCommand : CommandExecutor { override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array?): Boolean { if (sender is Player) sender.isInvulnerable = !sender.isInvulnerable diff --git a/src/main/kotlin/xyz/fortern/minehunt/command/TestCommand.kt b/src/main/kotlin/xyz/fortern/minehunt/command/TestCommand.kt new file mode 100644 index 0000000..02aedd4 --- /dev/null +++ b/src/main/kotlin/xyz/fortern/minehunt/command/TestCommand.kt @@ -0,0 +1,27 @@ +package xyz.fortern.minehunt.command + +import org.bukkit.Bukkit +import org.bukkit.command.Command +import org.bukkit.command.CommandExecutor +import org.bukkit.command.CommandSender + +/** + * 开发过程中的测试命令 + */ +class TestCommand : CommandExecutor { + override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array): Boolean { + when (args[0]) { + "sendTo" -> { + // 给某个玩家发消息 + val name = args[1] + val player = Bukkit.getPlayer(name) + if (player != null) { + player.sendMessage("离线发送消息") + } else { + sender.sendMessage("玩家 $name 不存在") + } + } + } + return true + } +} \ No newline at end of file diff --git a/src/main/kotlin/xyz/fortern/minehunt/listener/PlayerListener.kt b/src/main/kotlin/xyz/fortern/minehunt/listener/PlayerListener.kt index 4a170b9..c16fff3 100644 --- a/src/main/kotlin/xyz/fortern/minehunt/listener/PlayerListener.kt +++ b/src/main/kotlin/xyz/fortern/minehunt/listener/PlayerListener.kt @@ -1,58 +1,54 @@ package xyz.fortern.minehunt.listener -import org.bukkit.Bukkit import org.bukkit.GameMode import org.bukkit.event.EventHandler import org.bukkit.event.Listener -import org.bukkit.event.entity.PlayerDeathEvent -import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.event.player.PlayerJoinEvent import org.bukkit.event.player.PlayerQuitEvent import xyz.fortern.minehunt.Console +import xyz.fortern.minehunt.Console.GameStage class PlayerListener( private val console: Console ) : Listener { + /** + * 玩家加入服务器时 + */ @EventHandler fun onPlayerJoin(event: PlayerJoinEvent) { val player = event.player val stage = console.stage - if (stage == Console.GameStage.PREPARING) { + if (stage == GameStage.PREPARING && console.beginningCountdown == null) { + // 在准备阶段,玩家设为冒险模式 player.gameMode = GameMode.ADVENTURE - console.spectatorSet.add(player) - // 在开始倒计时阶段,所有玩家都是无敌状态 - if (console.countdownTask != null) { - player.isInvulnerable = true + // 重置队伍信息 + player.scoreboard.teams.forEach { it.removeEntry(player.name) } + // 自动加入观察者队伍 + console.spectatorTeam.addEntry(player.name) + } else { + // 在倒计时或进行阶段,玩家自动加入各自的Team + if (console.speedrunnerSet.contains(player)) { + console.speedrunnerTeam.addEntry(player.name) + } else if (console.hunterSet.contains(player)) { + console.hunterTeam.addEntry(player.name) + } else { + console.spectatorSet.add(player) } - } else if (stage == Console.GameStage.PROCESSING && console.speedrunnerTeam.hasEntry(player.name)) { - console.speedrunnerList.add(player) } } + /** + * 玩家退出服务器时的操作 + */ @EventHandler fun onPlayerQuit(event: PlayerQuitEvent) { val player = event.player - val stage = console.stage - if (stage == Console.GameStage.PREPARING) { - player.scoreboard.teams.forEach { it.removeEntry(player.name) } - } else if (stage == Console.GameStage.PROCESSING && console.speedrunnerTeam.hasEntry(player.name)) { + if (console.stage == GameStage.PROCESSING && console.speedrunnerSet.contains(player)) console.speedrunnerList.remove(player) - } - player.spigot().respawn() + } - @EventHandler - fun onIn(event: PlayerInteractEvent) { - val team = Bukkit.getScoreboardManager().mainScoreboard.getTeam("A")!! - val size = team.entries.size - - } - @EventHandler - fun onPlayerDeath(event: PlayerDeathEvent) { - val player = event.player - player.spigot().respawn() - } -} \ No newline at end of file +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 2ba23cb..7700c24 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -7,3 +7,5 @@ authors: [ Fortern ] commands: god: description: "使自己无敌" + test: + description: "测试"