mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-09 04:32:27 +08:00
命令管理器添加权限等
This commit is contained in:
17
gs/game/command_controller.go
Normal file
17
gs/game/command_controller.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package game
|
||||
|
||||
import "fmt"
|
||||
|
||||
// HelpCommand 帮助命令
|
||||
func (c *CommandManager) HelpCommand(cmd *Command) {
|
||||
c.gameManager.SendPrivateChat(c.system, cmd.Executor,
|
||||
"===== 帮助 / Help =====\n"+
|
||||
"以后再写awa\n",
|
||||
)
|
||||
}
|
||||
|
||||
// OpCommand 帮助命令
|
||||
func (c *CommandManager) OpCommand(cmd *Command) {
|
||||
cmd.Executor.IsGM = 1
|
||||
c.gameManager.SendPrivateChat(c.system, cmd.Executor, fmt.Sprintf("权限修改完毕, 现在你是GM啦 %v", cmd.Args))
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -75,43 +75,28 @@ func (g *GameManager) PullPrivateChatReq(player *model.Player, payloadMsg pb.Mes
|
||||
g.SendMsg(cmd.PullPrivateChatRsp, player.PlayerID, 0, pullPrivateChatRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) PrivateChatReq(player *model.Player, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user send private chat, uid: %v", player.PlayerID)
|
||||
req := payloadMsg.(*proto.PrivateChatReq)
|
||||
targetUid := req.TargetUid
|
||||
content := req.Content
|
||||
|
||||
// TODO 同步阻塞待优化
|
||||
targetPlayer := g.userManager.LoadTempOfflineUserSync(targetUid)
|
||||
if targetPlayer == nil {
|
||||
return
|
||||
}
|
||||
// SendPrivateChat 发送私聊文本消息给玩家
|
||||
func (g *GameManager) SendPrivateChat(player, targetPlayer *model.Player, content any) {
|
||||
chatInfo := &proto.ChatInfo{
|
||||
Time: uint32(time.Now().Unix()),
|
||||
Sequence: 101,
|
||||
ToUid: targetPlayer.PlayerID,
|
||||
Uid: player.PlayerID,
|
||||
IsRead: false,
|
||||
Content: nil,
|
||||
}
|
||||
|
||||
// 根据传入的值判断消息类型
|
||||
switch content.(type) {
|
||||
case *proto.PrivateChatReq_Text:
|
||||
text := content.(*proto.PrivateChatReq_Text).Text
|
||||
if len(text) == 0 {
|
||||
return
|
||||
}
|
||||
case string:
|
||||
// 文本消息
|
||||
chatInfo.Content = &proto.ChatInfo_Text{
|
||||
Text: text,
|
||||
Text: content.(string),
|
||||
}
|
||||
// 输入命令 会检测是否为命令的
|
||||
g.commandManager.InputCommand(text)
|
||||
case *proto.PrivateChatReq_Icon:
|
||||
icon := content.(*proto.PrivateChatReq_Icon).Icon
|
||||
case int, int32, uint32:
|
||||
// 图标消息
|
||||
chatInfo.Content = &proto.ChatInfo_Icon{
|
||||
Icon: icon,
|
||||
Icon: content.(uint32),
|
||||
}
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
// 消息加入自己的队列
|
||||
@@ -121,6 +106,7 @@ func (g *GameManager) PrivateChatReq(player *model.Player, payloadMsg pb.Message
|
||||
}
|
||||
msgList = append(msgList, g.ConvChatInfoToChatMsg(chatInfo))
|
||||
player.ChatMsgMap[targetPlayer.PlayerID] = msgList
|
||||
|
||||
// 消息加入目标玩家的队列
|
||||
msgList, exist = targetPlayer.ChatMsgMap[player.PlayerID]
|
||||
if !exist {
|
||||
@@ -129,6 +115,7 @@ func (g *GameManager) PrivateChatReq(player *model.Player, payloadMsg pb.Message
|
||||
msgList = append(msgList, g.ConvChatInfoToChatMsg(chatInfo))
|
||||
targetPlayer.ChatMsgMap[player.PlayerID] = msgList
|
||||
|
||||
// 如果目标玩家在线发送消息
|
||||
if targetPlayer.Online {
|
||||
// PacketPrivateChatNotify
|
||||
privateChatNotify := new(proto.PrivateChatNotify)
|
||||
@@ -140,6 +127,43 @@ func (g *GameManager) PrivateChatReq(player *model.Player, payloadMsg pb.Message
|
||||
privateChatNotify := new(proto.PrivateChatNotify)
|
||||
privateChatNotify.ChatInfo = chatInfo
|
||||
g.SendMsg(cmd.PrivateChatNotify, player.PlayerID, 0, privateChatNotify)
|
||||
}
|
||||
|
||||
func (g *GameManager) PrivateChatReq(player *model.Player, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user send private chat, uid: %v", player.PlayerID)
|
||||
req := payloadMsg.(*proto.PrivateChatReq)
|
||||
targetUid := req.TargetUid
|
||||
content := req.Content
|
||||
|
||||
// TODO 同步阻塞待优化
|
||||
targetPlayer := g.userManager.LoadTempOfflineUserSync(targetUid)
|
||||
if targetPlayer == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 根据发送的类型发送消息
|
||||
switch content.(type) {
|
||||
case *proto.PrivateChatReq_Text:
|
||||
text := content.(*proto.PrivateChatReq_Text).Text
|
||||
if len(text) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// 发送私聊文本消息
|
||||
g.SendPrivateChat(player, targetPlayer, text)
|
||||
|
||||
// 输入命令 会检测是否为命令的
|
||||
g.commandManager.InputCommand(player, text)
|
||||
|
||||
case *proto.PrivateChatReq_Icon:
|
||||
icon := content.(*proto.PrivateChatReq_Icon).Icon
|
||||
|
||||
// 发送私聊图标消息
|
||||
g.SendPrivateChat(player, targetPlayer, icon)
|
||||
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
// PacketPrivateChatRsp
|
||||
privateChatRsp := new(proto.PrivateChatRsp)
|
||||
|
||||
@@ -50,6 +50,7 @@ type Player struct {
|
||||
DropInfo *DropInfo `bson:"dropInfo"` // 掉落信息
|
||||
MainCharAvatarId uint32 `bson:"mainCharAvatarId"` // 主角id
|
||||
ChatMsgMap map[uint32][]*ChatMsg `bson:"chatMsgMap"` // 聊天信息
|
||||
IsGM uint8 `bson:"isGM"` // 管理员权限等级
|
||||
// 在线数据
|
||||
EnterSceneToken uint32 `bson:"-"` // 玩家的世界进入令牌
|
||||
DbState int `bson:"-"` // 数据库存档状态
|
||||
|
||||
Reference in New Issue
Block a user