使用 Brigadier Command API 重写命令
This commit is contained in:
@@ -398,6 +398,9 @@ class Console {
|
|||||||
|
|
||||||
scoreboard.getObjective("rule-list")!!.displaySlot = null
|
scoreboard.getObjective("rule-list")!!.displaySlot = null
|
||||||
stage = GameStage.PROCESSING
|
stage = GameStage.PROCESSING
|
||||||
|
Bukkit.getOnlinePlayers().forEach {
|
||||||
|
it.updateCommands()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -476,6 +479,7 @@ class Console {
|
|||||||
it.sendMessage(Component.text("没有赢家", NamedTextColor.GOLD))
|
it.sendMessage(Component.text("没有赢家", NamedTextColor.GOLD))
|
||||||
}
|
}
|
||||||
it.gameMode = GameMode.SURVIVAL
|
it.gameMode = GameMode.SURVIVAL
|
||||||
|
it.updateCommands()
|
||||||
}
|
}
|
||||||
// 取消剩余的复活任务
|
// 取消剩余的复活任务
|
||||||
hunterRespawnTasks.forEach {
|
hunterRespawnTasks.forEach {
|
||||||
@@ -578,6 +582,7 @@ class Console {
|
|||||||
hunterRespawnTasks.remove(uuid)
|
hunterRespawnTasks.remove(uuid)
|
||||||
}, gameRules.getRuleValue(RuleKey.HUNTER_RESPAWN_CD) * 20L)
|
}, gameRules.getRuleValue(RuleKey.HUNTER_RESPAWN_CD) * 20L)
|
||||||
}
|
}
|
||||||
|
player.updateCommands()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initScoreboard() {
|
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
|
package xyz.fortern.minehunt
|
||||||
|
|
||||||
|
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents
|
||||||
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.MhCommand
|
||||||
import xyz.fortern.minehunt.command.MinehuntCommand
|
import xyz.fortern.minehunt.command.MinehuntCommand
|
||||||
import xyz.fortern.minehunt.command.TestCommand
|
import xyz.fortern.minehunt.command.TestCommand
|
||||||
import xyz.fortern.minehunt.listener.PlayerListener
|
import xyz.fortern.minehunt.listener.PlayerListener
|
||||||
@@ -30,6 +32,10 @@ class Minehunt : JavaPlugin() {
|
|||||||
Bukkit.getPluginCommand("test")!!.setExecutor(TestCommand())
|
Bukkit.getPluginCommand("test")!!.setExecutor(TestCommand())
|
||||||
Bukkit.getPluginCommand("minehunt")!!.setExecutor(MinehuntCommand(console))
|
Bukkit.getPluginCommand("minehunt")!!.setExecutor(MinehuntCommand(console))
|
||||||
|
|
||||||
|
this.getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS) {
|
||||||
|
it.registrar().register(MhCommand(console).createCommand().build())
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDisable() {
|
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
|
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) {
|
private fun <T> setRuleValue(rule: RuleKey<T>, value: T) {
|
||||||
map[rule] = value!!
|
map[rule] = value!!
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
package xyz.fortern.minehunt.rule
|
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 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 =
|
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 {
|
try {
|
||||||
val i = it.toInt()
|
val i = it.toInt()
|
||||||
if (i in 0..120) i else null
|
if (i in 0..120) i else null
|
||||||
@@ -56,7 +72,14 @@ class RuleKey<T> private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val HUNTER_RESPAWN_CD =
|
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 {
|
try {
|
||||||
val i = it.toInt()
|
val i = it.toInt()
|
||||||
if (i in 0..120) i else null
|
if (i in 0..120) i else null
|
||||||
@@ -67,10 +90,17 @@ class RuleKey<T> private constructor(
|
|||||||
val FRIENDLY_FIRE = RuleKey(
|
val FRIENDLY_FIRE = RuleKey(
|
||||||
"friendly_fire",
|
"friendly_fire",
|
||||||
"队友之间是否有伤害",
|
"队友之间是否有伤害",
|
||||||
|
BoolArgumentType.bool(),
|
||||||
Boolean::class.java,
|
Boolean::class.java,
|
||||||
"Boolean",
|
"Boolean",
|
||||||
listOf("true", "false"),
|
listOf("true", "false"),
|
||||||
boolValidate
|
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