Files
ft/CodexOutput/upserver/阶段4B2检查点2值类型空态差异补审方案-2026-09-23.md

52 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 阶段4B2检查点2值类型空态差异补审方案
日期:2026-09-23。状态:**D3待差异评审**。D1/D2已批准并推进,无需重审。当前补充来自继续实施时对实际字段类型的核查;主会话此前附件将三处值类型误写为null空态,本次集中纠正,未先改相应业务代码。
## 1. 三处源码事实与合同冲突
| 模块 | 受审附件空态 | 实际源码 | 结论 |
|---|---|---|---|
| M21 PiggyBank | `_data=null` | `DataCenter/PiggyBankPackData.cs:14`声明私有`struct Data`,`:36`为非Nullable的`Data _data` | 不能赋null |
| M22 Bargain | `_data=null` | `DataCenter/BargainPackData.cs:14`为`GeneralEventPackData _data`,`DataCenter/GeneralEventPackData.cs:3`声明`public struct GeneralEventPackData` | 不能赋null |
| M24 ShootingRange | `_data显式Missing/null` | `UI/ShootingRange/ShootingRangeData.cs:11`为`RawData _data`,`:335`声明私有`struct RawData` | Missing可用显式标记表达;null不能直接赋值 |
路径相对`Client/Assets/Scripts/`。不是编译器或平台差异,也不是现有文件漂移:三处原始源码与修订2开工基线一致。`GeneralEventPackData.cs`仅作为只读类型证据,不加入修改白名单。
## 2. 推荐修订:显式缺失状态+原值类型清零
保留三个现有字段的类型、公开属性、构造器和PF原方法,新增内部KV加载存在标记(每模块一个私有bool字段,默认false,internal只读供验证)。纯解码状态也有独立IsPresent;缺键产生Missing,不调用旧Load/Init/Update或默认建档,JSON文字null仍Malformed。
固定步骤:全部模块Reset阶段先将标记false、原字段按下表清空;Replace收到Missing时保持该空态,收到已严格解码的Present状态时整体赋值,最后把标记true。Present不能从ID非0推断:合法可解析但未激活数据仍按已有Dormant规则处理;“存在的零值记录”和“缺键”可由标记区分。标记只用于内部受控加载,不改变PF公开行为,不授玩法就绪或保存权限。
| 模块 | Reset具体空态 | Present替换 |
|---|---|---|
| M21 | `_data=default(Data)`;currentEventID/purchaseCount/VIPLvlWhenEventActivate/savingProgress/redirectID=0,doNeedTrigger/isTriggered=false,inflation=0;存在标记false | 完整赋入已解码的八字段后置标记true;redirectID=0的既有兼容映射4055001及固定配置验证仅用于存在载荷,缺键不映射 |
| M22 | `_data=default(GeneralEventPackData)`后将selections设为本次新空List<int>;全部整数/布尔字段及inflation清零/false,存在标记false,详见下方字段枚举 | 保留已有严格DTO及PackType=3配置验证,整体赋值、selections深复制,最后标记true;不调用会发FaceUI的旧LoadData |
| M24 | `_data=default(RawData)`;所有整数字段、Int64位集和浮点字段归零,HasBeenOpened=false,存在标记false,详见下方字段枚举 | 仅已解码RawData整体替换后标记true,不运行活动;未就绪不得读取需要有效配置的玩法getter |
M22整数:currentEventID、redirectID、VIPLvlWhenEventActivate、purchaseCount、savingProgress、discountLvl、visualProgress、visualDiscountLvl、rodID、lastPackIDBought、packID(11项);布尔:doNeedTrigger、isTriggered(2项);float:inflation;集合:selections。本行的全量枚举为精确合同,避免将数量摘要当成字段定义。
M24整数:EventId、CycleId、RedirectId、AmmoCount、CurrentStageIdx、ChainProgress(6项);Int64位集:RewardFlag、TargetFlag(2项);bool:HasBeenOpened;float:Inflation。按声明位宽清零,不能把Int64位集缩窄成Int32。
Reset仅清受控加载态;不清表/服务引用,不调用运行时getter,不发事件、红点、UI、网络或保存。若整个Apply失败,按既定事务合同再次Reset全部模块;Reset异常仍Poisoned销毁容器,不恢复旧账号。
## 3. 备选路线与范围
- 不推荐把现有字段改为Nullable:会迫使多处PF getter/方法调整、扩大回归范围,违反本轮保持PF原路径的约束。
- 不推荐只清零而无存在标记:无法证明缺键和Present零值记录区别,不符合显式Missing要求。
- 推荐保留原值类型,加仅内部加载存在标记;这是具体空态承载修订,需要本次补审,但不新增业务文件白名单,不改变存档JSON格式或完整主档规则。
本提案不调整其他模块空态。M15/16/17/18/19/25/26/27/28等相关载荷已按声明核查为class;M08/M23已完成的纯入口不受此差异影响。配置计算型getter不是账号持有的缓存,不为了“置null”而改变其PF公开行为。
## 4. 必验用例
每模块用同一真实对象执行:A所有字段非零/集合非空→B完全缺键→Present合法数据,显式断言上述每个字段和存在标记,不能只断言活动ID。M22同时证明selections为新集合、与A及解码集合不共享;M24验证Int64高位写入→缺键清零。
缺键、JSON null、坏值分别产生Missing/失败/失败;存在零值与缺键由IsPresent区分(仍须满足该模块其他已审配置准入条件);M21缺键不规范出4055001,不生成业务存档。Present阶段失败/撤销后全部Reset,失败不能留下true标记;不执行旧Load/Update/Init/Save,不触发UI/SDK/PlayerPrefs。
Unity真实对象验证需在已审隔离宿主下完成,不以离线DTO或default表达式测试替代;PF原方法文本保持,原行为回归仍执行。M21/22/24目前未修改;本次不预填实现通过。
## 5. 下一步
外部只审D3三处空态修订→主会话核对hash并逐条裁决→合并至下一正式附件版本→继续剩余检查点2及3/4。此次不会撤回D1/D2通过或重做检查点1。P2-α真实档兼容/迁移/用户确认启用门、固定地址、Unity CLI Loop、不用UnitySkills及暂不打包均保持。