Files
dc-docs/output/feishu-docs/L6K3wxI54iLqBEkyD5zcWNxFn1g.md
T
2026-06-23 14:43:31 +08:00

98 lines
12 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.
# L6K3wxI54iLqBEkyD5zcWNxFn1g
Source: https://dianchukeji.feishu.cn/wiki/L6K3wxI54iLqBEkyD5zcWNxFn1g
# 一.工作内容概述
- 接入腾讯云 CloudBase,作为当前阶段的云存储方案,用于推进账号存档、资源同步和真机联调。
- 对 save service 进行了重构,支持 memory / douyin / cloudbase 多种存储后端切换,并补充 CloudBase 字段映射、环境配置、接口校验和 session TTL 清理等能力。
- 对关卡 Session 机制进行了异步化调整,将普通关、每日挑战、生存模式改为先展示棋盘、后台启动 session,减少网络请求对进入关卡体验的影响。
- 对体力、金币、广告奖励、生存模式结算等资源变动路径进行了审查和修复,尽量让云端模式下的关键资源变化统一走服务端处理,减少客户端直接修改资源带来的风险。
# 二.云存档服务重构与 CloudBase 接入
由于抖音云存储仍处于审核阶段,当前项目暂时无法直接使用抖音官方云存储能力。为了不影响后续云端存档、账号资源同步和真机联调,本次先接入腾讯云 CloudBase,作为当前阶段可用的云存储方案。
本次接入不只是替换一个存储接口,还整理了存储后端结构,包括账号存档读写、字段映射统一、环境配置、存储后端切换,以及 session 过期清理能力。
## 存储后端改为可插拔结构
本次重构新增了 cloudbaseStore.js,并将存储层整理为多后端结构。目前支持三种存储方式:
- memory:用于本地开发调试,服务重启后数据会丢失;
- douyin:预留给抖音官方云存储能力;
- cloudbase:当前阶段实际使用的云存储方案。
后端通过 STORAGE_BACKEND 环境变量选择实际使用哪一种存储实现。这样业务逻辑不需要关心底层具体使用哪个存储平台,只需要通过统一的 store 接口读写存档。
这种结构的好处是比较明显的。当前阶段可以先使用 CloudBase 推进开发和验证;后续如果抖音云存储审核通过,可以再接入 douyin 存储;如果 CloudBase 使用稳定,也可以继续作为正式存储方案保留。整体上不会把项目存档逻辑强绑定到某一个平台。
## CloudBase 配置与字段映射修复
为了让 CloudBase 能够在生产环境中使用,本次在 config.js 中补充了 CloudBase 相关环境变量配置,并在 store/index.js 中按环境动态选择存储后端。
同时修复了 CloudBase 存档读取时的字段映射问题。之前存在字段名不一致的情况,可能导致“写入成功,但读取时取不到正确数据”。例如同一类字段在不同存储后端中命名不统一,就会让读取逻辑需要额外做转换,后续也更容易出错。
本次将 CloudBase 存储字段统一为 openId、saveKey、revision 等格式,尽量与原有 douyin 存储保持一致。这样后续维护时,不需要在不同存储后端之间写大量额外适配逻辑,也能降低读取、回写、同步时出现字段不一致问题的概率。
## 存档接口加固
除了接入 CloudBase,本次也对 save service 的接口做了一些加固处理,包括统一错误处理、参数校验等。
云端存档一旦接入正式流程,就不只是简单的数据读写,还会影响体力、金币、道具、皮肤等账号资源。因此接口层需要尽量避免参数缺失、异常未捕获、字段不统一等问题。
同时,原先部分逻辑拆得比较散,本次也对相关结构做了整理,让存档服务的入口、配置和实际存储实现之间的关系更清晰。
## Session 过期清理接入 CloudBase TTL
除了账号存档外,本次也将 session 过期清理放到 CloudBase 接入方案中一并处理。
当前 session 机制用于记录玩家每一局游戏的开始状态和结算凭证。普通关、双鸡、每日挑战、生存模式都会创建对应 session。由于这些 session 只在短时间内有效,如果长期保留在数据库中,会造成无意义的数据堆积,也会增加后续排查和维护成本。
本次方案使用 CloudBase 的 TTL 能力来清理过期 session。服务端创建 session 时会写入 deleteAt 字段,CloudBase 控制台中已经确认 level-session 集合存在对应的 deleteAt_ttl 索引。后续每个 session 都会根据自身的过期时间,由 CloudBase 自动清理。
不过,TTL 删除通常不是实时执行的,因此服务端仍然保留业务层面的过期判断。即使某条过期 session 还没有被数据库自动删除,只要它已经超过业务允许时间,服务端也不会继续认为它有效。
这样处理的好处是:
- 不需要额外写定时清理任务;
- 数据库层面可以自动清理旧 session;
- 服务端业务层仍然保留安全兜底;
- session 表不会因为长期运行而持续堆积无效数据。
当前每个 session 暂定保留半小时,后续可以根据实际玩法时长、网络重试策略和反作弊需求再调整。
# 三.关卡 Session 机制重构与异步化
Session 的作用主要是保留服务端反作弊和结算凭证。也就是说,玩家开始一局游戏时,服务端会创建一个 session;玩家结算时,再通过这个 session 判断本局游戏是否合法、是否应该发放奖励或更新进度。
但之前的流程有一个明显问题:进入关卡时必须等待 session start 请求返回。
如果网络状态不好,玩家点击进入关卡后,可能会先看到一段空白等待。这对小游戏体验影响比较明显,尤其是关卡频繁切换、失败重开、每日挑战和生存模式这类入口,都会被网络请求拖慢。因此本次主要从“不要让 session 阻塞玩家进入关卡”这个方向进行调整。
## 进入关卡改为先展示棋盘
本次将普通关、每日挑战、生存模式的 session 启动流程都改为后台异步执行。
调整后的流程是:
这样玩家不会因为 session 请求而卡在进入页面。即使网络稍慢,也能先看到棋盘内容,整体体验会更流畅。
这次调整的核心原则是:
保留云端校验,但不要让云端请求阻塞玩家操作。
这里需要注意的是,session 仍然是必要的。它并没有被取消,只是不再作为进入关卡的前置阻塞条件。后续玩家完成关卡时,服务端仍然会根据 session 判断这局游戏是否有效,并决定是否允许结算、发放奖励或更新进度。
## complete 结算兜底
除了 start 异步化,本次也确认了 complete 的处理方式。
玩家过关后,可以先展示结算面板,后台再请求服务端 complete。也就是说,结算界面不会因为网络请求而完全卡住。这样玩家过关后可以更快看到反馈,不会因为接口请求慢而觉得游戏卡顿。
但为了避免 complete 没成功时玩家继续推进流程,当前方案是:
- 如果 complete 还没有成功返回,玩家点击下一关时,只弹出提示:网络错误,请稍后再试;
- complete 最多重试 3 次;
- 如果 3 次仍然失败,不再无限重试,只定时提示:网络错误,请重启游戏。
这样既能让结算面板先展示出来,又能避免服务端结算失败时,玩家继续进入下一关导致进度和资源状态不一致。
后续可以结合结算表现继续优化这部分体验。例如制作结算弹窗动画,在播放动画的过程中后台等待 complete 返回。如果请求正常完成,玩家几乎感知不到等待;如果请求失败,再通过提示阻止继续进入下一关。这样比直接让界面停住会更自然。
## 各玩法 Session 接口拆分
之前多个玩法共用旧的 start_level / complete_level 接口。早期玩法少时还能接受,但随着普通关、双鸡、每日挑战、生存模式逐步接入,每种模式的参数、次数消耗、奖励规则和校验逻辑都不同,继续共用接口会导致服务端堆很多条件判断。
本次确认后,将 Session 链路按玩法彻底拆分:
- 普通关:普通关 start / complete;
- 双鸡模式:双鸡 start / complete;
- 每日挑战:每日 start / complete;
- 生存模式:生存 start / complete。
拆分后的好处是每个模式都可以独立维护自己的规则。例如每日挑战要处理每日次数和新纪录,生存模式要处理波次、分数和体力奖励,普通关要处理关卡进度和体力消耗。如果继续放在同一个接口里,后续维护成本会越来越高。
# 四.云端资源变动路径审查与生存模式结算修复
随着云存档和 Session 机制逐步接入,金币、体力这类账号资源就不能再完全依赖客户端本地修改。否则玩家在云端模式下可能通过本地逻辑绕过服务端校验,导致服务端和客户端数据不一致。
因此今天对涉及体力、金币变动的路径做了一轮审查和修复。
## 生存模式结算体力发放修复
生存模式结算时会发放基础体力奖励。之前这部分在云端模式下不够完整,可能出现结算面板显示有体力奖励,但实际账号资源没有正确同步的问题。
本次在服务端 completeSurvival 中新增了体力发放逻辑,通过 grantAccountReward(player, { stamina: vitalBonus }) 自动发放基础体力。
同时,本地模式下也在客户端增加了兜底处理,直接执行 addStamina(vitalBonus),保证本地调试时也能看到正确效果。
结算面板文案也改成了:体力: +N(已发放)
这个文案比单纯显示 +N 更明确,可以告诉玩家这部分奖励已经到账,而不是还需要额外点击领取。
## 广告获取体力和金币改为服务端发放
修复了两个比较典型的资源漏洞。
第一个是看广告恢复体力:之前 StaminaRecoverPopupCtrl.ts 中存在直接 addStamina(60) 的逻辑。这个逻辑在纯本地阶段没问题,但在云端模式下就会绕过服务端。
第二个是胜利结算后看广告获得额外金币:之前 ResultPanelWinCtrl.ts 中也存在直接 addCoin(extraCoin) 的逻辑,同样会导致云端资源校验失效。
本次修复后,这两类逻辑都会先判断 CloudGameService.isAvailable():
- 云端服务可用时,走服务端 grantReward;
- 本地调试或离线模式下,才走本地直接加资源。
同时服务端补充了几个新的奖励来源:
- stamina_recover_ad:看广告恢复体力;
- win_ad_extra_coin:胜利后看广告额外金币;
- survival_ad_extra_vital:生存模式看广告额外体力。
这样每一类奖励都有明确 source,服务端可以根据 source 做统一配置、校验和发放,后续排查问题也更方便。
这部分调整的核心是:云端模式下,客户端不再直接决定关键账号资源的变化。客户端可以发起请求、展示结果,但真正的金币、体力变动应该由服务端根据规则发放,然后再同步回客户端。
## 资源同步与 applyCloudSave 调整
在修复资源变动时,还处理了一个 save 同步被跳过的问题。
之前 applyCloudSave 会受到 isRunValid 检查影响。如果当前 run 状态异常,可能导致服务端 save 没有同步到客户端。
这类问题不一定会立刻报错,但可能造成一个更麻烦的后果:服务端资源已经变化了,但客户端没有及时刷新,玩家看到的金币、体力和真实云端数据不一致。
本次将 applyCloudSave 移到 isRunValid 检查之前。因为 save 同步主要是把服务端返回的最新存档覆盖到本地状态,即使重复执行几次,一般也只是重复同步同一份结果,不会像“金币 +100”这种操作一样造成资源叠加。但如果这一步被跳过,就会造成客户端状态和服务端状态不同步。
# 五.后续计划
- 继续测试服务端相关改动,重点确认 CloudBase 存档读写、session 创建与清理、各模式 start / complete 链路、reward source 和生存体力发放是否正常生效。
- 继续实测普通关、双鸡模式、每日挑战、生存模式的完整流程,重点关注进入关卡、体力消耗、完成结算、奖励发放、存档同步、下一关推进等环节。
- 对测试过程中发现的 bug 和体验问题进行修复,优先处理影响关卡进入、资源同步、结算反馈的问题。