一、引擎内置过滤机制与触发链路
@@InPutStringX弹框输入后,客户端把字符串发回服务端,引擎先做第一层校验:命中M2过滤列表→直接跳转[@IsInFilterList](Hero端)或[@MsgFilter](3K端),不写入S变量、不执行后续脚本。这一层是硬编码在引擎里的,脚本层面无法绕过,但过滤列表的内容完全由服务端维护。
过滤列表位置:M2控制器→查看→列表信息→其他设置→过滤字符(部分版本存为GuildRankNameFilter.txt或FilterChar.txt)。每行一个词条,支持纯文本匹配。玩家输入包含任意词条即触发跳转。
二、脚本层二次校验:长度、字符集、格式
内置过滤只管"有没有命中词条",不管长度超限、纯数字、特殊符号组合等问题。实际脚本必须在回调段里加#if条件判断:
[@CallInPutString10]
if
EQUALS10
act
MESSAGEBOX输入不能为空
GOTO@main
elsesay
if
LARGE$STRLEN(S10)20
act
MESSAGEBOX输入长度不能超过20个字符
GOTO@main
elsesay
;继续正常逻辑
act
SENDMSG6输入内容:S10
说明:部分引擎支持$STRLEN()函数取字符串长度,不支持的用自定义计数或限制输入源(客户端输入框本身有字节上限)。
三、逐字符扫描检测特殊符号
对于需要严格限制字符集的场景(如行会名只允许中文+字母+数字),用循环或多次CHECKCONTAINS判断:
if
CHECKCONTAINSS10~
act
MESSAGEBOX不能包含~符号
GOTO@main
elsesay
if
CHECKCONTAINSS10`
act
MESSAGEBOX不能包含`符号
GOTO@main
elsesay
if
CHECKCONTAINSS10|
act
MESSAGEBOX不能包含|符号
GOTO@main
elsesay
if
CHECKCONTAINSS10<
act
MESSAGEBOX不能包含<符号
GOTO@main
elsesay
if
CHECKCONTAINSS10>
act
MESSAGEBOX不能包含>符号
GOTO@main
elsesay
if
CHECKCONTAINSS10&
act
MESSAGEBOX不能包含&符号
GOTO@main
elsesay
;全部通过才执行
act
GOTO@process
需要屏蔽的字符清单(按危害程度排序):
•|:部分版本脚本解析器把|当命令分隔符,注入后可执行额外指令
•<>:脚本标签语法符号,输入含<可能被误解析为标签跳转
•~:变量展开符号,某些引擎里~S10会展开为全局变量
•&:条件连接符,可能干扰#if解析
•'":SQL注入场景(如果后端用文本数据库且未转义)
•\r\n:换行注入,破坏脚本块结构
四、数字型输入的双重保险
即使弹的是@@InPutString,玩家也可能输入纯数字。如果需要数字,回调段里用EQUAL/NOTEQUAL+范围判断:
[@CallInPutString11]
if
EQUALS110
act
MESSAGEBOX不能为0
GOTO@main
elsesay
if
SMALLN111
act
MESSAGEBOX不能小于1
GOTO@main
elsesay
if
LARGEN119999
act
MESSAGEBOX不能超过9999
GOTO@main
elsesay
act
;S11已确认为合法数字字符串,N11为对应数值
SENDMSG6确认数值:N11
注意:@@InPutString的结果在S变量里,但引擎同时会尝试解析为数字存入同名N变量(如S11→N11)。如果输入含非数字字符,N11为0,可以用这个特性做"纯数字校验"——N11==0且S11不为"0"说明含字母。
五、数据库落盘前的转义处理
输入最终要写入文本文件或数据库时,必须做转义:
1.写文本文件(SAVEVAR):
变量内容含换行符会破坏文件格式。在写入前用REPLACE函数清除或替换危险字符:
CALCVARGLOBALZ1=$REPLACE(S10"|""")
CALCVARGLOBALZ1=$REPLACE(Z1"<""")
CALCVARGLOBALZ1=$REPLACE(Z1">""")
SAVEVARGLOBALZ1..\QuestDiary\数据文件\InputLog.txt
2.写DBC2000/Access:
通过脚本命令写入数据库的记录,字段长度限制要在脚本层提前拦截。比如HeroDB的Guild表Name字段varchar(20),脚本里用$STRLEN限制在20字符内,超长截断或拒绝。
六、行会名/角色名注册完整过滤示例
[@CallInPutString5]
;第一层:空值
if
EQUALS5
act
MESSAGEBOX行会名不能为空
GOTO@main
elsesay
;第二层:长度
if
LARGE$STRLEN(S5)16
act
MESSAGEBOX行会名最多16个字符
GOTO@main
elsesay
;第三层:非法字符
if
CHECKCONTAINSS5~
act
MESSAGEBOX不能包含~符号
GOTO@main
elsesay
if
CHECKCONTAINSS5<
act
MESSAGEBOX不能包含<符号
GOTO@main
elsesay
if
CHECKCONTAINSS5>
act
MESSAGEBOX不能包含>符号
GOTO@main
elsesay
if
CHECKCONTAINSS5|
act
MESSAGEBOX不能包含|符号
GOTO@main
elsesay
;第四层:重复检查
if
CHECKTEXTLIST..\QuestDiary\Guild\GuildNames.txtS5
act
MESSAGEBOX该行会名已被注册
GOTO@main
elsesay
;第五层:引擎内置过滤(自动跳@IsInFilterList,此处不用写)
;全部通过
act
ADDTEXTLIST..\QuestDiary\Guild\GuildNames.txtS5
SENDMSG6行会名[S5]注册成功
[@IsInFilterList]
act
MESSAGEBOX行会名含非法词汇,请重新输入
GOTO@main
七、M2过滤列表维护规范
过滤列表不是越长越好,维护原则:
•按功能分区:行会名过滤、聊天过滤、任务输入过滤分开建表(不同版本支持多个过滤列表文件)
•定期清理:过时的敏感词删掉,避免误拦正常输入
•测试流程:每次加新词条后,用测试号走一遍完整输入流程,确认不误伤
•备份:过滤列表文件改前复制一份.bak,改崩了能回滚
八、多引擎差异汇总
项目Hero引擎3K引擎GOM/GEE
回调段名[@CallInPutStringX][@InPutStringX][@InPutStringX]
过滤跳转段[@IsInFilterList][@MsgFilter][@MsgFilter]
过滤列表位置M2→列表信息→其他设置同左同左
变量存储SX+NXSX+NXSX+NX
CHECKCONTAINS支持支持支持
$STRLEN部分版本支持部分版本支持商业版支持
最大输入长度客户端限制约60字节同左同左
九、调试与日志
输入异常时排查步骤:
1.确认是否触发了[@IsInFilterList]→说明命中引擎过滤列表,去M2列表里查对应词条
2.没触发过滤但后续逻辑异常→在回调段第一行加SENDMSG6调试:S10,看实际写入内容
3.变量读出来是空的→检查回调段名是否拼对(Hero必须带Call)
4.中文变乱码→脚本文件存成UTF-8了,改ANSI
5.特殊符号没被拦住→CHECKCONTAINS的字符可能被引擎吃掉了,换成十六进制比较或升级引擎版本
十、完整防御纵深总结
玩家按键→客户端输入框(长度限制)→@@InPutStringX发包→引擎层过滤列表匹配(@IsInFilterList拦截)→写入S变量→回调段脚本校验(空值/长度/字符集/格式/重复)→转义处理→落盘(文本/DB)。五层防线,任意一层漏了还有下一层兜底。脚本层校验永远不能省——引擎过滤列表只管"有没有这个词",不管业务逻辑合不合法。
@@InPutStringX弹框输入后,客户端把字符串发回服务端,引擎先做第一层校验:命中M2过滤列表→直接跳转[@IsInFilterList](Hero端)或[@MsgFilter](3K端),不写入S变量、不执行后续脚本。这一层是硬编码在引擎里的,脚本层面无法绕过,但过滤列表的内容完全由服务端维护。
过滤列表位置:M2控制器→查看→列表信息→其他设置→过滤字符(部分版本存为GuildRankNameFilter.txt或FilterChar.txt)。每行一个词条,支持纯文本匹配。玩家输入包含任意词条即触发跳转。
二、脚本层二次校验:长度、字符集、格式
内置过滤只管"有没有命中词条",不管长度超限、纯数字、特殊符号组合等问题。实际脚本必须在回调段里加#if条件判断:
[@CallInPutString10]
if
EQUALS10
act
MESSAGEBOX输入不能为空
GOTO@main
elsesay
if
LARGE$STRLEN(S10)20
act
MESSAGEBOX输入长度不能超过20个字符
GOTO@main
elsesay
;继续正常逻辑
act
SENDMSG6输入内容:S10
说明:部分引擎支持$STRLEN()函数取字符串长度,不支持的用自定义计数或限制输入源(客户端输入框本身有字节上限)。
三、逐字符扫描检测特殊符号
对于需要严格限制字符集的场景(如行会名只允许中文+字母+数字),用循环或多次CHECKCONTAINS判断:
if
CHECKCONTAINSS10~
act
MESSAGEBOX不能包含~符号
GOTO@main
elsesay
if
CHECKCONTAINSS10`
act
MESSAGEBOX不能包含`符号
GOTO@main
elsesay
if
CHECKCONTAINSS10|
act
MESSAGEBOX不能包含|符号
GOTO@main
elsesay
if
CHECKCONTAINSS10<
act
MESSAGEBOX不能包含<符号
GOTO@main
elsesay
if
CHECKCONTAINSS10>
act
MESSAGEBOX不能包含>符号
GOTO@main
elsesay
if
CHECKCONTAINSS10&
act
MESSAGEBOX不能包含&符号
GOTO@main
elsesay
;全部通过才执行
act
GOTO@process
需要屏蔽的字符清单(按危害程度排序):
•|:部分版本脚本解析器把|当命令分隔符,注入后可执行额外指令
•<>:脚本标签语法符号,输入含<可能被误解析为标签跳转
•~:变量展开符号,某些引擎里~S10会展开为全局变量
•&:条件连接符,可能干扰#if解析
•'":SQL注入场景(如果后端用文本数据库且未转义)
•\r\n:换行注入,破坏脚本块结构
四、数字型输入的双重保险
即使弹的是@@InPutString,玩家也可能输入纯数字。如果需要数字,回调段里用EQUAL/NOTEQUAL+范围判断:
[@CallInPutString11]
if
EQUALS110
act
MESSAGEBOX不能为0
GOTO@main
elsesay
if
SMALLN111
act
MESSAGEBOX不能小于1
GOTO@main
elsesay
if
LARGEN119999
act
MESSAGEBOX不能超过9999
GOTO@main
elsesay
act
;S11已确认为合法数字字符串,N11为对应数值
SENDMSG6确认数值:N11
注意:@@InPutString的结果在S变量里,但引擎同时会尝试解析为数字存入同名N变量(如S11→N11)。如果输入含非数字字符,N11为0,可以用这个特性做"纯数字校验"——N11==0且S11不为"0"说明含字母。
五、数据库落盘前的转义处理
输入最终要写入文本文件或数据库时,必须做转义:
1.写文本文件(SAVEVAR):
变量内容含换行符会破坏文件格式。在写入前用REPLACE函数清除或替换危险字符:
CALCVARGLOBALZ1=$REPLACE(S10"|""")
CALCVARGLOBALZ1=$REPLACE(Z1"<""")
CALCVARGLOBALZ1=$REPLACE(Z1">""")
SAVEVARGLOBALZ1..\QuestDiary\数据文件\InputLog.txt
2.写DBC2000/Access:
通过脚本命令写入数据库的记录,字段长度限制要在脚本层提前拦截。比如HeroDB的Guild表Name字段varchar(20),脚本里用$STRLEN限制在20字符内,超长截断或拒绝。
六、行会名/角色名注册完整过滤示例
[@CallInPutString5]
;第一层:空值
if
EQUALS5
act
MESSAGEBOX行会名不能为空
GOTO@main
elsesay
;第二层:长度
if
LARGE$STRLEN(S5)16
act
MESSAGEBOX行会名最多16个字符
GOTO@main
elsesay
;第三层:非法字符
if
CHECKCONTAINSS5~
act
MESSAGEBOX不能包含~符号
GOTO@main
elsesay
if
CHECKCONTAINSS5<
act
MESSAGEBOX不能包含<符号
GOTO@main
elsesay
if
CHECKCONTAINSS5>
act
MESSAGEBOX不能包含>符号
GOTO@main
elsesay
if
CHECKCONTAINSS5|
act
MESSAGEBOX不能包含|符号
GOTO@main
elsesay
;第四层:重复检查
if
CHECKTEXTLIST..\QuestDiary\Guild\GuildNames.txtS5
act
MESSAGEBOX该行会名已被注册
GOTO@main
elsesay
;第五层:引擎内置过滤(自动跳@IsInFilterList,此处不用写)
;全部通过
act
ADDTEXTLIST..\QuestDiary\Guild\GuildNames.txtS5
SENDMSG6行会名[S5]注册成功
[@IsInFilterList]
act
MESSAGEBOX行会名含非法词汇,请重新输入
GOTO@main
七、M2过滤列表维护规范
过滤列表不是越长越好,维护原则:
•按功能分区:行会名过滤、聊天过滤、任务输入过滤分开建表(不同版本支持多个过滤列表文件)
•定期清理:过时的敏感词删掉,避免误拦正常输入
•测试流程:每次加新词条后,用测试号走一遍完整输入流程,确认不误伤
•备份:过滤列表文件改前复制一份.bak,改崩了能回滚
八、多引擎差异汇总
项目Hero引擎3K引擎GOM/GEE
回调段名[@CallInPutStringX][@InPutStringX][@InPutStringX]
过滤跳转段[@IsInFilterList][@MsgFilter][@MsgFilter]
过滤列表位置M2→列表信息→其他设置同左同左
变量存储SX+NXSX+NXSX+NX
CHECKCONTAINS支持支持支持
$STRLEN部分版本支持部分版本支持商业版支持
最大输入长度客户端限制约60字节同左同左
九、调试与日志
输入异常时排查步骤:
1.确认是否触发了[@IsInFilterList]→说明命中引擎过滤列表,去M2列表里查对应词条
2.没触发过滤但后续逻辑异常→在回调段第一行加SENDMSG6调试:S10,看实际写入内容
3.变量读出来是空的→检查回调段名是否拼对(Hero必须带Call)
4.中文变乱码→脚本文件存成UTF-8了,改ANSI
5.特殊符号没被拦住→CHECKCONTAINS的字符可能被引擎吃掉了,换成十六进制比较或升级引擎版本
十、完整防御纵深总结
玩家按键→客户端输入框(长度限制)→@@InPutStringX发包→引擎层过滤列表匹配(@IsInFilterList拦截)→写入S变量→回调段脚本校验(空值/长度/字符集/格式/重复)→转义处理→落盘(文本/DB)。五层防线,任意一层漏了还有下一层兜底。脚本层校验永远不能省——引擎过滤列表只管"有没有这个词",不管业务逻辑合不合法。

