diff --git a/gs/game/command_controller.go b/gs/game/command_controller.go index f658f4ed..37595536 100644 --- a/gs/game/command_controller.go +++ b/gs/game/command_controller.go @@ -9,9 +9,7 @@ import ( // HelpCommand 帮助命令 func (c *CommandManager) HelpCommand(cmd *CommandMessage) { - executor := cmd.Executor - - c.SendMessage(executor, + c.SendMessage(cmd.Executor, "========== 帮助 / Help ==========\n\n"+ "传送:/tp [-u ] [-s <场景ID>] -x <坐标X> -y <坐标Y> -z <坐标Z>\n\n"+ "给予:/give [-u ] [-c <数量>] -i <物品ID|武器ID|角色ID/item/weapon/avatar/all>\n", @@ -27,29 +25,40 @@ func (c *CommandManager) OpCommand(cmd *CommandMessage) { } player.IsGM = 1 - c.SendMessage(player, "权限修改完毕,现在你是GM啦~") + c.SendMessage(cmd.Executor, "权限修改完毕,现在你是GM啦~") } // TeleportCommand 传送玩家命令 -// tp [-u ] [-s ] -x -y -z +// tp [--u ] [--s ] {--t --x | --y | --z } func (c *CommandManager) TeleportCommand(cmd *CommandMessage) { - // 执行者如果不是玩家则必须输入目标UID + // 执行者如果不是玩家则必须输入UID player, ok := cmd.Executor.(*model.Player) if !ok && cmd.Args["u"] == "" { - c.SendMessage(cmd.Executor, "你不是玩家请指定目标UID。") + c.SendMessage(cmd.Executor, "你不是玩家请指定UID。") return } // 判断是否填写必备参数 - if cmd.Args["x"] == "" || cmd.Args["y"] == "" || cmd.Args["z"] == "" { - c.SendMessage(player, "参数不足,正确用法:/%v [-u ] [-s <场景ID>] -x <坐标X> -y <坐标Y> -z <坐标Z>", cmd.Name) + // 目前传送的必备参数是任意包含一个就行 + if cmd.Args["t"] == "" && cmd.Args["x"] == "" && cmd.Args["y"] == "" && cmd.Args["z"] == "" { + c.SendMessage(cmd.Executor, "参数不足,正确用法:%v [--u ] [--s <场景ID>] {--t <目标UID> | --x <坐标X> | --y <坐标Y> | --z <坐标Z>}", cmd.Name) + return + } + // 输入了目标UID则不能指定坐标或场景ID + if cmd.Args["t"] != "" && (cmd.Args["x"] != "" || cmd.Args["y"] != "" || cmd.Args["z"] != "" || cmd.Args["s"] != "") { + c.SendMessage(cmd.Executor, "你已指定目标玩家,无法指定传送位置。") return } // 初始值 - target := player // 目标 - sceneId := target.SceneId // 场景Id - pos := &model.Vector{} // 坐标 + var target *model.Player // 目标 + targetUid := uint32(0) // 目标玩家uid + sceneId := player.SceneId // 场景Id + pos := &model.Vector{ + X: player.Pos.X, + Y: player.Pos.Y, + Z: player.Pos.Z, + } // 坐标初始值为玩家当前所在位置 // 选择每个参数 for k, v := range cmd.Args { @@ -58,16 +67,16 @@ func (c *CommandManager) TeleportCommand(cmd *CommandMessage) { switch k { case "u": var uid uint64 - if uid, err = strconv.ParseUint(v, 10, 32); err != nil { + if uid, err = strconv.ParseUint(v, 10, 32); err == nil { // 判断目标用户是否在线 if user := USER_MANAGER.GetOnlineUser(uint32(uid)); user != nil { - target = user + player = user // 防止覆盖用户指定过的sceneId - if target.SceneId != sceneId { - sceneId = target.SceneId + if player.SceneId != sceneId { + sceneId = player.SceneId } } else { - c.SendMessage(player, "目标玩家不在线,UID: %v。", v) + c.SendMessage(cmd.Executor, "玩家不在线,UID: %v。", v) return } } @@ -76,6 +85,22 @@ func (c *CommandManager) TeleportCommand(cmd *CommandMessage) { if sid, err = strconv.ParseUint(v, 10, 32); err == nil { sceneId = uint32(sid) } + case "t": + var uid uint64 + if uid, err = strconv.ParseUint(v, 10, 32); err == nil { + // 判断目标用户是否在线 + user := USER_MANAGER.GetOnlineUser(uint32(uid)) + if user == nil { + // 目标玩家属于非本地玩家 + if !USER_MANAGER.GetRemoteUserOnlineState(uint32(uid)) { + // 全服不存在该在线玩家 + c.SendMessage(cmd.Executor, "目标玩家不在线,UID: %v。", v) + return + } + } + target = user + targetUid = uint32(uid) + } case "x": // 玩家此时的位置X var nowX float64 @@ -84,9 +109,12 @@ func (c *CommandManager) TeleportCommand(cmd *CommandMessage) { v = v[1:] // 去除 ~ nowX = player.Pos.X // 先记录 } - var x float64 - if x, err = strconv.ParseFloat(v, 64); err == nil { - pos.X = x + nowX // 如果不以 ~ 开头则加 0 + // 为空代表用户只输入 ~ 获取为玩家当前位置 + if v != "" { + var x float64 + if x, err = strconv.ParseFloat(v, 64); err == nil { + pos.X = x + nowX // 如果不以 ~ 开头则加 0 + } } case "y": // 玩家此时的位置Z @@ -96,9 +124,12 @@ func (c *CommandManager) TeleportCommand(cmd *CommandMessage) { v = v[1:] // 去除 ~ nowY = player.Pos.Y // 先记录 } - var y float64 - if y, err = strconv.ParseFloat(v, 64); v != "~" && err == nil { - pos.Y = y + nowY + // 为空代表用户只输入 ~ 获取为玩家当前位置 + if v != "" { + var y float64 + if y, err = strconv.ParseFloat(v, 64); err == nil { + pos.Y = y + nowY + } } case "z": // 玩家此时的位置Z @@ -108,47 +139,65 @@ func (c *CommandManager) TeleportCommand(cmd *CommandMessage) { v = v[1:] // 去除 ~ nowZ = player.Pos.Z // 先记录 } - var z float64 - if z, err = strconv.ParseFloat(v, 64); v != "~" && err == nil { - pos.Z = z + nowZ + // 为空代表用户只输入 ~ 获取为玩家当前位置 + if v != "" { + var z float64 + if z, err = strconv.ParseFloat(v, 64); err == nil { + pos.Z = z + nowZ + } } default: - c.SendMessage(player, "参数 -%v 冗余。", k) + c.SendMessage(cmd.Executor, "参数 --%v 冗余。", k) return } // 解析错误的话应该是参数类型问题 if err != nil { - c.SendMessage("参数 -%v 有误,类型错误。", k) + c.SendMessage(cmd.Executor, "参数 --%v 有误,类型错误。", k) return } } - // 传送玩家 - c.GMTeleportPlayer(target.PlayerID, sceneId, pos.X, pos.Y, pos.Z) + // 玩家是否指定目标UID + if cmd.Args["t"] != "" { + // 如果玩家不与目标玩家同一世界或不同服务器 + if target == nil || player.WorldId != target.WorldId { + // 请求进入目标玩家世界 + GAME_MANAGER.UserApplyEnterWorld(player, targetUid) + // 发送消息给执行者 + c.SendMessage(cmd.Executor, "已将玩家 UID:%v 请求加入目标玩家 UID:%v 的世界。", player.PlayerID, targetUid) + } else { + // 传送玩家至目标玩家的位置 + c.GMTeleportPlayer(player.PlayerID, target.SceneId, target.Pos.X, target.Pos.Y, target.Pos.Z) + // 发送消息给执行者 + c.SendMessage(cmd.Executor, "已将玩家 UID:%v 传送至 目标玩家 UID:%v。", player.PlayerID, targetUid) + } + } else { + // 传送玩家至指定的位置 + c.GMTeleportPlayer(player.PlayerID, sceneId, pos.X, pos.Y, pos.Z) + // 发送消息给执行者 + c.SendMessage(cmd.Executor, "已将玩家 UID:%v 传送至 场景:%v, X:%.2f, Y:%.2f, Z:%.2f。", player.PlayerID, sceneId, pos.X, pos.Y, pos.Z) + } - // 发送消息给执行者 - c.SendMessage(player, "已将玩家 UID:%v 传送至 场景:%v, X:%.2f, Y:%.2f, Z:%.2f。", target.PlayerID, sceneId, pos.X, pos.Y, pos.Z) } // GiveCommand 给予物品命令 -// give [-u ] [-c ] -i +// give [--u ] [--c ] --i <物品ID/item/weapon/reliquary/avatar/all> func (c *CommandManager) GiveCommand(cmd *CommandMessage) { - // 执行者如果不是玩家则必须输入目标UID + // 执行者如果不是玩家则必须输入UID player, ok := cmd.Executor.(*model.Player) if !ok && cmd.Args["u"] == "" { - c.SendMessage(cmd.Executor, "你不是玩家请指定目标UID。") + c.SendMessage(cmd.Executor, "你不是玩家请指定UID。") return } // 判断是否填写必备参数 if cmd.Args["i"] == "" { - c.SendMessage(player, "参数不足,正确用法:/%v [-u ] [-c <数量>] -i <物品ID|武器ID|圣遗物ID|角色ID/item/weapon/reliquary/avatar/all>。", cmd.Name) + c.SendMessage(cmd.Executor, "参数不足,正确用法:%v [--u ] [--c <数量>] --i <物品ID / item / weapon / reliquary / avatar / all>。", cmd.Name) return } // 初始值 - target := player // 目标 count := uint32(1) // 数量 itemId := uint32(0) // 物品Id // 给予物品的模式 @@ -163,12 +212,12 @@ func (c *CommandManager) GiveCommand(cmd *CommandMessage) { switch k { case "u": var uid uint64 - if uid, err = strconv.ParseUint(v, 10, 32); err != nil { + if uid, err = strconv.ParseUint(v, 10, 32); err == nil { // 判断目标用户是否在线 if user := USER_MANAGER.GetOnlineUser(uint32(uid)); user != nil { - target = user + player = user } else { - c.SendMessage(player, "目标玩家不在线,UID: %v。", v) + c.SendMessage(cmd.Executor, "目标玩家不在线,UID: %v。", v) return } } @@ -185,19 +234,19 @@ func (c *CommandManager) GiveCommand(cmd *CommandMessage) { default: var id uint64 if id, err = strconv.ParseUint(v, 10, 32); err != nil { - c.SendMessage(player, "参数 -%v 有误,允许内容: 。", k) + c.SendMessage(cmd.Executor, "参数 --%v 有误,允许内容: <物品ID / item / weapon / reliquary / avatar / all>。", k) return } itemId = uint32(id) } default: - c.SendMessage(player, "参数 -%v 冗余。", k) + c.SendMessage(cmd.Executor, "参数 --%v 冗余。", k) return } // 解析错误的话应该是参数类型问题 if err != nil { - c.SendMessage("参数 -%v 有误,类型错误。", k) + c.SendMessage(cmd.Executor, "参数 --%v 有误,类型错误。", k) return } } @@ -208,16 +257,16 @@ func (c *CommandManager) GiveCommand(cmd *CommandMessage) { _, ok := GAME_MANAGER.GetAllItemDataConfig()[int32(itemId)] if ok { // 给予玩家物品 - c.GMAddUserItem(target.PlayerID, itemId, count) - c.SendMessage(player, "已给予玩家 UID:%v, 物品ID: %v 数量: %v。", target.PlayerID, itemId, count) + c.GMAddUserItem(player.PlayerID, itemId, count) + c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 物品ID: %v 数量: %v。", player.PlayerID, itemId, count) return } // 判断是否为武器 _, ok = GAME_MANAGER.GetAllWeaponDataConfig()[int32(itemId)] if ok { // 给予玩家武器 - c.GMAddUserWeapon(target.PlayerID, itemId, count) - c.SendMessage(player, "已给予玩家 UID:%v, 武器ID:%v 数量:%v。", target.PlayerID, itemId, count) + c.GMAddUserWeapon(player.PlayerID, itemId, count) + c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 武器ID:%v 数量:%v。", player.PlayerID, itemId, count) return } @@ -225,8 +274,8 @@ func (c *CommandManager) GiveCommand(cmd *CommandMessage) { _, ok = GAME_MANAGER.GetAllReliquaryDataConfig()[int32(itemId)] if ok { // 给予玩家圣遗物 - c.GMAddUserReliquary(target.PlayerID, itemId, count) - c.SendMessage(player, "已给予玩家 UID:%v, 圣遗物ID:%v 数量:%v。", target.PlayerID, itemId, count) + c.GMAddUserReliquary(player.PlayerID, itemId, count) + c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 圣遗物ID:%v 数量:%v。", player.PlayerID, itemId, count) return } @@ -234,51 +283,49 @@ func (c *CommandManager) GiveCommand(cmd *CommandMessage) { _, ok = GAME_MANAGER.GetAllAvatarDataConfig()[int32(itemId)] if ok { // 给予玩家角色 - c.GMAddUserAvatar(target.PlayerID, itemId) - c.SendMessage(player, "已给予玩家 UID:%v, 角色ID:%v 数量:%v。", target.PlayerID, itemId, count) + c.GMAddUserAvatar(player.PlayerID, itemId) + c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 角色ID:%v 数量:%v。", player.PlayerID, itemId, count) return } // 都执行到这里那肯定是都不匹配 - c.SendMessage(player, "物品ID:%v 不存在。", itemId) + c.SendMessage(cmd.Executor, "物品ID:%v 不存在。", itemId) case "item": // 给予玩家所有物品 - c.GMAddUserAllItem(target.PlayerID, count) - c.SendMessage(player, "已给予玩家 UID:%v, 所有物品 数量:%v。", target.PlayerID, count) + c.GMAddUserAllItem(player.PlayerID, count) + c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 所有物品 数量:%v。", player.PlayerID, count) case "weapon": // 给予玩家所有武器 - c.GMAddUserAllWeapon(target.PlayerID, count) - c.SendMessage(player, "已给予玩家 UID:%v, 所有武器 数量:%v。", target.PlayerID, count) + c.GMAddUserAllWeapon(player.PlayerID, count) + c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 所有武器 数量:%v。", player.PlayerID, count) case "reliquary": // 给予玩家所有圣遗物 - c.GMAddUserAllReliquary(target.PlayerID, count) - c.SendMessage(player, "已给予玩家 UID:%v, 所有圣遗物 数量:%v。", target.PlayerID, count) + c.GMAddUserAllReliquary(player.PlayerID, count) + c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 所有圣遗物 数量:%v。", player.PlayerID, count) case "avatar": // 给予玩家所有角色 - c.GMAddUserAllAvatar(target.PlayerID) - c.SendMessage(player, "已给予玩家 UID:%v, 所有角色。", target.PlayerID) + c.GMAddUserAllAvatar(player.PlayerID) + c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 所有角色。", player.PlayerID) case "all": // 给予玩家所有内容 - c.GMAddUserAllEvery(target.PlayerID, count, count) // TODO 武器额外获取数量 - c.SendMessage(player, "已给予玩家 UID:%v, 所有内容。", target.PlayerID) + c.GMAddUserAllEvery(player.PlayerID, count, count) // TODO 武器额外获取数量 + c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 所有内容。", player.PlayerID) } } // ReloadConfigCommand 帮助命令 func (c *CommandManager) ReloadConfigCommand(cmd *CommandMessage) { - executor := cmd.Executor - LOCAL_EVENT_MANAGER.localEventChan <- &LocalEvent{ EventId: ReloadGameDataConfig, } - c.SendMessage(executor, "成功发送重载配置请求。") + c.SendMessage(cmd.Executor, "成功发送重载配置请求。") } // GcgCommand Gcg测试命令 -func (c *CommandManager) GcgCommand(cm *CommandMessage) { - player := cm.Executor.(*model.Player) +func (c *CommandManager) GcgCommand(cmd *CommandMessage) { + player := cmd.Executor.(*model.Player) GAME_MANAGER.GCGStartChallenge(player) - c.SendMessage(player, "收到命令") + c.SendMessage(cmd.Executor, "收到命令") } diff --git a/gs/game/command_manager.go b/gs/game/command_manager.go index 5a799dfa..c45cb6a8 100644 --- a/gs/game/command_manager.go +++ b/gs/game/command_manager.go @@ -105,18 +105,25 @@ func (c *CommandManager) IsCommand(cmdName string) bool { return false } -// InputCommand 输入要处理的命令 -func (c *CommandManager) InputCommand(executor any, text string) { +// PlayerInputCommand 玩家输入要处理的命令 +func (c *CommandManager) PlayerInputCommand(player *model.Player, targetUid uint32, text string) { // 机器人不会读命令所以写到了 PrivateChatReq - // 确保消息文本为 / 开头 - // 如果不为这个开头那接下来就毫无意义 - if strings.HasPrefix(text, "/") { - logger.Debug("input command, uid: %v text: %v", c.GetExecutorId(executor), text) - - // 输入的命令将在其他协程中处理 - c.commandTextInput <- &CommandMessage{Executor: executor, Text: text} + // 确保私聊的目标是处理命令的机器人 + if targetUid != c.system.PlayerID { + return } + // 输入命令进行处理 + c.InputCommand(player, text) +} + +// InputCommand 输入要处理的命令 +func (c *CommandManager) InputCommand(executor any, text string) { + // 留着这个主要还是为了万一以后要对接要别的地方 + logger.Debug("input command, uid: %v text: %v", c.GetExecutorId(executor), text) + + // 输入的命令将在其他协程中处理 + c.commandTextInput <- &CommandMessage{Executor: executor, Text: text} } // HandleCommand 处理命令 @@ -124,9 +131,9 @@ func (c *CommandManager) InputCommand(executor any, text string) { func (c *CommandManager) HandleCommand(cmd *CommandMessage) { executor := cmd.Executor - // 将开头的 / 去掉 并 分割出命令的每个参数 + // 分割出命令的每个参数 // 不区分命令的大小写 统一转为小写 - cmdSplit := strings.Split(strings.ToLower(cmd.Text[1:]), " -") + cmdSplit := strings.Split(strings.ToLower(cmd.Text), " --") // 分割出来啥也没有可能是个空的字符串 // 此时将会返回的命令名和命令参数都为空 @@ -149,7 +156,7 @@ func (c *CommandManager) HandleCommand(cmd *CommandMessage) { // 分割出来的参数只有一个那肯定不是键值对 if len(cmdArg) < 2 { - c.SendMessage(executor, "格式错误,用法: /%v -[参数名] [参数]。", cmd.Name) + c.SendMessage(executor, "格式错误,用法: %v --[参数名] [参数]。", cmd.Name) return } @@ -189,7 +196,7 @@ func (c *CommandManager) ExecCommand(cmd *CommandMessage) { cmdFunc, ok := c.commandFuncRouter[cmd.Name] if !ok { // 玩家可能会执行一些没有的命令仅做调试输出 - c.SendMessage(executor, "命令不存在,输入 /help 查看帮助。") + c.SendMessage(executor, "命令不存在,输入 help 查看帮助。") return } // 判断命令权限是否注册 @@ -219,9 +226,9 @@ func (c *CommandManager) SendMessage(executor any, msg string, param ...any) { // 玩家类型 player := executor.(*model.Player) GAME_MANAGER.SendPrivateChat(c.system, player.PlayerID, fmt.Sprintf(msg, param...)) - case string: - // GM接口等 - // str := executor.(string) + // case string: + // GM接口等 + // str := executor.(string) default: // 无效的类型报错 logger.Error("command executor type error, type: %T", executor) @@ -236,9 +243,9 @@ func (c *CommandManager) GetExecutorId(executor any) uint32 { // 玩家类型 player := executor.(*model.Player) return player.PlayerID - case string: - // GM接口等 - // return 123 + // case string: + // GM接口等 + // return 123 default: // 无效的类型报错 logger.Error("command executor type error, type: %T", executor) diff --git a/gs/game/player_chat.go b/gs/game/player_chat.go index b47ccf66..41895f5f 100644 --- a/gs/game/player_chat.go +++ b/gs/game/player_chat.go @@ -189,7 +189,7 @@ func (g *GameManager) PrivateChatReq(player *model.Player, payloadMsg pb.Message // 发送私聊文本消息 g.SendPrivateChat(player, targetUid, text) // 输入命令 会检测是否为命令的 - COMMAND_MANAGER.InputCommand(player, text) + COMMAND_MANAGER.PlayerInputCommand(player, targetUid, text) case *proto.PrivateChatReq_Icon: icon := content.(*proto.PrivateChatReq_Icon).Icon // 发送私聊图标消息 diff --git a/gs/game/player_equip.go b/gs/game/player_equip.go index 6035f43b..62d2ad33 100644 --- a/gs/game/player_equip.go +++ b/gs/game/player_equip.go @@ -68,6 +68,8 @@ func (g *GameManager) TakeoffEquipReq(player *model.Player, payloadMsg pb.Messag } // 卸下圣遗物 player.TakeOffReliquary(avatar.AvatarId, reliquary.ReliquaryId) + // 角色更新面板 + g.UpdateUserAvatarFightProp(player.PlayerID, avatar.AvatarId) // 更新玩家装备 avatarEquipChangeNotify := &proto.AvatarEquipChangeNotify{ AvatarGuid: avatar.Guid, @@ -113,6 +115,8 @@ func (g *GameManager) WearEquipReq(player *model.Player, payloadMsg pb.Message) g.SendError(cmd.WearEquipRsp, player, &proto.WearEquipRsp{}) return } + // 角色更新面板 + g.UpdateUserAvatarFightProp(player.PlayerID, avatar.AvatarId) wearEquipRsp := &proto.WearEquipRsp{ AvatarGuid: req.AvatarGuid,