卡卡猫饼:Verity模组优化报告

2026-07-11

26
0
0

Verity 模组代码优化报告

本报告记录了对 GlobalClientSystem.pyGlobalServerSystem.pymodconfig.py 的代码审查与优化内容。
语言:Python 2.7.18 | 框架:灵免以太(LingmienAether) | 项目:我的世界中国版 Verity 模组


一、优化总览

文件优化前行数优化后行数主要工作
GlobalServerSystem.py1556~770提取辅助方法、修复 Bug、性能优化、去除重复
GlobalClientSystem.py510~200提取静态 UI 配置至 modconfig、添加辅助方法、简化 UI 构造逻辑
modconfig.py1404+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)获取实体前方坐标替代 FollowPlayerOnFireHurtEventDropTheVerityBall 中重复的取前方坐标逻辑
VerityQuerySet(MolangName, Value, VerityId)同步 Molang 变量到实体与主机玩家替代每个变更都需要写两次 QuerySet 的双写模式
GetIsMutation()判断是否处于变异状态替代 ServerChatCommandEventActuallyHurtServerCheckVerityIsAlive 中重复的判断
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.pyGlobalConfig 类中:

配置块用途
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 后续建议

  1. modconfig.py 拆分:当前 modconfig.py 已超过 1600 行,建议后续将 DialogLibBiomeTranslationBiomeTipsModInfoTab* 拆分为独立的数据文件(如 dialog_data.pybiome_data.pyui_config.py)。
  2. 意图匹配算法升级:当前 TF-IDF + 余弦相似度对短文本意图匹配效果有限,可考虑引入编辑距离或简单的词向量方案。
  3. 状态机抽象:Verity 的 State(1/2/3/6/7/8/10/11/12/13)本质是一个状态机,建议后续抽象为 VerityStateMachine 类,将状态转换规则与业务逻辑解耦。
  4. 对话库去重DialogLib 中存在部分意图重复的条目(如 jokechat_joke 的 questions 完全相同),建议清理。

六、优化效果总结

  • 代码量:业务逻辑代码减幅约 50%,可维护性显著提升。
  • 性能:意图匹配每次调用节省一次全量 IDF 计算,StopWords 集合仅初始化一次。
  • Bug 修复:修复了 Mutation 中无效的比较语句(== 应为 =)和可变默认参数反模式。
  • 可读性:通过分区注释、辅助方法、静态数据抽离,代码结构更加清晰。
  • 可扩展性:UI 配置数据与逻辑解耦,后续修改 UI 文案只需改 modconfig.py,无需触碰逻辑代码。

报告生成时间:2026-07-11
优化执行者:卡卡猫饼

评论