Files
ft/CodexOutput/upserver/B3BatchMigration/M2/C2d-活动原流程核减.py.txt
Liubing\LB 6813da149a feat(upserver): 保存M2客户端KV迁移至本人统计写检查点
保存独立KV用户服务、固定会话存档与原业务接线,以及C3d资料缓存和C3e本人统计写。
保留原PF/AGG路线、业务公式和时序;榜单读取、好友资料、公告、匹配及首场景闸仍待完成。

验证:ServiceHost两条件各33组646断言;Unity CLI Loop编译0错误269警告。
包含相关方案、评审裁决、测试及状态文档。未操作服务器、正式账号或打包。
2026-09-30 19:19:05 +08:00

53 lines
3.8 KiB
Plaintext

from pathlib import Path
m=Path('CodexOutput/upserver/B3BatchMigration/M2')
# Reuse only the previously audited helper definitions, never replay prior edits.
exec((m/'C2d-按核证基线核减.py.txt').read_text(encoding='utf-8-sig').split('# All ten source bodies')[0])
def read(f):return (root/f).read_text(encoding='utf-8-sig')
def replace(f,a,b):
s=read(f); assert s.count(a)==1,(f,a); write(f,s.replace(a,b,1))
for f,klass in [('Activity/Data/EventDataRepository.cs','EventDataRepository'),('Activity/Services/EventTokenService.cs','EventTokenService')]:
s=original(f)
start=s.index('\n {',s.index('public class '+klass))+len('\n {')
s=s[:start]+'\n private readonly game.PlayerDataStorage.IPlayerSaveStore store;\n public '+klass+'(game.PlayerDataStorage.IPlayerSaveStore store)\n { this.store = store ?? throw new ArgumentNullException(nameof(store)); }\n'+s[start:]
s=s.replace('PlayFabMgr.Instance?.GetLocalData','PlayFabMgr.Instance.GetLocalData').replace('PlayFabMgr.Instance?.UpdateUserDataValue','PlayFabMgr.Instance.UpdateUserDataValue')
write(f,storage(s,'store'))
# Retain current store bindings and session checks. Restore only original parsing behavior.
for f in ['DataCenter/TotalRechargeManager.cs','MatchGame/MatchGameManager.cs','MiniBP/MiniBattlePassDataProvider.cs','EventLuckGame/EventLuckyGameModel.cs','EventWelcomeBack/EventWelcomeBackManager.cs','UI/AdWheel/AdWheelManager.cs','UI/OfferSweep/OfferSweepManager.cs','UI/JigsawPuzzle/JigsawPuzzleManager.cs']:
old=original(f); current=read(f)
# These files have only storage wiring + the inspected parsing changes; keep the current binding.
binding=' readonly game.PlayerDataStorage.IPlayerSaveStore saveStore = GContext.container.Resolve<game.PlayerDataStorage.IPlayerSaveStore>();\n\n'
assert current.count(binding)==1,f
prefix=current.split(binding)[0]
# Locate class opening in original without relying on line endings/BOM.
anchor='\n'.join(prefix.splitlines()[-2:])+'\n'
at=old.index(anchor)+len(anchor)
s=old[:at]+binding+old[at:]
s=storage(s,'saveStore')
if f=='MiniBP/MiniBattlePassDataProvider.cs':
s=s.replace(' public MiniBattlePassRecord GetMiniBattlePassRecord(string key)\n {',' public MiniBattlePassRecord GetMiniBattlePassRecord(string key)\n {\n if (!saveStore.IsCurrent) throw new System.InvalidOperationException("Expired battle pass session.");')
write(f,s)
f='Event/AEventDataManager.cs'
old=original(f);s=read(f)
a=s.index(' var read = SaveStore.Read(typeof(T).Name);')
b=s.index('\n }',a)
oa=old.index(' var dataStr = PlayFabMgr.Instance.GetLocalData(typeof(T).Name);')
ob=old.index('\n }',oa)
write(f,s[:a]+storage(old[oa:ob],'SaveStore')+s[b:])
# Exact original archive branches, including the old null behavior; retain async session checks.
for f in ['DataCenter/FishingEventData_OneOne.cs','DataCenter/FishingEventData_OneTwo.cs']:
write(f,storage(original(f),'playerSaveStore'))
f='DataCenter/FishingEvent_PVPData.cs';s=read(f);old=original(f)
for method in ['public void SoloCheckClaimReward()','public void InitSoloData(FishingEvent t)']:
a=s.index(method);b=s.index('\n public ',a+len(method))
oa=old.index(method);ob=old.index('\n public ',oa+len(method))
s=s[:a]+storage(old[oa:ob],'playerSaveStore')+s[b:]
write(f,s)
f='DataCenter/DataCenter.FishingEventData.cs';s=read(f)
a=s.index(' T ReadEventArchive<T>');b=s.index(' private cfg.Tables _tables;',a)
s=s[:a]+s[b:]
for line in [' List<Exception> errors = null;\n',' (errors ??= new List<Exception>()).Add(e);\n',' if (errors != null) throw new AggregateException("Activity refresh did not complete.", errors);\n']:
assert s.count(line)==1,line
s=s.replace(line,'',1)
write(f,s)
print('Restored original activity flows; retained store wiring and existing session isolation.')