命令管理器添加权限等

This commit is contained in:
UnKownOwO
2022-11-24 19:45:15 +08:00
parent c96deb20e2
commit b125302053
4 changed files with 154 additions and 86 deletions

View File

@@ -1,23 +1,35 @@
package game
import (
"fmt"
"hk4e/gs/model"
"hk4e/logger"
"hk4e/protocol/proto"
"strings"
)
type CommandFunc func(string, []string)
// CommandPerm 命令权限等级
// 0 为普通玩家 数越大权限越大
type CommandPerm uint8
// CommandFunc 命令执行函数
type CommandFunc func(*Command)
// Command 命令结构体
// 给下层执行命令时提供数据
type Command struct {
Name string // 命令前缀
Args []string // 命令参数
Executor *model.Player // 执行者
Text string // 命令原始文本
Name string // 命令前缀
Args []string // 命令参数
}
// CommandManager 命令管理器
type CommandManager struct {
system *model.Player // 机器人 目前负责收发命令 以及 大世界
commandFuncRouter map[string]CommandFunc // 记录命令处理函数
commandTextInput chan string // 传输要处理的命令文本
commandPermMap map[string]CommandPerm // 记录命令对应的权限
commandTextInput chan *Command // 传输要处理的命令文本
gameManager *GameManager
}
@@ -35,11 +47,10 @@ func NewCommandManager(g *GameManager) *CommandManager {
g.worldManager.InitBigWorld(r.system)
// 初始化
r.commandTextInput = make(chan string, 1000)
r.commandTextInput = make(chan *Command, 1000)
r.InitRouter() // 初始化路由
// 处理传入的命令
go r.HandleCommand()
go r.HandleCommand() // 处理传入的命令
r.gameManager = g
return r
@@ -48,24 +59,39 @@ func NewCommandManager(g *GameManager) *CommandManager {
// InitRouter 初始化命令路由
func (c *CommandManager) InitRouter() {
c.commandFuncRouter = make(map[string]CommandFunc)
c.RegisterRouter("awa", c.FuncAwA)
c.commandPermMap = make(map[string]CommandPerm)
{
// 权限等级 0: 普通玩家
c.RegisterRouter("help", 0, c.HelpCommand)
c.RegisterRouter("op", 0, c.OpCommand)
}
// GM命令
{
// 权限等级 1: GM 1级
c.RegisterRouter("nmsl", 1, c.HelpCommand)
}
}
// RegisterRouter 注册命令路由
func (c *CommandManager) RegisterRouter(cmdName string, cmdFunc CommandFunc) {
func (c *CommandManager) RegisterRouter(cmdName string, cmdPerm CommandPerm, cmdFunc CommandFunc) {
// 命令名统一转为小写
cmdName = strings.ToLower(cmdName)
// 记录命令
c.commandFuncRouter[cmdName] = cmdFunc
}
func (c *CommandManager) FuncAwA(cmd string, args []string) {
logger.LOG.Info("awa命令执行啦, name: %v, args: %v", cmd, args)
c.commandPermMap[cmdName] = cmdPerm
}
// InputCommand 输入要处理的命令
func (c *CommandManager) InputCommand(text string) {
func (c *CommandManager) InputCommand(executor *model.Player, text string) {
// 机器人不会读命令所以写到了 PrivateChatReq
// 输入的命令将在其他协程中处理
c.commandTextInput <- text
// 确保消息文本为 / 开头
// 如果不为这个开头那接下来就毫无意义
if strings.HasPrefix(text, "/") {
// 输入的命令将在其他协程中处理
c.commandTextInput <- c.NewCommand(executor, text)
}
}
// GetFriendList 获取包含系统的玩家好友列表
@@ -85,69 +111,69 @@ func (c *CommandManager) GetFriendList(friendList map[uint32]bool) map[uint32]bo
return tempFriendList
}
// NewCommand 创建命令结构
func (c *CommandManager) NewCommand(executor *model.Player, text string) *Command {
// 将开头的 / 去掉 并 分割出命令的每个参数
// 不区分命令的大小写 统一转为小写
cmdSplit := strings.Split(strings.ToLower(text[1:]), " ")
var cmdName string // 命令名
var cmdArgs []string // 命令参数
// 分割出来啥也没有可能是个空的字符串
// 此时将会返回的命令名和命令参数都为空
if len(cmdSplit) != 0 {
// 首个参数必是命令名
cmdName = cmdSplit[0]
// 命令名后当然是命令的参数喽
cmdArgs = cmdSplit[1:]
}
return &Command{executor, text, cmdName, cmdArgs}
}
// HandleCommand 处理命令
func (c *CommandManager) HandleCommand() {
// 处理传入 commandTextInput 的所有命令文本
// 为了避免主协程阻塞搞了个channel
for {
// 取出要处理的命令文本
text := <-c.commandTextInput
// 读取并创建命令
cmd := c.NewCommand(text)
if cmd == nil {
logger.LOG.Error("handle command is nil, text: %v", text)
continue
}
// 取出要执行的命令
cmd := <-c.commandTextInput
// 执行命令
c.ExecCommand(cmd)
}
}
// NewCommand 创建命令结构
func (c *CommandManager) NewCommand(text string) *Command {
// 命令必须以 / 为开头
if !strings.HasPrefix(text, "/") {
return nil
}
// 将开头的 / 去掉
text = text[1:]
// 分割出命令的每个参数
cmdSplit := strings.Split(text, " ")
// 分割出来啥也没有可能是个空的字符串
// 处理个寂寞直接return
if len(cmdSplit) == 0 {
return nil
}
// 首个参数必是命令名
cmdName := cmdSplit[0]
// 命令名后当然是命令的参数喽
cmdArgs := cmdSplit[1:]
return &Command{cmdName, cmdArgs}
}
// ExecCommand 执行命令
func (c *CommandManager) ExecCommand(cmd *Command) {
// 理论上执行前已经校验过不会出现nil 但以免万一
if cmd == nil {
logger.LOG.Error("exec command is nil")
return
}
player := cmd.Executor
// 判断命令是否注册
// 判断命令是否注册
cmdFunc, ok := c.commandFuncRouter[cmd.Name]
if !ok {
logger.LOG.Error("exec command not exist, name: %v", cmd.Name)
// 玩家可能会执行一些没有的命令仅做调试输出
logger.LOG.Debug("exec command not exist, name: %v", cmd.Name)
c.gameManager.SendPrivateChat(c.system, player, "命令不存在,输入 /help 查看帮助。")
return
}
// 判断命令权限是否注册
cmdPerm, ok := c.commandPermMap[cmd.Name]
if !ok {
// 一般命令权限都会注册 没注册则报error错误
logger.LOG.Error("exec command permission not exist, name: %v", cmd.Name)
return
}
logger.LOG.Debug("command start, name: %v args: %v", cmd.Name, cmd.Args)
cmdFunc(cmd.Name, cmd.Args) // 执行命令
logger.LOG.Debug("command done, name: %v args: %v", cmd.Name, cmd.Args)
// 判断玩家的权限是否符合要求
if player.IsGM < uint8(cmdPerm) {
logger.LOG.Debug("exec command permission denied, uid: %v, isGM: %v", player.PlayerID, player.IsGM)
c.gameManager.SendPrivateChat(c.system, player, fmt.Sprintf("权限不足,该命令需要%v级权限。\n你目前的权限等级%v", cmdPerm, player.IsGM))
return
}
logger.LOG.Debug("command start, uid: %v, text: %v, name: %v, args: %v", cmd.Executor.PlayerID, cmd.Text, cmd.Name, cmd.Args)
cmdFunc(cmd) // 执行命令
logger.LOG.Debug("command done, uid: %v, text: %v, name: %v, args: %v", cmd.Executor.PlayerID, cmd.Text, cmd.Name, cmd.Args)
}