- Java 包 cn.huijing.game→cn.wanxiang.game:126 .java + 15 目录 git mv(保留历史)+ Application scanBasePackages/@MapperScan + yaml type-aliases - SDK HuijingGameSDK→WanxiangGameSDK + postMessage channel huijing-game-sdk→wanxiang-game-sdk(契约 + 前端 host/sdk/inject/bridge) - 契约 contracts/ 同步(sdk-interface.d.ts / runtime.yaml / game-package.schema / $id URL / V3 SQL 注释) - 主 agent 独立验证全绿:后端集成编译+55 单测(cn.wanxiang)、前端 build+/browse 冒烟(WanxiangGameSDK+demo 911 像素+遥测 200)、残留 huijing=0、Flyway 5 迁移 diff-identical、yudao cn.iocoder.yudao 2167 文件未误伤 - 保留 yudao 框架 cn.iocoder.yudao + Maven groupId cn.iocoder.cloud Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
90 lines
3.7 KiB
TypeScript
90 lines
3.7 KiB
TypeScript
/**
|
||
* 契约 #3 | WanxiangGameSDK 公共 API 类型 + SDK↔宿主 postMessage 协议
|
||
* owner:WS3 SDK 负责人 | 消费方:game-studio 宿主 / 游戏侧
|
||
*
|
||
* 硬约束(来自 engineering-conventions §3):
|
||
* - 零第三方依赖;Core(Lifecycle+EventBus+Telemetry+ErrorTrack) 压缩后 < 8KB;每 Plugin < 5KB
|
||
* - 所有对外 API 不返回 Promise(fire-and-forget),不占游戏主线程,异常绝不向游戏抛
|
||
* - 新版本只增字段/方法、不删不改已有签名(semver)
|
||
*/
|
||
|
||
/** SDK 初始化参数(宿主注入) */
|
||
export interface WanxiangGameSDKInitOptions {
|
||
gameId: string;
|
||
versionId: string;
|
||
/** 贯穿 生成→编译→加载→运行→上报 的 trace_id */
|
||
traceId: string;
|
||
/** 是否开发模式(加载 Plugin.Debug,仅 dev) */
|
||
debug?: boolean;
|
||
}
|
||
|
||
/** 游戏生命周期事件名 */
|
||
export type LifecycleEvent =
|
||
| 'sdk_ready' // SDK 初始化完成
|
||
| 'game_loaded' // 游戏资源加载完成
|
||
| 'game_start' // 开始游玩
|
||
| 'game_end' // 本局结束
|
||
| 'game_error'; // 运行错误
|
||
|
||
/** SDK 根对象(挂在游戏侧 window.WanxiangGameSDK) */
|
||
export interface WanxiangGameSDK {
|
||
/** 初始化(宿主调用一次) */
|
||
init(options: WanxiangGameSDKInitOptions): void;
|
||
/** 生命周期事件订阅(EventBus) */
|
||
on(event: LifecycleEvent, handler: (payload?: Record<string, unknown>) => void): void;
|
||
off(event: LifecycleEvent, handler: (payload?: Record<string, unknown>) => void): void;
|
||
/** 遥测上报(fire-and-forget,内部 10条/5s 批量 flush + sendBeacon 兜底) */
|
||
track(event: string, props?: Record<string, unknown>): void;
|
||
/** 错误上报(去重,不中断游戏) */
|
||
reportError(error: { message: string; stack?: string }): void;
|
||
/** 插件(首次调用懒加载) */
|
||
ad: AdPlugin;
|
||
pay: PayPlugin;
|
||
}
|
||
|
||
/** 广告插件(MVP 桩 → 真实穿山甲/优量汇切换;每调用 5s 超时降级) */
|
||
export interface AdPlugin {
|
||
/** 激励视频;完成回调 rewarded=true */
|
||
showRewarded(slotId: string, cb: (result: { rewarded: boolean }) => void): void;
|
||
/** 插屏广告 */
|
||
showInterstitial(slotId: string, cb?: (result: { shown: boolean }) => void): void;
|
||
}
|
||
|
||
/** 支付插件(MVP 桩 → 真实微信支付切换) */
|
||
export interface PayPlugin {
|
||
/** 发起积分充值;宿主侧拉起支付 */
|
||
pay(order: { orderId: string; amount: number }, cb: (result: { paid: boolean }) => void): void;
|
||
}
|
||
|
||
/* ============================================================================
|
||
* SDK ↔ 宿主 postMessage 协议
|
||
* 游戏在 iframe 沙箱内,通过 postMessage 与 game-studio 宿主通信。
|
||
* 宿主侧校验 origin 白名单 + 消息 schema(双校验,见 security-and-reliability §1.1)。
|
||
* ========================================================================== */
|
||
|
||
/** 消息方向 */
|
||
export type MessageDirection = 'game_to_host' | 'host_to_game';
|
||
|
||
/** 消息类型全集 */
|
||
export type PostMessageType =
|
||
| 'init' // 宿主→游戏:初始化参数
|
||
| 'lifecycle' // 游戏→宿主:生命周期事件
|
||
| 'telemetry' // 游戏→宿主:遥测事件转发
|
||
| 'error' // 游戏→宿主:错误上报
|
||
| 'ad' // 双向:广告请求/结果(广告在 iframe 外宿主侧渲染)
|
||
| 'pay' // 双向:支付请求/结果
|
||
| 'social' // 双向:分享等
|
||
| 'storage'; // 双向:键值存储
|
||
|
||
/** postMessage 信封 */
|
||
export interface PostMessageEnvelope<T = unknown> {
|
||
/** 固定标识,宿主据此过滤非本协议消息 */
|
||
channel: 'wanxiang-game-sdk';
|
||
type: PostMessageType;
|
||
direction: MessageDirection;
|
||
/** 请求/响应配对 ID(ad/pay 等需回调的消息) */
|
||
requestId?: string;
|
||
traceId: string;
|
||
payload: T;
|
||
}
|