This commit is contained in:
2025-02-01 14:38:49 +08:00
parent e9ea1b2ecf
commit c53a74bfb2
8 changed files with 106 additions and 51 deletions

2
.gitignore vendored
View File

@@ -110,7 +110,7 @@ buildNumber.properties
.flattened-pom.xml .flattened-pom.xml
# Common working directory # Common working directory
run/ run*/
# Gradle # Gradle
.gradle/ .gradle/

View File

@@ -19,7 +19,7 @@ repositories {
dependencies { dependencies {
// Paper API // Paper API
compileOnly("io.papermc.paper:paper-api:1.21.3-R0.1-SNAPSHOT") 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") compileOnly("net.kyori:adventure-api:4.18.0")
// Kotlin Stdlib https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-stdlib // Kotlin Stdlib https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-stdlib
implementation(kotlin("stdlib")) implementation(kotlin("stdlib"))

View File

@@ -28,36 +28,51 @@ class Console {
/** /**
* 猎人队伍 * 猎人队伍
*/ */
private val hunterTeam: Team val hunterTeam: Team
/** /**
* 观察者队伍 * 观察者队伍
*/ */
private val spectatorTeam: Team val spectatorTeam: Team
// 玩家退出游戏后会自动离开Team所以我们维护自己的玩家集合
/** /**
* 用于遍历的速通者列表 * 速通者列表
*/ */
val speedrunnerList: MutableList<Player> = ArrayList() val speedrunnerSet: MutableSet<Player> = HashSet()
/** /**
* 插件维护的猎人玩家集合 * 猎人玩家集合
*/ */
val hunterSet: MutableSet<Player> = HashSet() val hunterSet: MutableSet<Player> = HashSet()
/** /**
* 插件维护的旁观者玩家集合 * 旁观者玩家集合
*/ */
val spectatorSet: MutableSet<Player> = HashSet() val spectatorSet: MutableSet<Player> = HashSet()
/**
* 存活中的速通者列表,用于指南针指向的遍历
*/
val speedrunnerList: MutableList<Player> = ArrayList()
/** /**
* 猎人持有的指南针指向的速通者在speedrunnerList中的index * 猎人持有的指南针指向的速通者在speedrunnerList中的index
*/ */
val trackRunnerMap: Map<String, Int> = HashMap() val trackRunnerMap: Map<String, Int> = HashMap()
var countdownTask: BukkitTask? = null /**
* 游戏开始前的倒计时任务
*/
var beginningCountdown: BukkitTask? = null
private set private set
/**
* 猎人出生倒计时
*/
var hunterSpawnCD: BukkitTask? = null
companion object { companion object {
@JvmStatic @JvmStatic
private lateinit var instance: Console private lateinit var instance: Console
@@ -68,7 +83,7 @@ class Console {
init { init {
instance = this instance = this
// 设置游戏规则 // 初始化游戏规则
val world = Bukkit.getWorld("world")!! val world = Bukkit.getWorld("world")!!
world.worldBorder.size = 32.0 world.worldBorder.size = 32.0
world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false) world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false)
@@ -79,7 +94,7 @@ class Console {
world.setGameRule(GameRule.SPECTATORS_GENERATE_CHUNKS, false) world.setGameRule(GameRule.SPECTATORS_GENERATE_CHUNKS, false)
world.difficulty = Difficulty.HARD world.difficulty = Difficulty.HARD
// 配置队伍 // 初始化队伍
val scoreboard = Bukkit.getScoreboardManager().mainScoreboard val scoreboard = Bukkit.getScoreboardManager().mainScoreboard
speedrunnerTeam = scoreboard.getTeam("speedrunner") ?: scoreboard.registerNewTeam("speedrunner") speedrunnerTeam = scoreboard.getTeam("speedrunner") ?: scoreboard.registerNewTeam("speedrunner")
@@ -91,16 +106,23 @@ class Console {
spectatorTeam.entries.forEach { spectatorTeam.removeEntries(it) } 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() countdownToStart()
return true return ""
} }
/**
* 游戏开始前的倒计时
*/
fun countdownToStart() { fun countdownToStart() {
// 进行开始前的倒计时 beginningCountdown = Bukkit.getScheduler().runTaskTimerAsynchronously(Minehunt.instance(), object : Runnable {
countdownTask = Bukkit.getScheduler().runTaskTimerAsynchronously(Minehunt.instance(), object : Runnable {
private var countdown = 6 private var countdown = 6
override fun run() { override fun run() {
if (--countdown > 0) { if (--countdown > 0) {
@@ -114,7 +136,8 @@ class Console {
} }
} else { } else {
// 倒计时结束后开始游戏 // 倒计时结束后开始游戏
countdownTask = null beginningCountdown!!.cancel()
beginningCountdown = null
start() start()
} }
} }
@@ -123,6 +146,8 @@ class Console {
/** /**
* 开始游戏 * 开始游戏
*
* 游戏阶段由 PREPARING 变为 PROCESSING
*/ */
fun start() { fun start() {
// 修改游戏规则 // 修改游戏规则
@@ -150,18 +175,21 @@ class Console {
// 通过Team遍历玩家很麻烦 // 通过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)) } hunterSet.forEach { it.teleport(Location(world, 0.0, -64.0, 0.0)) }
val scheduler = Bukkit.getScheduler() // 猎人出生倒计时Task
val task = scheduler.runTaskTimerAsynchronously(Minehunt.instance(), Runnable { hunterSpawnCD = Bukkit.getScheduler().runTaskTimerAsynchronously(Minehunt.instance(), Runnable {
hunterSet.forEach { hunterSet.forEach {
it.sendMessage(Component.text("你已到达出生点", NamedTextColor.RED)) it.sendMessage(Component.text("你已到达出生点", NamedTextColor.RED))
it.gameMode = GameMode.SURVIVAL it.gameMode = GameMode.SURVIVAL
it.teleport(spawnLocation) 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)
} }

View File

@@ -3,6 +3,7 @@ package xyz.fortern.minehunt
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.plugin.java.JavaPlugin import org.bukkit.plugin.java.JavaPlugin
import xyz.fortern.minehunt.command.GodCommand import xyz.fortern.minehunt.command.GodCommand
import xyz.fortern.minehunt.command.TestCommand
import xyz.fortern.minehunt.listener.PlayerListener import xyz.fortern.minehunt.listener.PlayerListener
class Minehunt : JavaPlugin() { class Minehunt : JavaPlugin() {
@@ -24,6 +25,7 @@ class Minehunt : JavaPlugin() {
Bukkit.getPluginManager().registerEvents(PlayerListener(console), this) Bukkit.getPluginManager().registerEvents(PlayerListener(console), this)
Bukkit.getPluginCommand("god")!!.setExecutor(GodCommand()) Bukkit.getPluginCommand("god")!!.setExecutor(GodCommand())
Bukkit.getPluginCommand("test")!!.setExecutor(TestCommand())
} }

View File

@@ -5,7 +5,7 @@ import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender import org.bukkit.command.CommandSender
import org.bukkit.entity.Player import org.bukkit.entity.Player
class GodCommand: CommandExecutor { class GodCommand : CommandExecutor {
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>?): Boolean { override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>?): Boolean {
if (sender is Player) if (sender is Player)
sender.isInvulnerable = !sender.isInvulnerable sender.isInvulnerable = !sender.isInvulnerable

View File

@@ -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<out String>): 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
}
}

View File

@@ -1,58 +1,54 @@
package xyz.fortern.minehunt.listener package xyz.fortern.minehunt.listener
import org.bukkit.Bukkit
import org.bukkit.GameMode import org.bukkit.GameMode
import org.bukkit.event.EventHandler import org.bukkit.event.EventHandler
import org.bukkit.event.Listener 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.PlayerJoinEvent
import org.bukkit.event.player.PlayerQuitEvent import org.bukkit.event.player.PlayerQuitEvent
import xyz.fortern.minehunt.Console import xyz.fortern.minehunt.Console
import xyz.fortern.minehunt.Console.GameStage
class PlayerListener( class PlayerListener(
private val console: Console private val console: Console
) : Listener { ) : Listener {
/**
* 玩家加入服务器时
*/
@EventHandler @EventHandler
fun onPlayerJoin(event: PlayerJoinEvent) { fun onPlayerJoin(event: PlayerJoinEvent) {
val player = event.player val player = event.player
val stage = console.stage val stage = console.stage
if (stage == Console.GameStage.PREPARING) { if (stage == GameStage.PREPARING && console.beginningCountdown == null) {
// 在准备阶段,玩家设为冒险模式
player.gameMode = GameMode.ADVENTURE player.gameMode = GameMode.ADVENTURE
console.spectatorSet.add(player) // 重置队伍信息
// 在开始倒计时阶段,所有玩家都是无敌状态 player.scoreboard.teams.forEach { it.removeEntry(player.name) }
if (console.countdownTask != null) { // 自动加入观察者队伍
player.isInvulnerable = true 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 @EventHandler
fun onPlayerQuit(event: PlayerQuitEvent) { fun onPlayerQuit(event: PlayerQuitEvent) {
val player = event.player val player = event.player
val stage = console.stage if (console.stage == GameStage.PROCESSING && console.speedrunnerSet.contains(player))
if (stage == Console.GameStage.PREPARING) {
player.scoreboard.teams.forEach { it.removeEntry(player.name) }
} else if (stage == Console.GameStage.PROCESSING && console.speedrunnerTeam.hasEntry(player.name)) {
console.speedrunnerList.remove(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()
}
}

View File

@@ -7,3 +7,5 @@ authors: [ Fortern ]
commands: commands:
god: god:
description: "使自己无敌" description: "使自己无敌"
test:
description: "测试"