@lizardon386/sdk-tools 0.2.0 → 0.3.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.
@@ -1,3 +1,4 @@
1
+ import type { GameReferenceSpec } from '@lizardon386/core-abi';
1
2
  export interface HostInfo {
2
3
  platform?: string;
3
4
  packFormats?: unknown;
@@ -16,6 +17,9 @@ export interface DoctorTarget {
16
17
  format: number;
17
18
  mode: string;
18
19
  apiVersion: number;
20
+ reference?: GameReferenceSpec;
21
+ /** 资料文档原文;源目录与包都用它跑同一份 parseGameReference。 */
22
+ referenceText?: string;
19
23
  }
20
24
  export interface DoctorCheck {
21
25
  ok: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AA2CD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAI7D;AAUD,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,GAAG,WAAW,EAAE,CAoB7E;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAiBnE;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW,EAAE,CAa/D;AAED,wBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAQpF"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG/D,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,8CAA8C;IAC9C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AA+DD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAI7D;AAUD,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,GAAG,WAAW,EAAE,CAoB7E;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAiBnE;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW,EAAE,CAiD/D;AAED,wBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAQpF"}
@@ -1,7 +1,19 @@
1
1
  import { existsSync, readFileSync, statSync } from 'node:fs';
2
2
  import { join, resolve } from 'node:path';
3
- import { API_VERSION, DEFAULT_MODE } from '@lizardon386/core-abi';
3
+ import { API_VERSION, DEFAULT_MODE, isValidGameReferenceEntry, parseGameReference, } from '@lizardon386/core-abi';
4
4
  import { PACK_FORMAT, readPack, readPackSource } from '@lizardon386/pack-format';
5
+ function readDeclaredReference(value) {
6
+ if (value === undefined)
7
+ return undefined;
8
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
9
+ throw new Error('bpmap.json 的 reference 必须是对象');
10
+ }
11
+ const entry = value.entry;
12
+ if (typeof entry !== 'string' || !isValidGameReferenceEntry(entry)) {
13
+ throw new Error('bpmap.json 的 reference.entry 必须是包内 .json 相对路径');
14
+ }
15
+ return { entry };
16
+ }
5
17
  function readSourceTarget(dir) {
6
18
  const rawPath = join(dir, 'bpmap.json');
7
19
  let raw;
@@ -15,6 +27,7 @@ function readSourceTarget(dir) {
15
27
  throw new Error(`读不到或解析不了源清单:${rawPath}(${error instanceof Error ? error.message : String(error)})`);
16
28
  }
17
29
  const source = readPackSource(dir);
30
+ const reference = readDeclaredReference(raw.reference);
18
31
  return {
19
32
  kind: 'source',
20
33
  path: dir,
@@ -27,10 +40,15 @@ function readSourceTarget(dir) {
27
40
  apiVersion: typeof raw.apiVersion === 'number' && Number.isSafeInteger(raw.apiVersion) && raw.apiVersion > 0
28
41
  ? raw.apiVersion
29
42
  : API_VERSION,
43
+ ...(reference ? { reference } : {}),
30
44
  };
31
45
  }
32
46
  function readPackTarget(file) {
33
47
  const pack = readPack(file);
48
+ const reference = pack.manifest.reference;
49
+ const document = reference
50
+ ? pack.files.find((entry) => entry.path.toLowerCase() === reference.entry.toLowerCase())
51
+ : undefined;
34
52
  return {
35
53
  kind: 'pack',
36
54
  path: file,
@@ -41,6 +59,8 @@ function readPackTarget(file) {
41
59
  format: pack.manifest.format,
42
60
  mode: pack.manifest.mode,
43
61
  apiVersion: pack.manifest.apiVersion,
62
+ ...(reference ? { reference } : {}),
63
+ ...(document ? { referenceText: document.bytes.toString('utf8') } : {}),
44
64
  };
45
65
  }
46
66
  export function readDoctorTarget(target) {
@@ -106,12 +126,48 @@ export function localChecks(target) {
106
126
  ];
107
127
  if (target.client)
108
128
  checks.push({ ok: existsSync(join(dir, target.client)), label: `客户端入口 ${target.client}` });
129
+ if (target.reference) {
130
+ const entry = target.reference.entry;
131
+ const valid = isValidGameReferenceEntry(entry);
132
+ checks.push({
133
+ ok: valid,
134
+ label: `资料文档入口 ${entry}`,
135
+ ...(valid ? {} : { detail: '必须是包内 .json 相对路径' }),
136
+ });
137
+ if (valid) {
138
+ const absolute = join(dir, ...entry.split('/'));
139
+ const exists = existsSync(absolute);
140
+ checks.push({ ok: exists, label: `资料文档 ${entry}` });
141
+ if (exists) {
142
+ const parsed = parseGameReference(readFileSync(absolute, 'utf8'));
143
+ checks.push({
144
+ ok: parsed.ok,
145
+ label: '资料文档格式',
146
+ ...(parsed.ok ? {} : { detail: parsed.error }),
147
+ });
148
+ }
149
+ }
150
+ }
109
151
  return checks;
110
152
  }
111
- return [
153
+ const checks = [
112
154
  { ok: target.format === PACK_FORMAT, label: `包格式 ${target.format}` },
113
155
  { ok: Boolean(target.server), label: `服务端入口 ${target.server}` },
114
156
  ];
157
+ if (target.reference) {
158
+ const entry = target.reference.entry;
159
+ const inPack = target.referenceText !== undefined;
160
+ checks.push({ ok: inPack, label: `资料文档 ${entry} 在包清单里` });
161
+ if (inPack) {
162
+ const parsed = parseGameReference(target.referenceText);
163
+ checks.push({
164
+ ok: parsed.ok,
165
+ label: '资料文档格式',
166
+ ...(parsed.ok ? {} : { detail: parsed.error }),
167
+ });
168
+ }
169
+ }
170
+ return checks;
115
171
  }
116
172
  export async function doctor(target, hostUrl) {
117
173
  const info = readDoctorTarget(target);
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lizardon386/sdk-tools",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "3178 SDK 工具:bpmap CLI、doctor 和游戏工程脚本模板",
5
5
  "license": "MIT",
6
6
  "author": "3178-battle-platform contributors",
@@ -32,8 +32,8 @@
32
32
  "src"
33
33
  ],
34
34
  "dependencies": {
35
- "@lizardon386/core-abi": "^0.2.0",
36
- "@lizardon386/pack-format": "^0.2.0"
35
+ "@lizardon386/core-abi": "^0.3.0",
36
+ "@lizardon386/pack-format": "^0.3.0"
37
37
  },
38
38
  "publishConfig": {
39
39
  "access": "public"
package/src/cli/doctor.ts CHANGED
@@ -1,6 +1,12 @@
1
1
  import { existsSync, readFileSync, statSync } from 'node:fs';
2
2
  import { join, resolve } from 'node:path';
3
- import { API_VERSION, DEFAULT_MODE } from '@lizardon386/core-abi';
3
+ import {
4
+ API_VERSION,
5
+ DEFAULT_MODE,
6
+ isValidGameReferenceEntry,
7
+ parseGameReference,
8
+ } from '@lizardon386/core-abi';
9
+ import type { GameReferenceSpec } from '@lizardon386/core-abi';
4
10
  import { PACK_FORMAT, readPack, readPackSource } from '@lizardon386/pack-format';
5
11
 
6
12
  export interface HostInfo {
@@ -22,6 +28,9 @@ export interface DoctorTarget {
22
28
  format: number;
23
29
  mode: string;
24
30
  apiVersion: number;
31
+ reference?: GameReferenceSpec;
32
+ /** 资料文档原文;源目录与包都用它跑同一份 parseGameReference。 */
33
+ referenceText?: string;
25
34
  }
26
35
 
27
36
  export interface DoctorCheck {
@@ -35,6 +44,18 @@ export interface DoctorReport {
35
44
  checks: DoctorCheck[];
36
45
  }
37
46
 
47
+ function readDeclaredReference(value: unknown): GameReferenceSpec | undefined {
48
+ if (value === undefined) return undefined;
49
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
50
+ throw new Error('bpmap.json 的 reference 必须是对象');
51
+ }
52
+ const entry = (value as Record<string, unknown>).entry;
53
+ if (typeof entry !== 'string' || !isValidGameReferenceEntry(entry)) {
54
+ throw new Error('bpmap.json 的 reference.entry 必须是包内 .json 相对路径');
55
+ }
56
+ return { entry };
57
+ }
58
+
38
59
  function readSourceTarget(dir: string): DoctorTarget {
39
60
  const rawPath = join(dir, 'bpmap.json');
40
61
  let raw: Record<string, unknown>;
@@ -46,6 +67,7 @@ function readSourceTarget(dir: string): DoctorTarget {
46
67
  throw new Error(`读不到或解析不了源清单:${rawPath}(${error instanceof Error ? error.message : String(error)})`);
47
68
  }
48
69
  const source = readPackSource(dir);
70
+ const reference = readDeclaredReference(raw.reference);
49
71
  return {
50
72
  kind: 'source',
51
73
  path: dir,
@@ -58,11 +80,16 @@ function readSourceTarget(dir: string): DoctorTarget {
58
80
  apiVersion: typeof raw.apiVersion === 'number' && Number.isSafeInteger(raw.apiVersion) && raw.apiVersion > 0
59
81
  ? raw.apiVersion
60
82
  : API_VERSION,
83
+ ...(reference ? { reference } : {}),
61
84
  };
62
85
  }
63
86
 
64
87
  function readPackTarget(file: string): DoctorTarget {
65
88
  const pack = readPack(file);
89
+ const reference = pack.manifest.reference;
90
+ const document = reference
91
+ ? pack.files.find((entry) => entry.path.toLowerCase() === reference.entry.toLowerCase())
92
+ : undefined;
66
93
  return {
67
94
  kind: 'pack',
68
95
  path: file,
@@ -73,6 +100,8 @@ function readPackTarget(file: string): DoctorTarget {
73
100
  format: pack.manifest.format,
74
101
  mode: pack.manifest.mode,
75
102
  apiVersion: pack.manifest.apiVersion,
103
+ ...(reference ? { reference } : {}),
104
+ ...(document ? { referenceText: document.bytes.toString('utf8') } : {}),
76
105
  };
77
106
  }
78
107
 
@@ -138,12 +167,48 @@ export function localChecks(target: DoctorTarget): DoctorCheck[] {
138
167
  { ok: existsSync(join(dir, target.server)), label: `服务端入口 ${target.server}` },
139
168
  ];
140
169
  if (target.client) checks.push({ ok: existsSync(join(dir, target.client)), label: `客户端入口 ${target.client}` });
170
+ if (target.reference) {
171
+ const entry = target.reference.entry;
172
+ const valid = isValidGameReferenceEntry(entry);
173
+ checks.push({
174
+ ok: valid,
175
+ label: `资料文档入口 ${entry}`,
176
+ ...(valid ? {} : { detail: '必须是包内 .json 相对路径' }),
177
+ });
178
+ if (valid) {
179
+ const absolute = join(dir, ...entry.split('/'));
180
+ const exists = existsSync(absolute);
181
+ checks.push({ ok: exists, label: `资料文档 ${entry}` });
182
+ if (exists) {
183
+ const parsed = parseGameReference(readFileSync(absolute, 'utf8'));
184
+ checks.push({
185
+ ok: parsed.ok,
186
+ label: '资料文档格式',
187
+ ...(parsed.ok ? {} : { detail: parsed.error }),
188
+ });
189
+ }
190
+ }
191
+ }
141
192
  return checks;
142
193
  }
143
- return [
194
+ const checks: DoctorCheck[] = [
144
195
  { ok: target.format === PACK_FORMAT, label: `包格式 ${target.format}` },
145
196
  { ok: Boolean(target.server), label: `服务端入口 ${target.server}` },
146
197
  ];
198
+ if (target.reference) {
199
+ const entry = target.reference.entry;
200
+ const inPack = target.referenceText !== undefined;
201
+ checks.push({ ok: inPack, label: `资料文档 ${entry} 在包清单里` });
202
+ if (inPack) {
203
+ const parsed = parseGameReference(target.referenceText);
204
+ checks.push({
205
+ ok: parsed.ok,
206
+ label: '资料文档格式',
207
+ ...(parsed.ok ? {} : { detail: parsed.error }),
208
+ });
209
+ }
210
+ }
211
+ return checks;
147
212
  }
148
213
 
149
214
  export async function doctor(target: string, hostUrl?: string): Promise<DoctorReport> {
@@ -6,7 +6,7 @@
6
6
  * --platform 复制到平台的 games/,--start 启动宿主,--host 调 bpmap doctor。
7
7
  */
8
8
  import { createRequire } from 'node:module';
9
- import { copyFileSync, cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
9
+ import { copyFileSync, cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
10
10
  import { dirname, isAbsolute, join, resolve, sep } from 'node:path';
11
11
  import { spawnSync } from 'node:child_process';
12
12
  import { build } from 'esbuild';
@@ -84,6 +84,31 @@ if (hasClient) {
84
84
  }
85
85
  }
86
86
 
87
+ // 资料文档与图片:src/reference/ 里的内容按原样铺到包根,也可只放一个 src/reference.json。
88
+ let referenceEntry = null;
89
+ const referenceDir = join(gameRoot, 'src', 'reference');
90
+ const singleReference = join(gameRoot, 'src', 'reference.json');
91
+ if (existsSync(referenceDir)) {
92
+ for (const item of readdirSync(referenceDir)) {
93
+ cpSync(join(referenceDir, item), join(outDir, item), { recursive: true });
94
+ }
95
+ referenceEntry = typeof pkg.bp?.reference === 'string' ? pkg.bp.reference : 'reference.json';
96
+ if (referenceEntry.includes('..') || isAbsolute(referenceEntry) || referenceEntry.includes('\\')) {
97
+ fail(`package.json 的 bp.reference 必须是包内相对路径:${referenceEntry}`);
98
+ }
99
+ if (!existsSync(join(outDir, ...referenceEntry.split('/')))) {
100
+ fail(`reference 入口不存在:src/reference/${referenceEntry}`);
101
+ }
102
+ } else if (existsSync(singleReference)) {
103
+ if (pkg.bp?.reference !== undefined && pkg.bp.reference !== 'reference.json') {
104
+ fail(`bp.reference 指向 ${pkg.bp.reference},但只找到 src/reference.json`);
105
+ }
106
+ referenceEntry = 'reference.json';
107
+ copyFileSync(singleReference, join(outDir, referenceEntry));
108
+ } else if (pkg.bp?.reference !== undefined) {
109
+ fail('package.json 声明了 bp.reference,但 src/reference/ 与 src/reference.json 都不存在');
110
+ }
111
+
87
112
  const manifest = {
88
113
  id,
89
114
  version,
@@ -91,6 +116,7 @@ const manifest = {
91
116
  apiVersion: pkg.bp?.apiVersion ?? API_VERSION,
92
117
  server: 'server.js',
93
118
  ...(hasClient ? { client: entry } : {}),
119
+ ...(referenceEntry ? { reference: { entry: referenceEntry } } : {}),
94
120
  };
95
121
  writeFileSync(join(outDir, 'bpmap.json'), JSON.stringify(manifest, null, 2) + '\n');
96
122