只要你等待的足够久,你想要的功能就会从开源社区自己长出来。 —— tg大佬·但忘了·是谁。
跳转:messagepack_csharp_unpacker.py
起因
在20-21年我尝试写了一个《河洛群侠传》的存档修改器,但因为当时水平太差,连格式都分析不出来,最后只能将河洛存读档的代码复制出来直接用,最后也只写出一个解包器,修改器不了了之。
时隔多年重新搜索,竟然发现有大佬写出了转换工具,而且最后更新时间在一个月前
令人感慨,果然只要等待的时间够久,就一定有人能将你的想法实现(笑
于是拿大佬的代码改改,写(zu)出(zhuang)来(chu)了给河洛群侠传用的存档转换器。
存档格式
河洛群侠传有两种存档格式:
- 纯文本格式的存档,header为”TitleSave”,是早期使用的存档格式
- 使用MessagePack-CSharp打包的存档,header为”HELUO_1_0”或”HELUO_1_1”,是新版本的存档格式
第一种格式是明文存储,修改起来很方便,网络上也已经有了很成熟的修改器
但并没有第二种格式的修改器,通常的解决办法是修改System.String Heluo.GameConfig::SaveDataVersion
为”TitleSave”,使新版游戏以旧版格式存档,以便修改。这种方法需要反编译Assembly-CSharp.dll,难度不大。
新版本存档转换为旧版本格式
我希望有不破坏游戏代码本身的方法,所以在寻求这种方式。
格式
旧版本格式的存档格式非常简单
1 | 第一行: TitleSave,[difficulty] |
新版本格式则是
“HELUO_1_1” + HELUO_1_1
+ GameData
其中后两个数据是序列化后的自定义类,而GameData中就包含角色属性、物品等数据。只要将它反序列化,就能修改了。
序列化的方法为
1 | LZ4MessagePackSerializer.Serialize<Header_HELUO_1_1>(memoryStream2, header_HELUO_1_2, HeluoResolver.Instance); |
原来卡住的地方
我希望用python的msgpack和lz4包对游戏存档进行解码,再转换为旧版本格式。
但MessagePack-CSharp的LZ4MessagePackSerializer算法看不懂,再加上逆向不熟练,代码追踪时总是跟丢,多次尝试后还是放弃了。最后解决的办法是将从游戏剥离出的存读档代码和1.x版本的MessagePack-CSharp一起编译成了dll。
messagepack_csharp_unpacker.py
在多年之后,终于看到了LZ4MessagePackSerializer.Deserialize的python实现,泪目
大佬的代码:https://gist.github.com/t-wy/778123fedd15513e4626ad27f07cb690
看完代码之后才发现原来结构这么简单(汗
于是改了一下,河群的格式转换就成了:(update 10/22/2024 更正time_format函数的输出,修复TimeTokens的Span和Time项的数据转换)
1 | import sys |
说点别的,没有逻辑
没想到三年前没做成的事情会在这个时候重新跳出来。回想一下三年前,才发现这几年过去了,自己竟然一点长进也没有(叹气
有人说过,和平庸的自己和解,是绝大多数人必须经历的事。对我来说,虽然很早就意识到了,但直到现在也不愿承认。或许今后我还是会一直挣扎吧。
从以前,到现在这个已不再青春的年纪,直到本就不强的能力越来越衰弱,最终被这个世界抛弃的未来,或许和自己闹别扭,想要在一地废品中找到属于自己独有的、能拿来吹牛逼的优势这件事终究还是会一直缠着我吧。
什么眼高手低的goushi人生。