一、先说结论
这次要处理的告警是:
19/04/26 15:20:10.85 [:000000f2] [I] activity_open:未注册脚本或脚本少内容 scriptid = 402043
这个问题不是客户端坏了,也不是活动配置表本身有毒。
真正的根因是:
- 当前客户端确实还在使用
402043
- 当前服务端
ActivityNotice.txt 也确实会调起 402043
- 但是现服
scripts.lua 没有注册 402043
- 并且现服也没有对应的 Lua 5.4 活动脚本模块
所以场景层在执行 activity_open 时,先调 GetDataValidator 就直接拿不到,最后只能打印:
activity_open:未注册脚本或脚本少内容 scriptid = 402043
这类问题的正确修法方向:
二、这条告警是怎么打出来的
先看当前服务端场景层。
文件:
/ubuntu/Game2/services/scene/scenecore.lua
关键逻辑如下:
function scenecore:activity_open(activity)
local scriptid = activity.scriptid or define.INVAILD_ID
if scriptid ~= define.INVAILD_ID then
local param6 = self.scriptenginer:call(scriptid, "GetDataValidator", 0, 0)
if param6 then
local id = activity.id
local param1 = activity.slow_broad or -1
local param2 = activity.reserve1 or -1
local param3 = activity.reserve2 or -1
local param4 = activity.reserve3 or -1
local param5 = activity.reserve4 or -1
self.scriptenginer:call(scriptid, "OnDefaultEvent", id, param1, param2, param3, param4, param5, param6)
else
skynet.logi("activity_open:未注册脚本或脚本少内容 scriptid = ", scriptid)
end
end
end
这里要注意一个很容易忽略的点:
不是“脚本文件存在”就行,而是必须至少满足这一套活动脚本入口:
GetDataValidator
OnDefaultEvent
OnTimer
少了第一步,连 OnDefaultEvent 都不会调,日志就会直接打出来。
三、先确认 402043 到底是谁
1. 当前客户端脚本映射
文件:
客户端/Config/Script.dat
可以查到:
402043=\event\fuben\efuben_cuju_2.lua
这一步说明当前客户端确实认识 402043,并且它对应的是:
\event\fuben\efuben_cuju_2.lua
2. 当前服务端活动配置
文件:
/ubuntu/Game2/configs/ActivityNotice.txt
对应活动行里也能看到 402043:
58 1 2 12 0 402043 75 ...
说明这不是“客户端孤儿脚本”,而是当前服务端活动表真的会调用它。
3. 当前服务端注册表
文件:
服务端/ubuntu/Game2/services/scripts/scripts.lua
原本附近只有:
[401001] = "scripts.event.fuben.efuben_1_zhenlong_huodong",
[402040] = "scripts.event.fuben.efuben_cuju",
[402041] = "scripts.obj.fuben.ofuben_4_cuju",
[402046] = "scripts.event.fuben.efuben_piaomiao",
[402047] = "scripts.event.fuben.efuben_bangzhan",
也就是说:
402040 有
402041 有
402043 没有
根因到这里其实已经很明确了。
四、老版本脚本告诉了我们什么
旧资源里能找到老 Lua 4.0 脚本:
Public/Data/Script/event/fuben/efuben_cuju_2.lua
老脚本核心逻辑非常短,只有两件事:
- 在指定日期范围内才启动活动公告
- 活动失效后停止活动
老写法大概是这样:
function x402043_OnDefaultEvent(sceneId, actId, iNoticeType, param2, param3, param4, param5)
local nToday = LuaFnGetDayOfThisMonth()
if (nToday > 7 and nToday < 15) or (nToday > 21) then
return
end
StartOneActivity(sceneId, actId, floor(60 * 1000), iNoticeType)
end
function x402043_OnTimer(sceneId, actId, uTime)
if CheckActiviyValidity(sceneId, actId) == 0 then
StopOneActivity(sceneId, actId)
end
end
但是这里不能直接复制到现服。
因为当前服务端已经不是老 Lua 4.0 的全局函数风格,而是 Lua 5.4 的类式脚本风格,要改成:
class(...)
script_base
self:StartOneActivity(...)
self:CheckActiviyValidity(...)
self:StopOneActivity(...)
五、这次修复最终只改 2 个文件
/ubuntu/Game2/services/scripts/event/fuben/efuben_cuju_2.lua
/ubuntu/Game2/services/scripts/scripts.lua
六、第一处修改:新增 Lua 5.4 活动脚本
新建文件:
/ubuntu/Game2/services/scripts/event/fuben/efuben_cuju_2.lua
完整代码如下,可以直接抄:
***付费内容*** ">[/kkpay]
七、第二处修改:注册 402043
打开文件:
/ubuntu/Game2/services/scripts/scripts.lua
在 402040 附近加入一行:
[401001] = "scripts.event.fuben.efuben_1_zhenlong_huodong",
[402040] = "scripts.event.fuben.efuben_cuju",
[402043] = "scripts.event.fuben.efuben_cuju_2",
[402041] = "scripts.obj.fuben.ofuben_4_cuju",
[402046] = "scripts.event.fuben.efuben_piaomiao",
[402047] = "scripts.event.fuben.efuben_bangzhan",
这一行不加,脚本文件就算写出来了,脚本引擎也根本找不到它。
八、为什么 GetDataValidator 不能省
很多人第一次修这个问题时,最容易偷懒的地方就是只写一个 OnDefaultEvent,或者只想随便塞个空脚本把日志压掉。
这在当前框架里是不够的。
因为 activity_open 的调用顺序就是:
- 先调
GetDataValidator
- 拿到返回值后再作为
param6
- 再去调
OnDefaultEvent
如果没有 GetDataValidator,或者它返回 nil,日志还是会继续报:
activity_open:未注册脚本或脚本少内容 scriptid = 402043
所以这次补脚本时,GetDataValidator 不是装饰品,而是活动框架的握手校验入口。
九、为什么不能只写一个空壳脚本
如果只是想消日志,理论上你确实可以写一个纯占位脚本。
但那样会引出两个问题:
- 告警没了,不代表功能恢复了
- 老版本这条脚本本来就有日期过滤逻辑,空壳会把原有行为吃掉
也就是说,真正正确的修法不是“让它不报错”,而是:
这也是为什么这里我没有写成万能空模板,而是把老 efuben_cuju_2.lua 的核心逻辑一起移植过来。
十、现服为什么要用 self: 风格
当前 Game2 的脚本体系,很多能力都已经封装在 script_base.lua 里了,比如:
function script_base:StartOneActivity(actId,on_time,noticetype,second,minute,hour)
function script_base:CheckActiviyValidity(actId)
function script_base:StopOneActivity(actId)
function script_base:LuaFnGetDayOfThisMonth()
所以从老 Lua 4.0 移植过来时,要把这些全局函数调用改成当前服务端风格:
self:LuaFnGetDayOfThisMonth()
self:StartOneActivity(...)
self:CheckActiviyValidity(...)
self:StopOneActivity(...)
这一步如果不改,脚本很容易变成“看起来像修了,实际运行时报 nil”。
1. 观察日志
重点看原来的这条日志是否消失:
activity_open:未注册脚本或脚本少内容 scriptid = 402043
2. 观察活动公告是否正常
到了配置时段后,确认对应活动公告能正常启动和结束。
十二、这类问题以后怎么快速排查
以后再遇到:
activity_open:未注册脚本或脚本少内容 scriptid = xxxx
我一般就按这条顺序排:
- 先看
configs/ActivityNotice.txt,确认是谁在用这个 scriptid
- 再看客户端
Config/Script.dat,确认当前客户端对应哪个脚本名
- 再看服务端
services/scripts/scripts.lua 有没有注册
- 再看现服是否真的存在对应 Lua 5.4 模块
- 最后去老资源或老 C++ 里找原始行为,判断是该写占位,还是该完整移植
这套流程比盲猜快很多,也更不容易把问题修偏。