使用 Brigadier Command API 重写命令
This commit is contained in:
@@ -398,6 +398,9 @@ class Console {
|
||||
|
||||
scoreboard.getObjective("rule-list")!!.displaySlot = null
|
||||
stage = GameStage.PROCESSING
|
||||
Bukkit.getOnlinePlayers().forEach {
|
||||
it.updateCommands()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -476,6 +479,7 @@ class Console {
|
||||
it.sendMessage(Component.text("没有赢家", NamedTextColor.GOLD))
|
||||
}
|
||||
it.gameMode = GameMode.SURVIVAL
|
||||
it.updateCommands()
|
||||
}
|
||||
// 取消剩余的复活任务
|
||||
hunterRespawnTasks.forEach {
|
||||
@@ -578,6 +582,7 @@ class Console {
|
||||
hunterRespawnTasks.remove(uuid)
|
||||
}, gameRules.getRuleValue(RuleKey.HUNTER_RESPAWN_CD) * 20L)
|
||||
}
|
||||
player.updateCommands()
|
||||
}
|
||||
|
||||
private fun initScoreboard() {
|
||||
@@ -657,6 +662,11 @@ class Console {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否处于倒计时前的开始阶段
|
||||
*/
|
||||
fun preparingAndNoCountdown(): Boolean = stage == GameStage.PREPARING && beginningCountdown == null
|
||||
|
||||
/**
|
||||
* 游戏阶段
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package xyz.fortern.minehunt
|
||||
|
||||
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.plugin.java.JavaPlugin
|
||||
import xyz.fortern.minehunt.command.MhCommand
|
||||
import xyz.fortern.minehunt.command.MinehuntCommand
|
||||
import xyz.fortern.minehunt.command.TestCommand
|
||||
import xyz.fortern.minehunt.listener.PlayerListener
|
||||
@@ -30,6 +32,10 @@ class Minehunt : JavaPlugin() {
|
||||
Bukkit.getPluginCommand("test")!!.setExecutor(TestCommand())
|
||||
Bukkit.getPluginCommand("minehunt")!!.setExecutor(MinehuntCommand(console))
|
||||
|
||||
this.getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS) {
|
||||
it.registrar().register(MhCommand(console).createCommand().build())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onDisable() {
|
||||
|
||||
212
src/main/kotlin/xyz/fortern/minehunt/command/MhCommand.kt
Normal file
212
src/main/kotlin/xyz/fortern/minehunt/command/MhCommand.kt
Normal file
@@ -0,0 +1,212 @@
|
||||
package xyz.fortern.minehunt.command
|
||||
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack
|
||||
import io.papermc.paper.command.brigadier.Commands
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.command.CommandSender
|
||||
import org.bukkit.entity.Player
|
||||
import xyz.fortern.minehunt.Console
|
||||
import xyz.fortern.minehunt.Console.GameStage
|
||||
import xyz.fortern.minehunt.Minehunt
|
||||
import xyz.fortern.minehunt.rule.RuleKey
|
||||
|
||||
class MhCommand(
|
||||
private val console: Console
|
||||
) {
|
||||
|
||||
private val helpMessages = listOf(
|
||||
Component.text("Minehunt v${Minehunt.instance().pluginMeta.version}", NamedTextColor.GREEN),
|
||||
Component.text("/minehunt help ", NamedTextColor.GOLD)
|
||||
.append(Component.text("帮助信息", NamedTextColor.WHITE)),
|
||||
Component.text("/minehunt join (hunter|speedrunner|audience) ", NamedTextColor.GOLD)
|
||||
.append(Component.text("加入一个阵营", NamedTextColor.WHITE)),
|
||||
Component.text("/minehunt leave ", NamedTextColor.GOLD)
|
||||
.append(Component.text("加入观察者阵营", NamedTextColor.WHITE)),
|
||||
Component.text("/minehunt rule <ruleKey> ", NamedTextColor.GOLD)
|
||||
.append(Component.text("查看或修改游戏规则", NamedTextColor.WHITE)),
|
||||
Component.text("/minehunt start ", NamedTextColor.GOLD)
|
||||
.append(Component.text("开始游戏", NamedTextColor.WHITE)),
|
||||
Component.text("/minehunt stop ", NamedTextColor.GOLD)
|
||||
.append(Component.text("进行中止游戏的投票", NamedTextColor.WHITE)),
|
||||
Component.text("/minehunt give ", NamedTextColor.GOLD)
|
||||
.append(Component.text("给予游戏中所需的特殊物品", NamedTextColor.WHITE)),
|
||||
)
|
||||
private val ruleHelpMessages = listOf(
|
||||
Component.text("/minehunt rule <ruleItem> ", NamedTextColor.GREEN)
|
||||
.append(Component.text("查看一项规则的详情", NamedTextColor.WHITE)),
|
||||
Component.text("/minehunt rule <ruleItem> <value> ", NamedTextColor.GREEN)
|
||||
.append(Component.text("为一项规则设置新的值", NamedTextColor.WHITE)),
|
||||
)
|
||||
|
||||
fun createCommand(): LiteralArgumentBuilder<CommandSourceStack> =
|
||||
Commands.literal("hunt")
|
||||
.then(help())
|
||||
.then(join())
|
||||
.then(leave())
|
||||
.then(rule())
|
||||
.then(start())
|
||||
.then(stop())
|
||||
.then(give())
|
||||
|
||||
private fun help(): LiteralArgumentBuilder<CommandSourceStack> {
|
||||
return Commands.literal("help").executes { sendHelp(it.source.sender) }
|
||||
}
|
||||
|
||||
private fun join(): LiteralArgumentBuilder<CommandSourceStack> {
|
||||
return Commands.literal("join")
|
||||
.requires {
|
||||
it.sender is Player && console.preparingAndNoCountdown()
|
||||
}.then(
|
||||
Commands.literal("hunter").executes {
|
||||
console.joinHunter(it.source.sender as Player)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
).then(
|
||||
Commands.literal("speedrunner").executes {
|
||||
console.joinSpeedrunner(it.source.sender as Player)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
).then(
|
||||
Commands.literal("audience").executes {
|
||||
console.joinAudience(it.source.sender as Player)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun leave(): LiteralArgumentBuilder<CommandSourceStack> {
|
||||
return Commands.literal("leave")
|
||||
.requires { it.sender is Player && console.preparingAndNoCountdown() }
|
||||
.executes {
|
||||
console.joinAudience(it.source.sender as Player)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
private fun rule(): LiteralArgumentBuilder<CommandSourceStack> {
|
||||
val ruleNode = Commands.literal("rule").requires {
|
||||
console.preparingAndNoCountdown()
|
||||
}
|
||||
console.gameRules.getAllRules().forEach { (k, v) ->
|
||||
ruleNode.then(
|
||||
// 定义ruleKey节点 在 minehunt -> rule -> ruleKey
|
||||
Commands.literal(k.name)
|
||||
.then(
|
||||
// 定义value节点 在 minehunt -> rule -> ruleKey -> value
|
||||
Commands.argument("value", k.type)
|
||||
// 执行修改规则的命令
|
||||
.executes {
|
||||
modifyGameRule(k, it.getArgument("value", k.clazz)!!, it.source.sender)
|
||||
}
|
||||
)
|
||||
// 执行查询规则的命令
|
||||
.executes { sendRuleInfo(it.source.sender, k) }
|
||||
)
|
||||
}
|
||||
ruleNode.executes {
|
||||
sendHelpRule(it.source.sender)
|
||||
}
|
||||
return ruleNode
|
||||
}
|
||||
|
||||
/**
|
||||
* 游戏开始
|
||||
*/
|
||||
private fun start(): LiteralArgumentBuilder<CommandSourceStack> {
|
||||
return Commands.literal("start")
|
||||
.requires { console.preparingAndNoCountdown() }
|
||||
.executes {
|
||||
val result = console.tryStart()
|
||||
if (result.isNotEmpty()) {
|
||||
it.source.sender.sendMessage(Component.text("游戏开始失败,原因:${result}", NamedTextColor.RED))
|
||||
}
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 投票结束游戏
|
||||
*/
|
||||
private fun stop(): LiteralArgumentBuilder<CommandSourceStack> {
|
||||
return Commands.literal("stop")
|
||||
.requires {
|
||||
if (console.stage != GameStage.PROCESSING) return@requires false
|
||||
val sender = it.sender
|
||||
if (sender !is Player) return@requires false
|
||||
console.isHunter(sender) || console.isSpeedrunner(sender)
|
||||
}
|
||||
.executes {
|
||||
console.voteForStop(it.source.sender as Player)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 给予玩家特殊物品
|
||||
*/
|
||||
private fun give(): LiteralArgumentBuilder<CommandSourceStack> {
|
||||
return Commands.literal("give")
|
||||
.requires { it.sender is Player && console.stage == GameStage.PROCESSING }
|
||||
.then(
|
||||
Commands.literal("compass")
|
||||
.requires {
|
||||
val sender = it.sender
|
||||
sender is Player && console.isHunter(sender)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改某项游戏规则
|
||||
*/
|
||||
private fun modifyGameRule(ruleKey: RuleKey<*>, value: Any, sender: CommandSender): Int {
|
||||
if (console.gameRules.setGameRuleValue(ruleKey, value)) {
|
||||
sender.sendMessage(
|
||||
Component.text(sender.name, NamedTextColor.YELLOW)
|
||||
.append(Component.text("修改规则项", NamedTextColor.WHITE))
|
||||
.append(Component.text(ruleKey.name, NamedTextColor.GOLD))
|
||||
.append(Component.text("值为", NamedTextColor.WHITE))
|
||||
.append(
|
||||
Component.text(
|
||||
console.gameRules.getRuleValue(ruleKey).toString(),
|
||||
NamedTextColor.GREEN
|
||||
)
|
||||
)
|
||||
)
|
||||
console.refreshEntry(ruleKey)
|
||||
} else {
|
||||
sender.sendMessage(Component.text("不合适的值", NamedTextColor.RED))
|
||||
}
|
||||
return Command.SINGLE_SUCCESS
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送规则详情
|
||||
*/
|
||||
private fun sendRuleInfo(sender: CommandSender, ruleKey: RuleKey<*>): Int {
|
||||
sender.sendMessage(Component.text("游戏规则: ${ruleKey.name}"))
|
||||
sender.sendMessage(Component.text("描述: ${ruleKey.info}"))
|
||||
sender.sendMessage(Component.text("值类型: ${ruleKey.typeInfo}"))
|
||||
sender.sendMessage(Component.text("数值: ${console.gameRules.getRuleValue(ruleKey)}"))
|
||||
return Command.SINGLE_SUCCESS
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送帮助信息
|
||||
*/
|
||||
private fun sendHelp(sender: CommandSender): Int {
|
||||
helpMessages.forEach { sender.sendMessage(it) }
|
||||
return Command.SINGLE_SUCCESS
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送rule子命令的帮助信息
|
||||
*/
|
||||
private fun sendHelpRule(sender: CommandSender): Int {
|
||||
ruleHelpMessages.forEach { sender.sendMessage(it) }
|
||||
return Command.SINGLE_SUCCESS
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,19 @@ class GameRules internal constructor() {
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置一项游戏规则
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T> setGameRuleValue(rule: RuleKey<T>, value: Any): Boolean {
|
||||
return try {
|
||||
setRuleValue(rule, value as T)
|
||||
true
|
||||
} catch (e: ClassCastException) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> setRuleValue(rule: RuleKey<T>, value: T) {
|
||||
map[rule] = value!!
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package xyz.fortern.minehunt.rule
|
||||
|
||||
import com.mojang.brigadier.arguments.ArgumentType
|
||||
import com.mojang.brigadier.arguments.BoolArgumentType
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType
|
||||
|
||||
/**
|
||||
* 描述每一个规则项的类
|
||||
*/
|
||||
@@ -14,10 +18,15 @@ class RuleKey<T> private constructor(
|
||||
*/
|
||||
val info: String,
|
||||
|
||||
/**
|
||||
* 这项规则值的参数类型
|
||||
*/
|
||||
val type: ArgumentType<*>,
|
||||
|
||||
/**
|
||||
* 这项规则值的类型
|
||||
*/
|
||||
val type: Class<T>,
|
||||
val clazz: Class<T>,
|
||||
|
||||
/**
|
||||
* 值类型的描述信息
|
||||
@@ -47,7 +56,14 @@ class RuleKey<T> private constructor(
|
||||
}
|
||||
|
||||
val HUNTER_READY_CD =
|
||||
RuleKey("hunter_ready_cd", "猎人出生倒计时(秒)", Int::class.java, "Integer", listOf("0", "15", "30")) {
|
||||
RuleKey(
|
||||
"hunter_ready_cd",
|
||||
"猎人出生倒计时(秒)",
|
||||
IntegerArgumentType.integer(0, 120),
|
||||
Int::class.java,
|
||||
"Integer",
|
||||
listOf("0", "15", "30")
|
||||
) {
|
||||
try {
|
||||
val i = it.toInt()
|
||||
if (i in 0..120) i else null
|
||||
@@ -56,7 +72,14 @@ class RuleKey<T> private constructor(
|
||||
}
|
||||
}
|
||||
val HUNTER_RESPAWN_CD =
|
||||
RuleKey("hunter_respawn_cd", "猎人重生倒计时(秒)", Int::class.java, "Integer", listOf("0, 15, 30")) {
|
||||
RuleKey(
|
||||
"hunter_respawn_cd",
|
||||
"猎人重生倒计时(秒)",
|
||||
IntegerArgumentType.integer(0, 120),
|
||||
Int::class.java,
|
||||
"Integer",
|
||||
listOf("0, 15, 30")
|
||||
) {
|
||||
try {
|
||||
val i = it.toInt()
|
||||
if (i in 0..120) i else null
|
||||
@@ -67,10 +90,17 @@ class RuleKey<T> private constructor(
|
||||
val FRIENDLY_FIRE = RuleKey(
|
||||
"friendly_fire",
|
||||
"队友之间是否有伤害",
|
||||
BoolArgumentType.bool(),
|
||||
Boolean::class.java,
|
||||
"Boolean",
|
||||
listOf("true", "false"),
|
||||
boolValidate
|
||||
)
|
||||
|
||||
val map: Map<String, RuleKey<*>> = mapOf(
|
||||
"hunter_ready_cd" to HUNTER_READY_CD,
|
||||
"hunter_respawn_cd" to HUNTER_RESPAWN_CD,
|
||||
"friendly_fire" to FRIENDLY_FIRE
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user