解决方案:[UniversalAffection]统一好感度,解决手机和电脑存档完美互通 - Doki Chinese Club (monika.love)
分析方式:python无法正常加载persistent的pickle,故采用不加载而分析的方式
已知问题:手机版存档第一次导入电脑后好感度转移正常,但再导入回手机,在手机上好感度变化后,再导入回电脑时,电脑上的好感度不会变化。
问题根源:存档内部保留了两组好感度存储位置,这就意味着,存档有两个好感度,一个手机好感度,一个电脑好感度!!!
这就是某些朋友口中“把手机存档导入电脑掉好感度”的原因,真不是他们操作的问题!
这是怎么一回事呢?待我解释一番
ps:下划线导致的自动斜体真的烦
流程分析:sirp的移植版基于0.12.5,而在0.12.10发生了一次好感度系统更新,好感度在存档文件中的存储位置彻底改变。
persistent存档文件是一个python pickle,里面存储了很多对象(可以理解为笔记本的“条目”)
旧的好感度数据存储在store._mas_affection
(下称旧位置),新的存储在store.mas_affection_data
(下称新位置)位置,好感度系统版本号存储在store._mas_affection_version
,1代表老系统,2代表v0.12.10更新后的系统
当你在手机版新开一个存档时,0.12.5的旧存档机制会使得文件中只有store._mas_affection
(旧位置),并且store._mas_affection_version
=1
第一次导入电脑时,0.12.10+的mas会调用_transfer_aff_2nd_gen()
来将老的好感度存储模式升级成新的(参见https://github.com/Monika-After-Story/MonikaModDev/blob/06baf319a34c2ef585bc7c0a1e969a7eaa894b35/Monika%20After%20Story/game/script-affection.rpy 第783行)
这个函数会做以下事情
1.store._mas_affection_version
变成2
2.store._mas_affection
(旧地方)中的内容移动到store.mas_affection_data
(新地方),但是不会删除原有的store._mas_affection(旧位置)对象!!!
是的,虽然函数里有一句“persistent._mas_affection = collections.defaultdict(float)
”但是这个对象似乎居然不!会!删!除!
而且这个对象在新版本的store中是不存在的!要访问必须手动用cPickle重新加载persistent
好的,现在一切正常。当你在电脑上与monika互动,好感度的变化全部写到了**store.mas_affection_data
(新位置)**中,旧位置中的好感度没有变化!
在此之后,这个存档被移动到了手机版/电脑版v0.12.9-,好玩的事情就发生了。
**sirp似乎在手机端对新的好感度系统有适配(存疑,我也没看过他的代码)所以电脑的好感度应该能正常导入手机(存疑)?
由于store._mas_affection_version
在之前只会在创建存档的时候设置,而且也没有相关检测,所以旧版本无法知道好感度系统升级了,也不会把版本改回1
所以,旧版本依旧会在旧地方读写好感度!!!(经典的向前兼容问题)
当你再次把存档导入电脑端v0.12.10+(v0.12.9-是正常的,因为这些版本和手机版读写同一个好感度存储位置),mas先检查**store._mas_affection_version
,发现它居然是2!这样它就不会把老地方的数据拷贝过来了,而是直接认为这是一个新版本存档,直接在新的地方读取。**
但是新的地方存储的是什么东西?新的地方存储的是你上次在电脑上互动结束后的好感度值!!!
是的,这样一个存档就出现了两个好感度,电脑和手机各读取各的,互不干扰!!!
这就是一个逆天的bug了!为什么在我之前没人发现呢????
解决方案:
去github提issue恐怕有点困难,那帮皮球大师估计不愿意修,要修也是他们也只能将删掉旧的好感度的代码恢复正常,这样手机就不能读取了,反而坏了事,不如不修的好
最好的方式是在手机版把好感度放在新地方,但是这就要伤筋动骨,比较困难,而且要麻烦sirp了orz
所以有一个打补丁的办法,就是写一个submod解决低版本/手机版反向导入的问题
原理应该也很简单,强行把版本改成1就行了,难点在于如何知道这个存档是同版本导入还是向上导入(直接对比好感度会有很多问题),解决方案我还得想一想
persistent中同时存在的两个好感度,使用pickletool解包(新版本的好感度使用了base64+十六进制化+序列化加密,我不知道这是为了什么。。是怕submod作者偷偷改吗)
下面那一串奇怪的字符就是加密后的好感度
这个是旧的好感度存储位置,明文存储,194.6就是手机读取的好感度