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
# Common working directory
run/
run*/
# Gradle
.gradle/

View File

@@ -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"))

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 spectatorSet: MutableSet<Player> = HashSet()
/**
* 存活中的速通者列表,用于指南针指向的遍历
*/
val speedrunnerList: MutableList<Player> = ArrayList()
/**
* 猎人持有的指南针指向的速通者在speedrunnerList中的index
*/
val trackRunnerMap: Map<String, Int> = 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)
}

View File

@@ -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())
}

View File

@@ -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<out String>?): Boolean {
if (sender is Player)
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
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
// 重置队伍信息
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)
// 在开始倒计时阶段,所有玩家都是无敌状态
if (console.countdownTask != null) {
player.isInvulnerable = true
}
} 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()
}
}

View File

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