Verity 模组代码优化报告
本报告记录了对
GlobalClientSystem.py、GlobalServerSystem.py与modconfig.py的代码审查与优化内容。
语言:Python 2.7.18 | 框架:灵免以太(LingmienAether) | 项目:我的世界中国版 Verity 模组
一、优化总览
| 文件 | 优化前行数 | 优化后行数 | 主要工作 |
|---|---|---|---|
| GlobalServerSystem.py | 1556 | ~770 | 提取辅助方法、修复 Bug、性能优化、去除重复 |
| GlobalClientSystem.py | 510 | ~200 | 提取静态 UI 配置至 modconfig、添加辅助方法、简化 UI 构造逻辑 |
| modconfig.py | 1404 | +200 | 新增 5 个静态 UI 配置数据块(原本硬编码在客户端逻辑中) |
总体代码量从约 3470 行精简到约 2970 行(含新增配置数据),逻辑代码本身减幅约 50%。所有改动均遵循 Python 2.7 语法(使用 .format(),未使用 f-string),新变量采用大驼峰命名。
二、GlobalServerSystem.py 优化详情
2.1 新增辅助方法(去除重复代码)
以下逻辑原本散落在多个事件回调中重复书写,现统一抽离为辅助方法:
| 方法 | 作用 | 替代了哪些重复代码 |
|---|---|---|
GetVerityData() | 读取 VerityData 存档字典 | 在 20+ 处调用替代 LASystem.GetModRenderAttrByKey(levelId, 'VerityData') or {} |
SaveVerityData(VerityData) | 保存 VerityData 存档 | 替代多处 LASystem.SetModRenderAttrByKey(levelId, 'VerityData', VerityData) |
BuildSoundData(SoundName, Volume) | 构建标准单音效数据字典 | 替代约 10 处重复的 {0.1: [{'SoundName': ..., 'Volume': ..., 'Pitch': 1, 'Loop': False, 'EntityIdList': serverApi.GetPlayerList()}]} |
GetFrontPos(EntityId, Distance) | 获取实体前方坐标 | 替代 FollowPlayer、OnFireHurtEvent、DropTheVerityBall 中重复的取前方坐标逻辑 |
VerityQuerySet(MolangName, Value, VerityId) | 同步 Molang 变量到实体与主机玩家 | 替代每个变更都需要写两次 QuerySet 的双写模式 |
GetIsMutation() | 判断是否处于变异状态 | 替代 ServerChat、CommandEvent、ActuallyHurtServer、CheckVerityIsAlive 中重复的判断 |
GetSettingData() | 获取设置数据(带默认值) | 替代硬编码 or {'JumpScareMode': '全部', ...} |
2.2 性能优化
2.2.1 IdfDict 预计算
问题:原 MatchIntent 方法每次被调用(每次玩家聊天)都会通过 BuildIdfDict 重新遍历整个 DialogLib(约 230 条记录)计算 IDF 字典。这是 O(N×M) 的重复计算。
优化:在 __init__ 中预计算并存储:
self.IdfDict = self.BuildIdfDict(self.DialogLib)
MatchIntent 直接使用 self.IdfDict,每次聊天节省一次全量遍历。
2.2.2 StopWords 提升为类属性
问题:原 MatchIntent 方法内部每次调用都重新构造一个包含 100+ 元素的 StopWords 集合。
优化:将 StopWords 提升为类属性 VerityServerSystem.StopWords,仅初始化一次。
2.2.3 CatchPlayer 中重复 Timer 合并
问题:原 CatchPlayer 中连续 5 次写 compTimer.AddTimer(0.25 * i, lambda: self.VerityQuerySet('verity_boss_material', x, VerityBossId)),硬编码重复 5 次。
优化:改为循环:
for Index in range(1, 6):
compTimer.AddTimer(0.25 * Index, lambda Val=float((Index + 1) % 2): self.VerityQuerySet('verity_boss_material', Val, VerityBossId))
2.3 Bug 修复
2.3.1 Mutation 方法中的赋值错误
原代码(无效语句):
VerityData['State'] == 10 # 这是比较,不是赋值,没有任何效果
修复:
VerityData['State'] = 10
2.3.2 可变默认参数
原代码(Python 经典反模式,可变默认参数会在多次调用间共享状态):
def SendVerityMsg(self, PlayerId, Content, SoundData=None, StateData=[1, 2], ...):
修复:
def SendVerityMsg(self, PlayerId, Content, SoundData=None, StateData=None, ...):
if StateData is None:
StateData = [1, 2]
2.4 代码简化
| 简化点 | 做法 |
|---|---|
BuildIdfDict / GetTfIdfVec | 使用 dict comprehension 替代 for 循环构造字典 |
HandleFlyPlayer / ExtractTpTarget | 使用 any() + 生成器替代多层 for + if 嵌套 |
ContextText 拼接 | 使用 ' '.join(generator) 替代循环 += |
HandleTpPlayer | 使用 DimMap 字典替代多层 if/elif 判断维度 |
GetTheVerityBall | 删除未使用的 SoundData 变量 |
IntentHandlers 调度表 | 使用字典替代长串 if/elif 匹配意图处理器 |
2.5 代码组织
在文件中加入分区注释,使结构清晰:
# ===================== 辅助方法 =====================
# ===================== 事件监听 =====================
# ===================== Verity核心逻辑 =====================
# ===================== 对话系统 =====================
# ===================== 计算器 =====================
三、GlobalClientSystem.py 优化详情
3.1 提取静态 UI 配置到 modconfig.py(核心优化)
问题:原 OpenModInfo 方法长达 380+ 行,其中 360+ 行是硬编码的 UI 配置数据(按钮、列表、说明文本等),与逻辑代码混杂,极难维护。
优化:将所有静态 UI 数据抽取到 modconfig.py 的 GlobalConfig 类中:
| 配置块 | 用途 |
|---|---|
ModInfoTabGeneral | 通用设置 tab 的内容(反馈信息、恐吓等级、唤醒词、追杀破坏方块、追杀凝视) |
ModInfoTabFunction | 功能说明 tab 的内容(保护功能、对话功能两个 list_button) |
ModInfoTabDebug | 开发者调试 tab 的内容(VerityId、InitTick、Affinity、IsItem、IsMutation) |
ModInfoTabMoreMod | 更多模组 tab 的内容(模组推荐列表) |
StoreModIdData | 模组商店 ID 映射字典 |
OpenModInfo 方法本身从 380+ 行精简到约 70 行,只负责动态回调绑定和 UI 表单组装。
3.2 新增辅助方法
| 方法 | 作用 |
|---|---|
GetVerityData() | 读取 VerityData 存档字典(与服务端对称) |
GetSettingData() | 读取 VeritySettingData 存档字典 |
ResetPlayerRenderByData(RenderData) | 根据缓存的 LARenderData 重置玩家渲染,替代直接展开 5 个字段 |
3.3 InitQueryList 提升为类属性
问题:原 ClientLoading 中硬编码 4 个 Molang 变量名循环初始化。
优化:提升为类属性 InitQueryList,便于后续扩展:
InitQueryList = ['verity_animation', 'verity_talk', 'verity_boss_material', 'verity_boss_state']
3.4 OpenStore 简化
问题:原方法在内部硬编码 ModIdData 字典,且使用 try/except KeyError 处理找不到的情况。
优化:使用 GlobalConfig.StoreModIdData.get(ModName) 显式判空,并给出明确的"未找到该模组"提示,避免依赖异常捕获控制流程。
3.5 OpenModInfo 中动态绑定 FunctionInstance
由于 FunctionInstance 必须绑定到实例方法(self.RenderToVerityBoss 等),这部分无法完全静态化。采用的做法是:
- 静态数据中不包含
FunctionInstance字段 OpenModInfo运行时通过循环为input_button类型的项绑定self.EditDebugData,为list_button中的项绑定self.OpenStore- 调试按钮组(DebugButtons)单独构造,因为其结构较特殊
这样既保留了静态数据的可维护性,又保证了回调绑定的正确性。
3.6 代码组织
加入分区注释:
# ===================== 辅助方法 =====================
# ===================== 事件监听 =====================
# ===================== 追杀玩家表现 =====================
# ===================== 调试功能 =====================
# ===================== 模组说明书 =====================
四、modconfig.py 优化详情
在 GlobalConfig 类中新增 5 个静态数据块(详见 3.1 节)。
将原本散落在客户端逻辑中的多行字符串('''...''')统一改为 \n 转义符,避免多行字符串在数据结构中造成缩进混乱。
五、未改动项与后续建议
5.1 未改动项
config.py:基础配置文件,结构清晰,无需优化。ServerLingmienAether.py/ClientLingmienAether.py:补全库(框架引擎接口),不属于业务代码。EventApi.py:装饰器定义,无优化空间。
5.2 后续建议
- modconfig.py 拆分:当前
modconfig.py已超过 1600 行,建议后续将DialogLib、BiomeTranslation、BiomeTips、ModInfoTab*拆分为独立的数据文件(如dialog_data.py、biome_data.py、ui_config.py)。 - 意图匹配算法升级:当前 TF-IDF + 余弦相似度对短文本意图匹配效果有限,可考虑引入编辑距离或简单的词向量方案。
- 状态机抽象:Verity 的 State(1/2/3/6/7/8/10/11/12/13)本质是一个状态机,建议后续抽象为
VerityStateMachine类,将状态转换规则与业务逻辑解耦。 - 对话库去重:
DialogLib中存在部分意图重复的条目(如joke与chat_joke的 questions 完全相同),建议清理。
六、优化效果总结
- 代码量:业务逻辑代码减幅约 50%,可维护性显著提升。
- 性能:意图匹配每次调用节省一次全量 IDF 计算,StopWords 集合仅初始化一次。
- Bug 修复:修复了 Mutation 中无效的比较语句(
==应为=)和可变默认参数反模式。 - 可读性:通过分区注释、辅助方法、静态数据抽离,代码结构更加清晰。
- 可扩展性:UI 配置数据与逻辑解耦,后续修改 UI 文案只需改
modconfig.py,无需触碰逻辑代码。
报告生成时间:2026-07-11
优化执行者:卡卡猫饼