@zhimakechuang/game-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,179 @@
1
+ # @zhimakechuang/game-sdk
2
+
3
+ 通用游戏 SDK — 封装 [`apps/game-server-shared`](https://github.com/Chuang0516/game-factory/tree/main/apps/game-server-shared) 的 HTTP 接口,一套代码支持**微信小游戏 / 抖音小游戏 / H5** 三端。
4
+
5
+ ## 特性
6
+
7
+ - **一套代码三端运行**:自动检测运行环境(wx / tt / H5),底层切换 `wx.request` / `tt.request` / `fetch`
8
+ - **Token 自动持久化**:登录后自动存到 `localStorage`(H5)或本地存储(小游戏),下次进入免登录
9
+ - **多租户隔离**:通过 `gameId` 隔离不同游戏的数据,一套服务端承载所有游戏
10
+ - **模拟模式**:`mock: true` 时不连服务端,返回假数据,方便模板开发与调试
11
+ - **全类型定义**:TypeScript 编写,自带 `.d.ts`,IDE 智能提示完备
12
+ - **零依赖**:打包后仅 8KB(gzip 后更小),不引入任何运行时依赖
13
+
14
+ ## 安装
15
+
16
+ ```bash
17
+ npm install @zhimakechuang/game-sdk
18
+ # 或
19
+ pnpm add @zhimakechuang/game-sdk
20
+ # 或
21
+ yarn add @zhimakechuang/game-sdk
22
+ ```
23
+
24
+ ## 快速开始
25
+
26
+ ### 工程化项目(npm 安装)
27
+
28
+ ```ts
29
+ import { createGameSdk } from '@zhimakechuang/game-sdk';
30
+
31
+ const sdk = createGameSdk({
32
+ gameId: 'merge-game', // 在平台后台登记的游戏 ID
33
+ baseUrl: 'https://api.example.com', // api-server 根地址
34
+ });
35
+
36
+ // 登录(微信小游戏)
37
+ const { wx } = miniProgram; // 假设已拿到微信环境
38
+ const { code } = await wx.login();
39
+ await sdk.auth.login({ code, platform: 'wx' });
40
+
41
+ // 提交分数
42
+ const result = await sdk.score.submit({ score: 1000 });
43
+ console.log(result.rank, result.isHighScore);
44
+
45
+ // 拉排行榜
46
+ const top = await sdk.leaderboard.top(100);
47
+ const me = await sdk.leaderboard.myRank();
48
+ ```
49
+
50
+ ### CDN 引入(轻量模板 / H5)
51
+
52
+ ```html
53
+ <script src="https://unpkg.com/@zhimakechuang/game-sdk"></script>
54
+ <script>
55
+ const sdk = GameSDK.createGameSdk({
56
+ gameId: 'merge-game',
57
+ baseUrl: 'https://api.example.com',
58
+ });
59
+
60
+ // 访客登录(H5 无需微信/抖音凭据)
61
+ await sdk.auth.login({ code: 'device-id', platform: 'guest' });
62
+ await sdk.score.submit({ score: 1000 });
63
+ </script>
64
+ ```
65
+
66
+ ### 模拟模式(不连服务端)
67
+
68
+ ```ts
69
+ const sdk = createGameSdk({
70
+ gameId: 'demo',
71
+ baseUrl: '', // 不需要
72
+ mock: true, // 关键:走 mock
73
+ });
74
+
75
+ await sdk.auth.login({ code: 'x', platform: 'guest' });
76
+ const r = await sdk.score.submit({ score: 100 });
77
+ // r.isHighScore === true, r.rank === 1
78
+ ```
79
+
80
+ ## API 参考
81
+
82
+ ### `createGameSdk(config)` → `GameSdk`
83
+
84
+ | 参数 | 类型 | 说明 |
85
+ |---|---|---|
86
+ | `config.gameId` | `string` | 游戏 ID(必填) |
87
+ | `config.baseUrl` | `string` | api-server 根地址(必填,mock 模式可空) |
88
+ | `config.mock` | `boolean` | 模拟模式,默认 `false` |
89
+
90
+ ### `sdk.auth` — 身份与登录
91
+
92
+ | 方法 | 说明 |
93
+ |---|---|
94
+ | `login(opts)` | 登录(wx/tt/guest),成功后自动持久化 token |
95
+ | `me()` | 获取当前登录玩家信息 |
96
+ | `logout()` | 登出,清除本地 token |
97
+ | `getToken()` | 获取当前 token(调试用) |
98
+
99
+ ```ts
100
+ await sdk.auth.login({
101
+ code: 'wx-code', // wx/tt 的 login code,或 guest 的设备标识
102
+ platform: 'wx', // 'wx' | 'tt' | 'guest',默认 guest
103
+ deviceId?: 'xxx', // platform=guest 时必传
104
+ nickname?: '玩家名', // 首次登录设置
105
+ });
106
+ ```
107
+
108
+ ### `sdk.score` — 分数
109
+
110
+ | 方法 | 说明 |
111
+ |---|---|
112
+ | `submit(opts)` | 提交分数,返回 `{ isHighScore, previousBest, bestScore, rank }` |
113
+
114
+ ```ts
115
+ const r = await sdk.score.submit({
116
+ score: 1000,
117
+ extra?: { maxLevel: 5 }, // 游戏自定义数据
118
+ metadata?: { seed: 'xxx' }, // 反作弊元数据
119
+ });
120
+ // r.submitted / r.isHighScore / r.previousBest / r.bestScore / r.rank
121
+ ```
122
+
123
+ ### `sdk.leaderboard` — 排行榜
124
+
125
+ | 方法 | 说明 |
126
+ |---|---|
127
+ | `top(limit?)` | 获取 Top N(匿名可访问,默认 100) |
128
+ | `myRank()` | 获取当前玩家排名(需登录) |
129
+ | `nearby(range?)` | 获取附近排名(需登录,默认 ±5) |
130
+
131
+ ### `sdk.player` — 玩家档案
132
+
133
+ | 方法 | 说明 |
134
+ |---|---|
135
+ | `getProfile()` | 获取当前玩家档案 |
136
+ | `updateProfile(patch)` | 更新昵称/头像/扩展字段 |
137
+
138
+ ### `sdk.save` — 云存档(KV)
139
+
140
+ | 方法 | 说明 |
141
+ |---|---|
142
+ | `set(key, value)` | 保存数据到指定 key |
143
+ | `get(key)` | 读取指定 key |
144
+ | `getAll()` | 读取所有存档 |
145
+ | `remove(key)` | 删除指定 key |
146
+ | `clear()` | 清空所有存档 |
147
+
148
+ ```ts
149
+ // 存进度
150
+ await sdk.save.set('progress', { level: 5, coins: 100 });
151
+ const progress = await sdk.save.get('progress');
152
+ ```
153
+
154
+ ## 运行环境检测
155
+
156
+ SDK 会自动检测当前环境:
157
+
158
+ | 环境 | 检测条件 | HTTP 实现 | 存储实现 |
159
+ |---|---|---|---|
160
+ | 微信小游戏 | `typeof wx !== 'undefined'` | `wx.request` | `wx.setStorageSync` |
161
+ | 抖音小游戏 | `typeof tt !== 'undefined'` | `tt.request` | `tt.setStorageSync` |
162
+ | H5 浏览器 | 其他 | `fetch` | `localStorage` |
163
+
164
+ 无需手动指定,SDK 自动适配。
165
+
166
+ ## 服务端
167
+
168
+ 本 SDK 配套的通用游戏服务端在 [`apps/game-server-shared`](https://github.com/Chuang0516/game-factory/tree/main/apps/game-server-shared)(NestJS + MongoDB),提供:
169
+
170
+ - 多租户数据隔离(按 `gameId`)
171
+ - 身份(微信/抖音 code2session + JWT)/ 访客模式
172
+ - 分数 + 排行榜(Top / 我的排名 / 附近玩家)
173
+ - 云存档(KV)
174
+ - 玩家档案 + 封禁管理
175
+ - Admin 运营接口
176
+
177
+ ## License
178
+
179
+ MIT
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Game SDK 类型定义
3
+ * 与 game-server-shared 接口契约一一对应
4
+ */
5
+ type Platform = 'wx' | 'tt' | 'guest';
6
+ /** SDK 配置 */
7
+ interface GameSdkConfig {
8
+ /** 游戏 ID(在平台后台登记) */
9
+ gameId: string;
10
+ /** api-server 根地址(如 https://api.example.com) */
11
+ baseUrl: string;
12
+ /** 模拟模式(不连服务端,返回假数据,用于模板开发) */
13
+ mock?: boolean;
14
+ }
15
+ interface LoginOptions {
16
+ /** 登录凭据:wx/tt 的 code,或 guest 的设备标识 */
17
+ code: string;
18
+ platform?: Platform;
19
+ /** 访客设备 ID(platform=guest 时必传) */
20
+ deviceId?: string;
21
+ nickname?: string;
22
+ avatarUrl?: string;
23
+ }
24
+ interface LoginResult {
25
+ token: string;
26
+ openId: string;
27
+ isNew: boolean;
28
+ profile: PlayerProfile;
29
+ }
30
+ interface PlayerProfile {
31
+ openId: string;
32
+ platform: Platform;
33
+ nickname: string;
34
+ avatarUrl?: string;
35
+ bestScore: number;
36
+ playCount: number;
37
+ createdAt: string;
38
+ lastSeenAt: string;
39
+ }
40
+ interface SubmitScoreOptions {
41
+ score: number;
42
+ /** 游戏自定义扩展数据(如 maxLevel、通关时间) */
43
+ extra?: Record<string, any>;
44
+ /** 反作弊元数据 */
45
+ metadata?: Record<string, any>;
46
+ }
47
+ interface SubmitScoreResult {
48
+ submitted: number;
49
+ isHighScore: boolean;
50
+ previousBest: number;
51
+ bestScore: number;
52
+ rank: number;
53
+ }
54
+ interface LeaderboardEntry {
55
+ rank: number;
56
+ openId: string;
57
+ nickname: string;
58
+ avatarUrl?: string;
59
+ score: number;
60
+ isSelf?: boolean;
61
+ }
62
+ interface MyRank {
63
+ rank: number;
64
+ score: number;
65
+ totalPlayers: number;
66
+ playCount?: number;
67
+ }
68
+ interface SaveEntry {
69
+ key: string;
70
+ value: Record<string, any>;
71
+ updatedAt: string;
72
+ }
73
+
74
+ /**
75
+ * @game-factory/game-sdk
76
+ *
77
+ * 通用游戏 SDK,封装 game-server-shared 所有 HTTP 接口。
78
+ *
79
+ * 用法(工程化):
80
+ * import { createGameSdk } from '@game-factory/game-sdk';
81
+ * const sdk = createGameSdk({ gameId: 'merge-game', baseUrl: 'https://api.example.com' });
82
+ * await sdk.auth.login({ code: 'xxx', platform: 'wx' });
83
+ * await sdk.score.submit({ score: 1000 });
84
+ *
85
+ * 用法(CDN):
86
+ * <script src="https://cdn.example.com/game-sdk/index.umd.js"></script>
87
+ * const sdk = GameSDK.createGameSdk({ gameId: 'merge-game', baseUrl: '...' });
88
+ *
89
+ * 用法(模拟模式,不连服务端):
90
+ * const sdk = createGameSdk({ gameId: 'demo', baseUrl: '', mock: true });
91
+ */
92
+
93
+ declare class GameSdkError extends Error {
94
+ status: number;
95
+ data?: any | undefined;
96
+ constructor(message: string, status: number, data?: any | undefined);
97
+ }
98
+ interface GameSdk {
99
+ /** 身份与登录 */
100
+ auth: {
101
+ /** 登录(微信/抖音/访客),成功后自动持久化 token */
102
+ login(opts: LoginOptions): Promise<LoginResult>;
103
+ /** 获取当前登录玩家信息(需先 login) */
104
+ me(): Promise<PlayerProfile>;
105
+ /** 登出,清除本地 token */
106
+ logout(): void;
107
+ /** 获取当前 token(用于调试) */
108
+ getToken(): string | null;
109
+ };
110
+ /** 分数 */
111
+ score: {
112
+ /** 提交分数(需登录) */
113
+ submit(opts: SubmitScoreOptions): Promise<SubmitScoreResult>;
114
+ };
115
+ /** 排行榜 */
116
+ leaderboard: {
117
+ /** 获取 Top N(匿名可访问,limit 默认 100) */
118
+ top(limit?: number): Promise<LeaderboardEntry[]>;
119
+ /** 获取当前玩家排名(需登录) */
120
+ myRank(): Promise<MyRank>;
121
+ /** 获取附近排名(需登录,range 默认 ±5) */
122
+ nearby(range?: number): Promise<LeaderboardEntry[]>;
123
+ };
124
+ /** 玩家档案 */
125
+ player: {
126
+ /** 获取当前玩家档案(需登录) */
127
+ getProfile(): Promise<PlayerProfile>;
128
+ /** 更新档案(昵称/头像/扩展字段) */
129
+ updateProfile(patch: {
130
+ nickname?: string;
131
+ avatarUrl?: string;
132
+ extra?: Record<string, any>;
133
+ }): Promise<PlayerProfile>;
134
+ };
135
+ /** 云存档(KV) */
136
+ save: {
137
+ /** 保存数据到指定 key */
138
+ set(key: string, value: Record<string, any>): Promise<{
139
+ success: boolean;
140
+ key: string;
141
+ value: Record<string, any>;
142
+ }>;
143
+ /** 读取指定 key 的数据 */
144
+ get(key: string): Promise<Record<string, any> | null>;
145
+ /** 读取所有存档 */
146
+ getAll(): Promise<Record<string, any>>;
147
+ /** 删除指定 key */
148
+ remove(key: string): Promise<{
149
+ success: boolean;
150
+ key: string;
151
+ }>;
152
+ /** 清空所有存档 */
153
+ clear(): Promise<{
154
+ success: boolean;
155
+ deleted: number;
156
+ }>;
157
+ };
158
+ }
159
+ declare function createGameSdk(config: GameSdkConfig): GameSdk;
160
+
161
+ export { type GameSdk, type GameSdkConfig, GameSdkError, type LeaderboardEntry, type LoginOptions, type LoginResult, type MyRank, type Platform, type PlayerProfile, type SaveEntry, type SubmitScoreOptions, type SubmitScoreResult, createGameSdk };
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Game SDK 类型定义
3
+ * 与 game-server-shared 接口契约一一对应
4
+ */
5
+ type Platform = 'wx' | 'tt' | 'guest';
6
+ /** SDK 配置 */
7
+ interface GameSdkConfig {
8
+ /** 游戏 ID(在平台后台登记) */
9
+ gameId: string;
10
+ /** api-server 根地址(如 https://api.example.com) */
11
+ baseUrl: string;
12
+ /** 模拟模式(不连服务端,返回假数据,用于模板开发) */
13
+ mock?: boolean;
14
+ }
15
+ interface LoginOptions {
16
+ /** 登录凭据:wx/tt 的 code,或 guest 的设备标识 */
17
+ code: string;
18
+ platform?: Platform;
19
+ /** 访客设备 ID(platform=guest 时必传) */
20
+ deviceId?: string;
21
+ nickname?: string;
22
+ avatarUrl?: string;
23
+ }
24
+ interface LoginResult {
25
+ token: string;
26
+ openId: string;
27
+ isNew: boolean;
28
+ profile: PlayerProfile;
29
+ }
30
+ interface PlayerProfile {
31
+ openId: string;
32
+ platform: Platform;
33
+ nickname: string;
34
+ avatarUrl?: string;
35
+ bestScore: number;
36
+ playCount: number;
37
+ createdAt: string;
38
+ lastSeenAt: string;
39
+ }
40
+ interface SubmitScoreOptions {
41
+ score: number;
42
+ /** 游戏自定义扩展数据(如 maxLevel、通关时间) */
43
+ extra?: Record<string, any>;
44
+ /** 反作弊元数据 */
45
+ metadata?: Record<string, any>;
46
+ }
47
+ interface SubmitScoreResult {
48
+ submitted: number;
49
+ isHighScore: boolean;
50
+ previousBest: number;
51
+ bestScore: number;
52
+ rank: number;
53
+ }
54
+ interface LeaderboardEntry {
55
+ rank: number;
56
+ openId: string;
57
+ nickname: string;
58
+ avatarUrl?: string;
59
+ score: number;
60
+ isSelf?: boolean;
61
+ }
62
+ interface MyRank {
63
+ rank: number;
64
+ score: number;
65
+ totalPlayers: number;
66
+ playCount?: number;
67
+ }
68
+ interface SaveEntry {
69
+ key: string;
70
+ value: Record<string, any>;
71
+ updatedAt: string;
72
+ }
73
+
74
+ /**
75
+ * @game-factory/game-sdk
76
+ *
77
+ * 通用游戏 SDK,封装 game-server-shared 所有 HTTP 接口。
78
+ *
79
+ * 用法(工程化):
80
+ * import { createGameSdk } from '@game-factory/game-sdk';
81
+ * const sdk = createGameSdk({ gameId: 'merge-game', baseUrl: 'https://api.example.com' });
82
+ * await sdk.auth.login({ code: 'xxx', platform: 'wx' });
83
+ * await sdk.score.submit({ score: 1000 });
84
+ *
85
+ * 用法(CDN):
86
+ * <script src="https://cdn.example.com/game-sdk/index.umd.js"></script>
87
+ * const sdk = GameSDK.createGameSdk({ gameId: 'merge-game', baseUrl: '...' });
88
+ *
89
+ * 用法(模拟模式,不连服务端):
90
+ * const sdk = createGameSdk({ gameId: 'demo', baseUrl: '', mock: true });
91
+ */
92
+
93
+ declare class GameSdkError extends Error {
94
+ status: number;
95
+ data?: any | undefined;
96
+ constructor(message: string, status: number, data?: any | undefined);
97
+ }
98
+ interface GameSdk {
99
+ /** 身份与登录 */
100
+ auth: {
101
+ /** 登录(微信/抖音/访客),成功后自动持久化 token */
102
+ login(opts: LoginOptions): Promise<LoginResult>;
103
+ /** 获取当前登录玩家信息(需先 login) */
104
+ me(): Promise<PlayerProfile>;
105
+ /** 登出,清除本地 token */
106
+ logout(): void;
107
+ /** 获取当前 token(用于调试) */
108
+ getToken(): string | null;
109
+ };
110
+ /** 分数 */
111
+ score: {
112
+ /** 提交分数(需登录) */
113
+ submit(opts: SubmitScoreOptions): Promise<SubmitScoreResult>;
114
+ };
115
+ /** 排行榜 */
116
+ leaderboard: {
117
+ /** 获取 Top N(匿名可访问,limit 默认 100) */
118
+ top(limit?: number): Promise<LeaderboardEntry[]>;
119
+ /** 获取当前玩家排名(需登录) */
120
+ myRank(): Promise<MyRank>;
121
+ /** 获取附近排名(需登录,range 默认 ±5) */
122
+ nearby(range?: number): Promise<LeaderboardEntry[]>;
123
+ };
124
+ /** 玩家档案 */
125
+ player: {
126
+ /** 获取当前玩家档案(需登录) */
127
+ getProfile(): Promise<PlayerProfile>;
128
+ /** 更新档案(昵称/头像/扩展字段) */
129
+ updateProfile(patch: {
130
+ nickname?: string;
131
+ avatarUrl?: string;
132
+ extra?: Record<string, any>;
133
+ }): Promise<PlayerProfile>;
134
+ };
135
+ /** 云存档(KV) */
136
+ save: {
137
+ /** 保存数据到指定 key */
138
+ set(key: string, value: Record<string, any>): Promise<{
139
+ success: boolean;
140
+ key: string;
141
+ value: Record<string, any>;
142
+ }>;
143
+ /** 读取指定 key 的数据 */
144
+ get(key: string): Promise<Record<string, any> | null>;
145
+ /** 读取所有存档 */
146
+ getAll(): Promise<Record<string, any>>;
147
+ /** 删除指定 key */
148
+ remove(key: string): Promise<{
149
+ success: boolean;
150
+ key: string;
151
+ }>;
152
+ /** 清空所有存档 */
153
+ clear(): Promise<{
154
+ success: boolean;
155
+ deleted: number;
156
+ }>;
157
+ };
158
+ }
159
+ declare function createGameSdk(config: GameSdkConfig): GameSdk;
160
+
161
+ export { type GameSdk, type GameSdkConfig, GameSdkError, type LeaderboardEntry, type LoginOptions, type LoginResult, type MyRank, type Platform, type PlayerProfile, type SaveEntry, type SubmitScoreOptions, type SubmitScoreResult, createGameSdk };