OY-Play WebSDK(oyapi)接入指南
本技能指导你(AI 助手)在 Web 游戏工程中安装 OYplay WebSDK,并按平台约定使用 window.oyapi,避免自建一套和平台冲突的存档/同步逻辑。
oyapi 是什么(30 秒版)
OY-Play 平台托管的 Web 游戏运行在隔离沙箱基座中,基座会在游戏首个脚本执行前完成两件事:
- 注入全局对象
window.oyapi(玩家信息 + 云存档控制); - 在默认的
auto模式下用一个 Proxy 透明接管window.localStorage——游戏照常读写localStorage,数据自动云同步。
因此本 SDK 没有任何运行时代码:OYplay_WebSDK.ts 只是一份 TypeScript 声明,作用是语法提示与文档。游戏在平台外直开(本地 file:// 或自建服务器)时 window.oyapi 不存在,localStorage 是浏览器原生实现。
安装 SDK
当前Skill适用的SDK版本是:0.1.0
SDK 完整压缩包位于"https://static.mp.quanmwl.com/public/sdk/WebSDK_{version}.zip",version是版本号
SDK 单文件位于"https://static.mp.quanmwl.com/public/sdk/oyapi-websdk-{version}/WebSDK/OYplay_WebSDK.ts",version是版本号
在 TS 工程中二选一:
方案 A(推荐):复制单文件
把 OYplay_WebSDK.ts 复制进游戏工程(例如 src/types/OYplay_WebSDK.ts)。文件自带 export {} 与 declare global,只要它落在 tsconfig.json 的 include 范围内,window.oyapi 与 oyapi:ready 事件的类型即全局生效,无需任何 import。
方案 B:本地类型依赖
在游戏工程 package.json 中声明本地依赖(路径按实际位置调整):
{ "dependencies": { "oyplay-websdk": "file:../WebSDK" } }
然后在整个工程只需一处类型导入,让全局声明进入编译(注意必须用 import type {},纯类型导入会在编译后擦除,不会引入运行时模块):
import type {} from "oyplay-websdk";
纯 JS 工程:SDK 无运行时,无需安装;把 OYplay_WebSDK.ts 和本技能的 references 当作 API 文档阅读即可。
安装完成后用 npx tsc --noEmit 验证:window.oyapi.Player.GetInfo() 应能通过类型检查。
API 速览
// —— 玩家信息 ——
const player = window.oyapi.Player.GetInfo();
if (player) {
console.log(player.id, player.nickname); // 平台会话存在
} else {
// 未登录或非平台环境(本地直开同样是 null)
}
// —— 云存档:数据本体直接用 localStorage ——
localStorage.setItem("progress", JSON.stringify(state)); // auto 模式下自动云同步
const saved = localStorage.getItem("progress");
// —— 模式控制 ——
await window.oyapi.CloudStorage.Mode("disable"); // 关闭云同步(成功后基座会刷新页面)
await window.oyapi.CloudStorage.Mode("auto"); // 重新开启
// —— 主动同步 + 同步回调 ——
const snapshot = await window.oyapi.CloudStorage.CloudSync(); // 最新快照,或 null
const off = window.oyapi.CloudStorage.OnSync((snap) => {
console.log("synced, version =", snap.version);
});
off(); // 取消注册
本地开发守卫(平台外 window.oyapi 不存在):
const oyapi = typeof window !== "undefined" && "oyapi" in window ? window.oyapi : null;
更完整的守卫与安全封装见 assets/oyapi-compat.ts,可直接复制进工程。
关键行为约束(写代码前必读)
- 存档入口就是
localStorage,不要为云同步自建任何请求或队列——auto 模式下基座已全部代劳。 - 存档整体上限约 5MB(全量 JSON 编码后),超限
setItem抛QuotaExceededError,原数据不变。 - 写入后有 800ms 防抖才触发同步;页面隐藏、页面卸载、网络恢复时也会触发;不必手动频繁
CloudSync()。 - 未登录(无平台会话):
GetInfo()返回null,CloudSync()返回null,Mode()会 reject。 Mode("disable")成功后基座约 100ms 后刷新页面;此后localStorage退化为沙箱本地持久化(不访问部署节点原生存储)。- 模式按「玩家 ID + 游戏 ID」记录在云端,玩家下次进入即生效。
- 同步失败自动重试(1s 起指数退避,封顶 30s),基座顶部弹「云存档异常!」。
OnSync回调抛错会被吞掉,不影响其他回调与同步流程。- 冲突以云端
version高者胜,平局比recorded_at_ms;同步响应到达时若本地无新写入,数据整体替换为云端版本。 - 所有键值都是字符串(与浏览器
localStorage一致),对象请 JSON 序列化。
涉及模式切换、同步时机、错误处理或需要精确语义时,先读参考文件再动手:
- references/api.md —— 类型与语义全量参考、错误信息对照表
- references/cloud-storage.md —— localStorage 接管与云同步机制细节
推荐接入流程
- 确认是 Web/H5 游戏工程且将上架 OY-Play;TS 工程按上面方案 A/B 安装类型,纯 JS 工程跳过。
- 游戏存档读写统一走
localStorage(包括首次进入时恢复云存档——数据在首个脚本执行前已注入)。 - 需要展示玩家身份时调用
Player.GetInfo(),并处理null(未登录/非平台环境)。 - 需要同步反馈或版本展示时注册
OnSync,记得保存取消函数。 - 提供存档开关 UI 时用
Mode("disable" / "auto"),注意 disable 后页面会刷新,切换期间不要堆积其他操作。 - 运行
npx tsc --noEmit验证类型接入成功。
故障排查速查
| 症状 | 原因 | 处理 |
|---|---|---|
window.oyapi 为 undefined |
本地直开,无基座 | 属预期;用守卫判断并降级 |
setItem 抛 QuotaExceededError |
存档超 5MB | 压缩/拆分数据、清理无用键 |
Mode() reject cloud session is unavailable |
未登录/无平台会话 | 引导登录或保持默认模式 |
CloudSync() 返回 null |
非 auto 模式或无会话 | 检查模式与会话状态 |
OnSync 回调迟迟不触发 |
无新写入或防抖未到 | 等待 800ms 防抖/页面隐藏,或主动 CloudSync() |
| disable 后页面自动刷新 | 基座设计如此,确保状态落盘 | 正常行为,切换前先写完数据 |
本技能的安装(给最终用户)
本技能目录随 WebSDK 分发。若游戏工程由 AI 辅助开发,把 oyapi-websdk 整个目录复制到工程根目录的 .agents/skills/(跨工具通用)或 .zcode/skills/ 下,AI 即可自动发现并按本指南接入。