init 19
This commit is contained in:
@@ -2,6 +2,8 @@ package xyz.fortern.minehunt
|
|||||||
|
|
||||||
import net.kyori.adventure.text.Component
|
import net.kyori.adventure.text.Component
|
||||||
import net.kyori.adventure.text.format.NamedTextColor
|
import net.kyori.adventure.text.format.NamedTextColor
|
||||||
|
import net.kyori.adventure.text.format.Style
|
||||||
|
import net.kyori.adventure.text.format.TextDecoration
|
||||||
import net.kyori.adventure.title.Title
|
import net.kyori.adventure.title.Title
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.Difficulty
|
import org.bukkit.Difficulty
|
||||||
@@ -17,6 +19,7 @@ import org.bukkit.scheduler.BukkitRunnable
|
|||||||
import org.bukkit.scheduler.BukkitTask
|
import org.bukkit.scheduler.BukkitTask
|
||||||
import org.bukkit.scoreboard.Criteria
|
import org.bukkit.scoreboard.Criteria
|
||||||
import org.bukkit.scoreboard.DisplaySlot
|
import org.bukkit.scoreboard.DisplaySlot
|
||||||
|
import org.bukkit.scoreboard.RenderType
|
||||||
import org.bukkit.scoreboard.Team
|
import org.bukkit.scoreboard.Team
|
||||||
import xyz.fortern.minehunt.rule.GameRules
|
import xyz.fortern.minehunt.rule.GameRules
|
||||||
import xyz.fortern.minehunt.rule.RuleKey
|
import xyz.fortern.minehunt.rule.RuleKey
|
||||||
@@ -164,8 +167,7 @@ class Console {
|
|||||||
/**
|
/**
|
||||||
* 猎人出生倒计时
|
* 猎人出生倒计时
|
||||||
*/
|
*/
|
||||||
var hunterSpawnCD: BukkitTask? = null
|
private var hunterSpawnCD: BukkitTask? = null
|
||||||
private set
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指南针刷新任务
|
* 指南针刷新任务
|
||||||
@@ -189,7 +191,7 @@ class Console {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
instance = this
|
instance = this
|
||||||
setRuleScoreboard()
|
initScoreboard()
|
||||||
// 初始化 Minecraft 游戏规则
|
// 初始化 Minecraft 游戏规则
|
||||||
overworld.worldBorder.size = 32.0
|
overworld.worldBorder.size = 32.0
|
||||||
overworld.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false)
|
overworld.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false)
|
||||||
@@ -207,54 +209,57 @@ class Console {
|
|||||||
hunterTeam = scoreboard.getTeam("hunter") ?: scoreboard.registerNewTeam("hunter")
|
hunterTeam = scoreboard.getTeam("hunter") ?: scoreboard.registerNewTeam("hunter")
|
||||||
spectatorTeam = scoreboard.getTeam("spectator") ?: scoreboard.registerNewTeam("spectator")
|
spectatorTeam = scoreboard.getTeam("spectator") ?: scoreboard.registerNewTeam("spectator")
|
||||||
|
|
||||||
speedrunnerTeam.entries.forEach { speedrunnerTeam.removeEntries(it) }
|
speedrunnerTeam.let { t ->
|
||||||
hunterTeam.entries.forEach { hunterTeam.removeEntries(it) }
|
t.color(NamedTextColor.BLUE)
|
||||||
spectatorTeam.entries.forEach { spectatorTeam.removeEntries(it) }
|
t.prefix(Component.text("[速通者] ", NamedTextColor.BLUE))
|
||||||
|
t.entries.forEach { speedrunnerTeam.removeEntries(it) }
|
||||||
|
}
|
||||||
|
hunterTeam.let { t ->
|
||||||
|
t.color(NamedTextColor.RED)
|
||||||
|
t.prefix(Component.text("[猎人] ", NamedTextColor.RED))
|
||||||
|
t.entries.forEach { hunterTeam.removeEntries(it) }
|
||||||
|
}
|
||||||
|
spectatorTeam.let { t ->
|
||||||
|
t.color(NamedTextColor.GRAY)
|
||||||
|
t.prefix(Component.text("[观众] ", NamedTextColor.GRAY))
|
||||||
|
t.entries.forEach { spectatorTeam.removeEntries(it) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断玩家是否为猎人
|
* 判断玩家是否为猎人
|
||||||
*/
|
*/
|
||||||
fun isHunter(player: Player) = hunterSet.contains(player.uniqueId)
|
fun isHunter(player: Player): Boolean = hunterSet.contains(player.uniqueId)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断是否为观察者
|
* 判断是否为观察者
|
||||||
*/
|
*/
|
||||||
fun isSpectator(player: Player) = spectatorSet.contains(player.uniqueId)
|
fun isSpectator(player: Player): Boolean = spectatorSet.contains(player.uniqueId)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断是否为速通者
|
* 判断是否为速通者
|
||||||
*/
|
*/
|
||||||
fun isSpeedrunner(player: Player) = speedrunnerSet.contains(player.uniqueId)
|
fun isSpeedrunner(player: Player): Boolean = speedrunnerSet.contains(player.uniqueId)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加入猎人阵营
|
* 加入猎人阵营
|
||||||
*/
|
*/
|
||||||
fun joinHunter(player: Player) {
|
fun joinHunter(player: Player) {
|
||||||
val uuid = player.uniqueId
|
hunterTeam.addEntry(player.name)
|
||||||
speedrunnerSet.remove(uuid)
|
|
||||||
spectatorSet.remove(uuid)
|
|
||||||
hunterSet.add(uuid)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加入速通者阵营
|
* 加入速通者阵营
|
||||||
*/
|
*/
|
||||||
fun joinSpeedrunner(player: Player) {
|
fun joinSpeedrunner(player: Player) {
|
||||||
val uuid = player.uniqueId
|
speedrunnerTeam.addEntry(player.name)
|
||||||
hunterSet.remove(uuid)
|
|
||||||
spectatorSet.remove(uuid)
|
|
||||||
speedrunnerSet.add(uuid)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加入观察者阵营
|
* 加入观察者阵营
|
||||||
*/
|
*/
|
||||||
fun joinSpectator(player: Player) {
|
fun joinSpectator(player: Player) {
|
||||||
val uuid = player.uniqueId
|
spectatorTeam.addEntry(player.name)
|
||||||
hunterSet.remove(uuid)
|
|
||||||
speedrunnerSet.remove(uuid)
|
|
||||||
spectatorSet.add(uuid)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -295,6 +300,11 @@ class Console {
|
|||||||
}, 0, 20)
|
}, 0, 20)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun interruptCountdownToStart() {
|
||||||
|
beginningCountdown?.cancel()
|
||||||
|
beginningCountdown = null
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始游戏
|
* 开始游戏
|
||||||
*
|
*
|
||||||
@@ -326,13 +336,21 @@ class Console {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 速通者更改为生存模式,并加入speedrunnerList
|
// 速通者更改为生存模式,并加入speedrunnerList
|
||||||
speedrunnerSet.forEach { Bukkit.getPlayer(it)?.gameMode = GameMode.SURVIVAL }
|
speedrunnerTeam.entries.forEach { entry ->
|
||||||
speedrunnerList = speedrunnerSet.toList()
|
Bukkit.getPlayer(entry)?.let {
|
||||||
|
speedrunnerSet.add(it.uniqueId)
|
||||||
|
it.gameMode = GameMode.SURVIVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
speedrunnerSet.toList()
|
||||||
|
|
||||||
// 将猎人传送到世界底部,且指南针开始有所指向
|
// 将猎人传送到世界底部,且指南针开始有所指向
|
||||||
hunterSet.forEach {
|
hunterTeam.entries.forEach { entry ->
|
||||||
Bukkit.getPlayer(it)?.teleport(Location(world, 0.0, -64.0, 0.0))
|
Bukkit.getPlayer(entry)?.let {
|
||||||
trackRunnerMap[it] = 0
|
hunterSet.add(it.uniqueId)
|
||||||
|
it.teleport(Location(world, 0.0, -64.0, 0.0))
|
||||||
|
trackRunnerMap[it.uniqueId] = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建指南针更新任务
|
// 创建指南针更新任务
|
||||||
@@ -342,24 +360,9 @@ class Console {
|
|||||||
val hunter = Bukkit.getPlayer(it) ?: return@forEach
|
val hunter = Bukkit.getPlayer(it) ?: return@forEach
|
||||||
val i = (trackRunnerMap[it] ?: return@forEach) % speedrunnerList.size
|
val i = (trackRunnerMap[it] ?: return@forEach) % speedrunnerList.size
|
||||||
// hunter 正在追踪的 speedrunner
|
// hunter 正在追踪的 speedrunner
|
||||||
|
// 这意味着如果速通者掉线,指南针将指向掉线时的位置
|
||||||
val speedrunner = Bukkit.getPlayer(speedrunnerList[i]) ?: return@forEach
|
val speedrunner = Bukkit.getPlayer(speedrunnerList[i]) ?: return@forEach
|
||||||
val items = hunter.inventory.all(hunterCompass)
|
refreshCompassTrack(hunter, speedrunner)
|
||||||
var flag = false
|
|
||||||
items.forEach inner@{ (k, v) ->
|
|
||||||
// 避免玩家身上有多个猎人指南针
|
|
||||||
if (flag) {
|
|
||||||
hunter.inventory.clear(k)
|
|
||||||
return@inner
|
|
||||||
}
|
|
||||||
val lore = v.lore()
|
|
||||||
if (!lore.isNullOrEmpty() && lore[0].equals(compassFlag)) {
|
|
||||||
flag = true
|
|
||||||
// 让指南针指向某一个猎人
|
|
||||||
val meta = v.itemMeta as CompassMeta
|
|
||||||
meta.isLodestoneTracked = false
|
|
||||||
meta.lodestone = speedrunner.location
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -379,7 +382,9 @@ class Console {
|
|||||||
compassRefreshTask = compassTask.runTaskTimer(Minehunt.instance(), 0, 20)
|
compassRefreshTask = compassTask.runTaskTimer(Minehunt.instance(), 0, 20)
|
||||||
|
|
||||||
// 通知速通者
|
// 通知速通者
|
||||||
speedrunnerSet.forEach { Bukkit.getPlayer(it)?.sendMessage(Component.text("猎人开始追杀", NamedTextColor.RED)) }
|
speedrunnerSet.forEach {
|
||||||
|
Bukkit.getPlayer(it)?.sendMessage(Component.text("猎人开始追杀", NamedTextColor.RED))
|
||||||
|
}
|
||||||
}, gameRules.getRuleValue(RuleKey.HUNTER_READY_CD) * 20L)
|
}, gameRules.getRuleValue(RuleKey.HUNTER_READY_CD) * 20L)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -467,20 +472,51 @@ class Console {
|
|||||||
/**
|
/**
|
||||||
* 让该玩家所追踪的目标切换到下一个
|
* 让该玩家所追踪的目标切换到下一个
|
||||||
*/
|
*/
|
||||||
fun trackNextPlayer(player: Player) {
|
fun trackNextPlayer(hunter: Player) {
|
||||||
if (stage != GameStage.PROCESSING) return
|
if (stage != GameStage.PROCESSING) return
|
||||||
val i = trackRunnerMap[player.uniqueId] ?: return
|
val i = trackRunnerMap[hunter.uniqueId] ?: return
|
||||||
if (speedrunnerList.isEmpty()) return
|
if (speedrunnerList.isEmpty()) return
|
||||||
|
|
||||||
var j = i
|
var j = i
|
||||||
while (true) {
|
while (true) {
|
||||||
j++
|
j++
|
||||||
j %= speedrunnerList.size
|
j %= speedrunnerList.size
|
||||||
val speedrunner = speedrunnerList[i]
|
if (i == j) {
|
||||||
if (!outPlayers.contains(speedrunner) && Bukkit.getPlayer(speedrunner) != null || i == j) {
|
// 极端情况,所有速通者都掉线了
|
||||||
trackRunnerMap[player.uniqueId] = j
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
val uuid = speedrunnerList[j]
|
||||||
|
val speedrunner = Bukkit.getPlayer(uuid)
|
||||||
|
if (!outPlayers.contains(uuid) && speedrunner != null) {
|
||||||
|
trackRunnerMap[hunter.uniqueId] = j
|
||||||
|
val location = speedrunner.location
|
||||||
|
// hunter操作指南针时立即刷新位置
|
||||||
|
refreshCompassTrack(hunter, speedrunner)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使hunter的指南针指向此时speedrunner的位置
|
||||||
|
*/
|
||||||
|
private fun refreshCompassTrack(hunter: Player, speedrunner: Player) {
|
||||||
|
val items = hunter.inventory.all(hunterCompass)
|
||||||
|
var flag = false
|
||||||
|
items.forEach inner@{ (k, v) ->
|
||||||
|
// 避免玩家身上有多个猎人指南针
|
||||||
|
if (flag) {
|
||||||
|
hunter.inventory.clear(k)
|
||||||
|
return@inner
|
||||||
|
}
|
||||||
|
val lore = v.lore()
|
||||||
|
if (!lore.isNullOrEmpty() && lore[0].equals(compassFlag)) {
|
||||||
|
flag = true
|
||||||
|
// 让指南针指向某一个猎人
|
||||||
|
val meta = v.itemMeta as CompassMeta
|
||||||
|
meta.isLodestoneTracked = false
|
||||||
|
meta.lodestone = speedrunner.location
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,11 +524,18 @@ class Console {
|
|||||||
* 处理玩家死亡
|
* 处理玩家死亡
|
||||||
*/
|
*/
|
||||||
fun handlePlayerDeath(player: Player) {
|
fun handlePlayerDeath(player: Player) {
|
||||||
|
if (stage != GameStage.PROCESSING) return
|
||||||
|
|
||||||
Bukkit.getPlayer(player.uniqueId)
|
Bukkit.getPlayer(player.uniqueId)
|
||||||
if (isSpeedrunner(player)) {
|
if (isSpeedrunner(player)) {
|
||||||
// 速通者置为旁观者模式,加入淘汰名单
|
// 速通者置为旁观者模式,加入淘汰名单
|
||||||
player.gameMode = GameMode.SPECTATOR
|
player.gameMode = GameMode.SPECTATOR
|
||||||
outPlayers.add(player.uniqueId)
|
outPlayers.add(player.uniqueId)
|
||||||
|
// 给淘汰的玩家名字上加删除线
|
||||||
|
val playerListName = player.playerListName()
|
||||||
|
playerListName.style(Style.style(TextDecoration.STRIKETHROUGH))
|
||||||
|
player.playerListName(playerListName)
|
||||||
|
// 如给所有hunter都淘汰,则游戏结束
|
||||||
if (outPlayers.size == hunterSet.size) {
|
if (outPlayers.size == hunterSet.size) {
|
||||||
end("hunter")
|
end("hunter")
|
||||||
}
|
}
|
||||||
@@ -507,11 +550,16 @@ class Console {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setRuleScoreboard() {
|
private fun initScoreboard() {
|
||||||
//清除旧的计分板信息
|
//清除旧的计分板信息
|
||||||
scoreboard.teams.forEach { it.unregister() }
|
scoreboard.teams.forEach { it.unregister() }
|
||||||
val objective = scoreboard.getObjective("rule-list")
|
scoreboard.getObjective("rule-list")?.unregister()
|
||||||
objective?.unregister()
|
scoreboard.getObjective("players")?.unregister()
|
||||||
|
|
||||||
|
scoreboard.registerNewObjective("players", Criteria.HEALTH, null).let {
|
||||||
|
it.displaySlot = DisplaySlot.PLAYER_LIST
|
||||||
|
it.renderType = RenderType.HEARTS
|
||||||
|
}
|
||||||
|
|
||||||
//设置新的计分板信息
|
//设置新的计分板信息
|
||||||
val ruleListObjective = scoreboard.registerNewObjective(
|
val ruleListObjective = scoreboard.registerNewObjective(
|
||||||
@@ -531,7 +579,6 @@ class Console {
|
|||||||
Component.text(": ").append(Component.text(entry.value.toString(), NamedTextColor.GREEN))
|
Component.text(": ").append(Component.text(entry.value.toString(), NamedTextColor.GREEN))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleListObjective.displaySlot = DisplaySlot.SIDEBAR
|
ruleListObjective.displaySlot = DisplaySlot.SIDEBAR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -132,6 +132,12 @@ class MinehuntCommand(
|
|||||||
* 玩家加入队伍
|
* 玩家加入队伍
|
||||||
*/
|
*/
|
||||||
private fun onJoin(sender: CommandSender, args: List<String>, flag: Boolean): List<String>? {
|
private fun onJoin(sender: CommandSender, args: List<String>, flag: Boolean): List<String>? {
|
||||||
|
if (console.stage != Console.GameStage.PREPARING && console.beginningCountdown != null) {
|
||||||
|
if (flag) {
|
||||||
|
sender.sendMessage(Component.text("只能在准备阶段加入队伍", NamedTextColor.RED))
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
if (args.size == 1) {
|
if (args.size == 1) {
|
||||||
if (flag) {
|
if (flag) {
|
||||||
sender.sendMessage(Component.text("输入正确的队伍名称", NamedTextColor.RED))
|
sender.sendMessage(Component.text("输入正确的队伍名称", NamedTextColor.RED))
|
||||||
|
|||||||
@@ -59,6 +59,12 @@ class TestCommand : CommandExecutor {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 调试
|
||||||
|
"list_name" -> {
|
||||||
|
if (sender is Player && sender.name == "Fortern") {
|
||||||
|
sender.sendMessage(sender.playerListName)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import org.bukkit.event.player.PlayerDropItemEvent
|
|||||||
import org.bukkit.event.player.PlayerJoinEvent
|
import org.bukkit.event.player.PlayerJoinEvent
|
||||||
import org.bukkit.event.player.PlayerMoveEvent
|
import org.bukkit.event.player.PlayerMoveEvent
|
||||||
import org.bukkit.event.player.PlayerPortalEvent
|
import org.bukkit.event.player.PlayerPortalEvent
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent
|
||||||
import org.bukkit.event.player.PlayerTeleportEvent
|
import org.bukkit.event.player.PlayerTeleportEvent
|
||||||
import xyz.fortern.minehunt.Console
|
import xyz.fortern.minehunt.Console
|
||||||
import xyz.fortern.minehunt.Console.GameStage
|
import xyz.fortern.minehunt.Console.GameStage
|
||||||
@@ -32,16 +33,22 @@ class PlayerListener(
|
|||||||
player.scoreboard.teams.forEach { it.removeEntry(player.name) }
|
player.scoreboard.teams.forEach { it.removeEntry(player.name) }
|
||||||
// 自动加入观察者队伍
|
// 自动加入观察者队伍
|
||||||
console.spectatorTeam.addEntry(player.name)
|
console.spectatorTeam.addEntry(player.name)
|
||||||
} else {
|
|
||||||
// 在倒计时或进行阶段,玩家自动加入各自的Team
|
|
||||||
if (console.isSpeedrunner(player)) {
|
|
||||||
console.speedrunnerTeam.addEntry(player.name)
|
|
||||||
} else if (console.isHunter(player)) {
|
|
||||||
console.hunterTeam.addEntry(player.name)
|
|
||||||
} else {
|
|
||||||
console.joinSpectator(player)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参与游戏的玩家在倒计时阶段退出,则中断倒计时
|
||||||
|
*/
|
||||||
|
@EventHandler
|
||||||
|
fun onPlayerJoin(event: PlayerQuitEvent) {
|
||||||
|
val player = event.player
|
||||||
|
val stage = console.stage
|
||||||
|
if (stage == GameStage.PREPARING
|
||||||
|
&& console.beginningCountdown != null
|
||||||
|
&& (console.isHunter(player) || console.isSpeedrunner(player))
|
||||||
|
) {
|
||||||
|
console.interruptCountdownToStart()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,7 +106,9 @@ class PlayerListener(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听传送门传送事件。改变维度时,记录最后的位置。
|
/**
|
||||||
|
* 监听传送门传送事件。改变维度时,记录最后的位置。
|
||||||
|
*/
|
||||||
@EventHandler
|
@EventHandler
|
||||||
fun onPlayerChangeWorld(event: PlayerPortalEvent) {
|
fun onPlayerChangeWorld(event: PlayerPortalEvent) {
|
||||||
if (console.stage != GameStage.PROCESSING) return
|
if (console.stage != GameStage.PROCESSING) return
|
||||||
|
|||||||
Reference in New Issue
Block a user