№ · 数据规范 CH.06.22
主页 · 💾 数据规范 · tongfu-data-structure-and-table-spec

tongfu-data-structure-and-table-spec

📅 2026-06-22 · 📦 13.7 KB · 💾 数据规范 · 📝 MD 文档 🏷️ Buff🏷️ 规范🏷️ 设计

在无服务器的纯本地化 Web 端游戏架构中,我们推荐将数据结构划分为**“只读静态配置表(Static Metadata)”和“读写动态状态表(Dynamic State)”**。

虽然游戏运行在浏览器本地(LocalStorage/IndexedDB),但依然需要按照关系型数据库的设计思想进行 schema 规范化,以便于前端代码的数据检索、深拷贝与状态重置。

以下是《同福客栈》全局账户、成就系统、单周目存档以及 Buff 运行态的完整数据结构与表格设计方案。

《同福客栈》数据结构与表格设计方案 (JSON / TypeScript 规范)

一、 存档与配置关系图 (Data Architecture Map)

在前端运行态中,静态配置在游戏初始化时一次性加载(通常为只读 JSON),动态数据在游戏运行中实时修改并定期序列化写入本地存储。

静态配置表 (Static Configs - 只读) 动态数据表 (Dynamic States - 读写) ┌────────────────────────────────┐ ┌──────────────────────────────────┐ │ 1. StaticAchievementConfig │ │ 3. GlobalProfile │ │ (成就定义表 - 静态JSON) │ ◄──────────│ (全局账号数据 - LocalStorage) │ ├────────────────────────────────┤ ├──────────────────────────────────┤ │ 2. StaticBuffConfig │ │ 4. PlaythroughSaveSlot │ │ (Buff定义表 - 静态JSON) │ ◄──────────│ (单局存档槽位 - LocalStorage) │ └────────────────────────────────┘ └──────────────────────────────────┘ │ ▼ 包含 ┌──────────────────────────────────┐ │ - StaffState (员工状态) │ │ - RuntimeBuff (运行时Buff实例) │ │ - PlaythroughCounters (单局计数器)│ └──────────────────────────────────┘

二、 全局数据模型设计 (Global Data Schema)

2.1 全局账户数据表 (GlobalProfile)

  • 存储 Key:tongfu_global_profile
  • 用途:记录跨周目不重置的玩家全局数据(阅历、已解锁成就、永久特权)。

| 字段名 (Field) | 数据类型 (Type) | 必填 | 默认值 | 说明 | | :--------------------- | :--------------- | :-: | :--: | :-------------------------- | | legacyPoints | Integer | 是 | 0 | 全局可支配的“江湖阅历”点数余额 | | unlockedAchievements | Array<String> | 是 | [] | 已解锁的成就 ID 数组 (关联成就配置表) | | purchasedLegacies | Array<String> | 是 | [] | 永久解锁的特权 ID 数组 | | globalCounters | Object | 是 | {} | 跨周目累积计数器,K-V 结构(见下文 2.2 示例) | | lastSavedAt | Long (Timestamp) | 是 | - | 上次保存时间戳 | | signature | String | 是 | - | 数字签名,用于防篡改校验 |

📝 账户全局计数器 (globalCounters) K-V 映射规范:

用于记录如“累计赚取100w两银子”等跨周目成就。

  • silver_gained_total: 历史累计获得银两数
  • brawls_prevented_total: 历史累计制止斗殴次数
  • fines_paid_total: 历史累计缴纳罚款次数
  • playthroughs_completed: 历史累计通关周目数

2.2 静态成就配置表 (StaticAchievementConfig)

  • 存储介质:静态资源包 configs/achievements.json (只读)
  • 用途:定义所有成就的达成判定条件与奖励。

| 字段名 (Field) | 数据类型 (Type) | 必填 | 说明 | | :--------------- | :---------------- | :-: | :------------------------------------------------------------- | | id | String | 是 | 唯一主键(如 ACH_MON_100W) | | name | String | 是 | 成就展示名称(如“富甲关中”) | | desc | String | 是 | 成就达成说明(描述文案) | | category | Enum | 是 | 判定模式:CUMULATIVE (累积型) / THRESHOLD (阈值型) / SPECIAL (特殊触发) | | triggerEvent | String | 是 | 绑定的事件总线事件(如 EVENT_SILVER_CHANGE) | | conditionParam | String | 是 | 判定所需的数值字段(对应 globalCountersPlaythroughCounters 中的 key) | | targetValue | Integer | 是 | 达标目标数值(如 1000000) | | rewardPoints | Integer | 是 | 奖励的江湖阅历点数 | | unlockRewardId | String (Nullable) | 否 | 达成后额外解锁的道具/菜谱/挂饰 ID |

三、 单周目存档模型设计 (Playthrough Data Schema)

每个存档槽位作为一个整体,序列化为 JSON 字符串存储在 LocalStorage 中。

  • 存储 Key:tongfu_save_slot_1 / tongfu_save_slot_2 / tongfu_save_slot_3

3.1 核心槽位表 (PlaythroughSaveSlot)

| 字段名 (Field) | 数据类型 (Type) | 必填 | 默认值 | 说明 | | :---------------- | :------------------- | :-: | :---------------: | :------------------------- | | slotId | Integer | 是 | - | 槽位 ID (1-3) | | currentDay | Integer | 是 | 1 | 当前经营天数 | | currentHour | Integer | 是 | 6 | 当前游戏小时(早 6 点开盘 - 晚 22 点打烊) | | gameStage | Enum | 是 | NORMAL_BUSINESS | 对应状态机中的九大客栈经营状态 | | silver | Double | 是 | 100.0 | 当前手头持有的银两余额 | | healthScore | Integer | 是 | 80 | 当前客栈综合健康分 (0-100) | | cleanliness | Double | 是 | 80.0 | 运行时环境清洁度 (0-100) | | security | Double | 是 | 70.0 | 运行时安防值守值 (0-100) | | reputation | Double | 是 | 50.0 | 运行时口碑与声望 (0-100) | | negativePr | Double | 是 | 0.0 | 运行时舆论负面值 (0-100) | | ingredientStock | Double | 是 | 3.0 | 食材充足天数 (单位: 天) | | ingredientFresh | Double | 是 | 90.0 | 库存食材平均新鲜度 (0-100) | | staffs | Array<StaffState> | 是 | [] | 运行时员工数据表(见 3.2) | | runtimeBuffs | Array<RuntimeBuff> | 是 | [] | 当前客栈全局挂载的活动 Buff 列表(见四) | | counters | Object | 是 | - | 单周目运行时计数器表(见 3.3) | | signature | String | 是 | - | 单槽位防篡改签名 |

3.2 员工运行时状态表 (StaffState)

嵌套在 PlaythroughSaveSlot.staffs 数组中。

| 字段名 (Field) | 数据类型 (Type) | 必填 | 默认值 | 说明 | | :----------- | :------------------- | :-: | :-----: | :----------------------------------------------- | | staffId | String | 是 | - | 员工唯一 ID (如 STAFF_LBA) | | name | String | 是 | - | 员工名称(如“白展堂”) | | job | Enum | 是 | - | 岗位:COOK (厨子), WAITER (跑堂), ACCOUNTANT (账房) | | mood | Double | 是 | 100.0 | 运行时心情值 (0-100) | | isOnDuty | Boolean | 是 | true | 当前是否在岗(轮班状态) | | staffBuffs | Array<RuntimeBuff> | 是 | [] | 挂载在该员工身上的个人 Buff 列表 |

3.3 单周目专用计数器表 (PlaythroughCounters)

嵌套在 PlaythroughSaveSlot.counters 中。周目结束时,部分数据累加至全局,随后本表清空。

| 字段名 (Field) | 数据类型 (Type) | 必填 | 默认值 | 说明 | | :------------------------ | :---------- | :-: | :---: | :----------------------- | | silver_gained_run | Double | 是 | 0.0 | 本周目累计赚取的银两 | | thieves_caught_run | Integer | 是 | 0 | 本周目累计抓住小偷次数 | | consecutive_clean_days | Integer | 是 | 0 | 清洁度连续大于 80 的天数(不满足则重置) | | consecutive_guo_mood_90 | Integer | 是 | 0 | 郭芙蓉心情连续大于 90 的天数(用于成就判定) | | fines_paid_run | Double | 是 | 0.0 | 本周目累计缴纳的罚款 | | pr_crisis_triggered | Integer | 是 | 0 | 本周目触发食物中毒/舆论危机的次数 |

四、 Buff 运行态数据结构 (Runtime Buff Schema)

Buff 分为“配置态”和“运行态”。运行态实例包含时间刻、来源等动态信息,存在于客栈全局或员工状态中。

4.1 运行时 Buff 实例结构 (RuntimeBuff)

| 字段名 (Field) | 数据类型 (Type) | 必填 | 默认值 | 说明 | | :------------------ | :-------------- | :-: | :------: | :----------------------------------------------------- | | instanceId | String | 是 | - | 运行时实例 ID(生成随机 UUID 防止堆叠混淆) | | configId | String | 是 | - | 关联的配置 ID (如 BUFF_INN_SAN_CRISIS) | | tags | Array<String> | 是 | [] | 继承并持有的系统标签(如 ["#SanitationCrisis"]) | | durationRemaining | Double | 是 | -1 | 剩余游戏小时数。-1 代表永久挂载,依靠条件卸载 | | sourceType | Enum | 是 | SYSTEM | 来源类型:SYSTEM (数值触发) / EVENT (随机事件) / STAFF (员工技能) | | modifiers | Array<Object> | 是 | [] | 动态属性修饰符快照 |

📝 modifiers 核心属性修饰器数据规范:

[ { "targetAttribute": "cleanliness_decay_rate", "calcType": "MULTIPLY", "value": 0.5 }, { "targetAttribute": "security_recovery_rate", "calcType": "ADD", "value": 6.0 } ]

五、 数据流动示例:事件触发与成就解锁 (Data Flow)

以下展示当跑堂(老白)点住小偷时,各数据表字段的级联变动过程,帮助开发人员理清状态维护逻辑:

  1. 业务系统触发捕盗事件
  • 派发事件 GameEventBus.emit('EVENT_THIEF_CAUGHT', { count: 1 }) │ ▼
  1. 单局数据更新
  • playthrough_slot_1.counters.thieves_caught_run 增加 1 (单局计数器) │ ▼
  1. 全局数据更新
  • global_profile.global_counters.thieves_caught_total 增加 1 (全局计数器) │ ▼
  1. 成就系统检查
  • 遍历 StaticAchievementConfig,发现绑定事件 EVENT_THIEF_CAUGHT 的成就: ID: ACH_LBA_DOU (盗圣在此), 目标值: 100
  • 检查 global_profile.unlockedAchievements 是否已存在该 ID │ ├─► [已存在] ──────► 结束数据流 │ └─► [未存在] ──────► 执行 5. │ ▼
  1. 达成解锁
  • global_profile.unlockedAchievements 压入 'ACH_LBA_DOU'
  • global_profile.legacyPoints 增加该成就对应奖励 +150
  • 使用新数据对 global_profile 生成新签名 signature
  • 保存回浏览器 LocalStorage,派发弹窗UI通知。