完整课程入口:996 全套课程体系 | Lua 学习路径 | 幂尔框架 mirs.cn
运维一个服务器,加物品、调等级、刷怪、开关活动是日常。第一代形态是手敲命令字符串:@item 玩家名 1001 5,快,但参数顺序全靠记,敲错就是事故。第二代是配置表驱动:命令与参数定义在表里,程序自动生成帮助与校验。第三代是参数化面板:配合前端界面点选执行。无论哪代,核心都是同一层——结构化的 GM 命令处理器。
把每条命令定义为数据:名称、权限等级、参数类型表、执行函数。启动时统一注册,执行时统一做权限与参数校验:
local Cmds = {}
local function reg(def) Cmds[string.lower(def.name)] = def end
reg{
name = "item", level = 3,
args = { {"玩家名","string"}, {"物品id","int"}, {"数量","int"} },
run = function(who, name, itemId, count)
giveItem(name, itemId, count)
log("GM", who, "发物品", name, itemId, count) -- 全量留痕
end
}
function ExecGM(who, level, line)
local parts = {}
for w in line:gmatch("%S+") do parts[#parts + 1] = w end
local def = Cmds[string.lower(parts[1] or "")]
if not def then return "未知命令" end
if level < def.level then return "权限不足" end
-- 逐参数按类型校验后调用 def.run
end
权限分级。 level 1 查询、2 发放、3 数值改写、4 危险操作(重载/删档),命令注册时定死,执行时强制校验,任何人不得绕过。
全量留痕。 每次执行记录:谁、何时、什么命令、什么参数、结果。GM 日志是封号与客诉的唯一凭据,这一步省不得。
参数校验前置。 int 就是 int、玩家名先验在线,错误在入口拦下并回提示,绝不带着脏参数进业务函数。
影响范围先声明。 对全服生效的命令(公告、加速倍率)在注册时标记 global=true,执行前要求二次确认参数,防手抖。
工具也要热更。 GM 处理器按模块挂表,加新命令 = 注册一条数据,不需要重启 M2——应急时刻你会感谢这个设计。
把这套处理器与文档自动生成(遍历 Cmds 输出帮助表)组合起来,一天就能搭出可持续演进的 GM 体系,比每次现写命令字符串稳妥得多。
getgmlevel(actor)
获取玩家GM权限值,命令分发前先取权限值,权限表只在服务端
| 参数 | 类型 | 说明 |
|---|---|---|
| actor | object | 玩家对象(必填参数) |
setgmlevel(actor, gmlevel)
设置玩家GM权限值,调试期改权限,比改配置文件快
| 参数 | 类型 | 说明 |
|---|---|---|
| actor | object | 玩家对象(必填参数) |
| gmlevel | integer | GM权限值(必填参数) |
regnpcmsg(msgId, NPCIndex)
给NPC注册Lua消息,把命令挂到 NPC 消息上,玩家侧只发命令字
| 参数 | 类型 | 说明 |
|---|---|---|
| msgId | int | 消息ID(必填参数) |
| NPCIndex | int | NPC索引(NPC配置表中的ID)(必填参数) |
say(actor, msg)
NPC界面文本发送,命令回执用界面文本,比系统公告更合适
| 参数 | 类型 | 说明 |
|---|---|---|
| actor | object | 玩家对象(必填参数) |
| msg | string | 界面文本内容(必填参数) |
openmerchantbigdlg(actor, pos, x, y, height, width, bool, closeX, closeY, isMove)
打开NPC大窗口,参数化面板类的多条命令用大窗口承载
| 参数 | 类型 | 说明 |
|---|---|---|
| actor | object | 路径(必填参数) |
| pos | int | 显示位置(必填参数) |
| x | int | X坐标(必填参数) |
| y | int | Y坐标(必填参数) |
| height | int | 高度(必填参数) |
| width | int | 宽度(必填参数) |
getplayerbyname(name)
获取玩家对象 根据玩家名,按名字定位执行目标,注意重名与离线情况
| 参数 | 类型 | 说明 |
|---|---|---|
| name | string | 玩家名字(必填参数) |
setplaydef(actor, varName)
设置玩家变量,挂在玩家身上的命令上下文,下线即失效
| 参数 | 类型 | 说明 |
|---|---|---|
| actor | object | 玩家对象(必填参数) |
| varName | string | 变量名(必填参数) |
getplaydef(actor, varName)
获取玩家变量,读取上一次命令留下的状态
| 参数 | 类型 | 说明 |
|---|---|---|
| actor | object | 玩家对象(必填参数) |
| varName | string | 变量名(必填参数) |