@sfmc-bds/bds-tools 0.2.0-beta.11 → 0.2.0-beta.13

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.
Files changed (39) hide show
  1. package/dist/bds-manager.d.ts.map +1 -1
  2. package/dist/bds-manager.js +12 -1
  3. package/dist/bds-manager.js.map +2 -2
  4. package/dist/check-update.d.ts.map +1 -1
  5. package/dist/check-update.js +3 -2
  6. package/dist/check-update.js.map +2 -2
  7. package/dist/cli-pack-manager.js +11 -1
  8. package/dist/cli-pack-manager.js.map +2 -2
  9. package/dist/dependency-negotiator.d.ts +73 -0
  10. package/dist/dependency-negotiator.d.ts.map +1 -0
  11. package/dist/dependency-negotiator.js +151 -0
  12. package/dist/dependency-negotiator.js.map +7 -0
  13. package/dist/dependency-negotiator.test.js +120 -0
  14. package/dist/dependency-negotiator.test.js.map +7 -0
  15. package/dist/level-dat.d.ts +87 -0
  16. package/dist/level-dat.d.ts.map +1 -0
  17. package/dist/level-dat.js +326 -0
  18. package/dist/level-dat.js.map +7 -0
  19. package/dist/level-dat.test.js +125 -0
  20. package/dist/level-dat.test.js.map +7 -0
  21. package/dist/pack-manager.d.ts +18 -6
  22. package/dist/pack-manager.d.ts.map +1 -1
  23. package/dist/pack-manager.js +73 -24
  24. package/dist/pack-manager.js.map +2 -2
  25. package/dist/server-properties-i18n.d.ts +17 -0
  26. package/dist/server-properties-i18n.d.ts.map +1 -0
  27. package/dist/server-properties-i18n.js +197 -0
  28. package/dist/server-properties-i18n.js.map +7 -0
  29. package/dist/server-properties.d.ts +22 -0
  30. package/dist/server-properties.d.ts.map +1 -1
  31. package/dist/server-properties.js +126 -1
  32. package/dist/server-properties.js.map +2 -2
  33. package/dist/server-properties.test.js +127 -0
  34. package/dist/server-properties.test.js.map +7 -0
  35. package/dist/world-packs.d.ts +57 -1
  36. package/dist/world-packs.d.ts.map +1 -1
  37. package/dist/world-packs.js +159 -1
  38. package/dist/world-packs.js.map +2 -2
  39. package/package.json +6 -3
@@ -0,0 +1,326 @@
1
+ import fs from "node:fs";
2
+ const TAG_END = 0;
3
+ const TAG_BYTE = 1;
4
+ const TAG_SHORT = 2;
5
+ const TAG_INT = 3;
6
+ const TAG_LONG = 4;
7
+ const TAG_FLOAT = 5;
8
+ const TAG_DOUBLE = 6;
9
+ const TAG_BYTE_ARRAY = 7;
10
+ const TAG_STRING = 8;
11
+ const TAG_LIST = 9;
12
+ const TAG_COMPOUND = 10;
13
+ const TAG_INT_ARRAY = 11;
14
+ const TAG_LONG_ARRAY = 12;
15
+ function skipNbtPayload(buf, offset, type) {
16
+ switch (type) {
17
+ case TAG_BYTE:
18
+ return offset + 1;
19
+ case TAG_SHORT:
20
+ return offset + 2;
21
+ case TAG_INT:
22
+ case TAG_FLOAT:
23
+ return offset + 4;
24
+ case TAG_LONG:
25
+ case TAG_DOUBLE:
26
+ return offset + 8;
27
+ case TAG_BYTE_ARRAY: {
28
+ if (offset + 4 > buf.length) throw new Error("Unexpected EOF reading TAG_Byte_Array length");
29
+ const len = buf.readInt32LE(offset);
30
+ return offset + 4 + Math.max(0, len);
31
+ }
32
+ case TAG_STRING: {
33
+ if (offset + 2 > buf.length) throw new Error("Unexpected EOF reading TAG_String length");
34
+ const len = buf.readUInt16LE(offset);
35
+ return offset + 2 + len;
36
+ }
37
+ case TAG_LIST: {
38
+ if (offset + 5 > buf.length) throw new Error("Unexpected EOF reading TAG_List header");
39
+ const elemType = buf.readUInt8(offset);
40
+ const count = buf.readInt32LE(offset + 1);
41
+ let cur = offset + 5;
42
+ for (let i = 0; i < count; i++) {
43
+ cur = skipNbtPayload(buf, cur, elemType);
44
+ }
45
+ return cur;
46
+ }
47
+ case TAG_COMPOUND: {
48
+ let cur = offset;
49
+ while (cur < buf.length) {
50
+ const t = buf.readUInt8(cur);
51
+ if (t === TAG_END) {
52
+ return cur + 1;
53
+ }
54
+ if (cur + 3 > buf.length) throw new Error("Unexpected EOF reading compound child header");
55
+ const nameLen = buf.readUInt16LE(cur + 1);
56
+ const childValOffset = cur + 3 + nameLen;
57
+ cur = skipNbtPayload(buf, childValOffset, t);
58
+ }
59
+ return cur;
60
+ }
61
+ case TAG_INT_ARRAY: {
62
+ if (offset + 4 > buf.length) throw new Error("Unexpected EOF reading TAG_Int_Array length");
63
+ const len = buf.readInt32LE(offset);
64
+ return offset + 4 + Math.max(0, len) * 4;
65
+ }
66
+ case TAG_LONG_ARRAY: {
67
+ if (offset + 4 > buf.length) throw new Error("Unexpected EOF reading TAG_Long_Array length");
68
+ const len = buf.readInt32LE(offset);
69
+ return offset + 4 + Math.max(0, len) * 8;
70
+ }
71
+ default:
72
+ throw new Error(`Unsupported or unknown NBT tag type: ${type} at offset ${offset}`);
73
+ }
74
+ }
75
+ function parseCompoundChildren(buf, compoundValueOffset) {
76
+ const children = /* @__PURE__ */ new Map();
77
+ let cur = compoundValueOffset;
78
+ while (cur < buf.length) {
79
+ const tagType = buf.readUInt8(cur);
80
+ if (tagType === TAG_END) {
81
+ return { children, compoundEndOffset: cur + 1 };
82
+ }
83
+ if (cur + 3 > buf.length) {
84
+ throw new Error(`Unexpected EOF reading named tag header at offset ${cur}`);
85
+ }
86
+ const nameLen = buf.readUInt16LE(cur + 1);
87
+ const nameOffset = cur + 3;
88
+ if (nameOffset + nameLen > buf.length) {
89
+ throw new Error(`Unexpected EOF reading tag name at offset ${cur}`);
90
+ }
91
+ const name = buf.toString("utf8", nameOffset, nameOffset + nameLen);
92
+ const valOffset = nameOffset + nameLen;
93
+ const endOffset = skipNbtPayload(buf, valOffset, tagType);
94
+ let val = void 0;
95
+ if (tagType === TAG_BYTE) {
96
+ val = buf.readInt8(valOffset);
97
+ } else if (tagType === TAG_INT) {
98
+ val = buf.readInt32LE(valOffset);
99
+ } else if (tagType === TAG_STRING) {
100
+ const sLen = buf.readUInt16LE(valOffset);
101
+ val = buf.toString("utf8", valOffset + 2, valOffset + 2 + sLen);
102
+ }
103
+ children.set(name, {
104
+ type: tagType,
105
+ name,
106
+ startOffset: cur,
107
+ nameOffset,
108
+ valueOffset: valOffset,
109
+ endOffset,
110
+ value: val
111
+ });
112
+ cur = endOffset;
113
+ }
114
+ return { children, compoundEndOffset: cur };
115
+ }
116
+ function parseBedrockLevelDat(buf) {
117
+ if (buf.length < 8) {
118
+ throw new Error("Invalid level.dat: buffer smaller than 8-byte header");
119
+ }
120
+ const version = buf.readUInt32LE(0);
121
+ const dataLength = buf.readUInt32LE(4);
122
+ if (buf.length < 9 || buf.readUInt8(8) !== TAG_COMPOUND) {
123
+ throw new Error("Invalid level.dat: root tag is not TAG_Compound");
124
+ }
125
+ const rootNameLen = buf.readUInt16LE(9);
126
+ const rootCompoundName = buf.toString("utf8", 11, 11 + rootNameLen);
127
+ const rootValueOffset = 11 + rootNameLen;
128
+ const { children: rootChildren, compoundEndOffset: rootEndOffset } = parseCompoundChildren(buf, rootValueOffset);
129
+ return {
130
+ version,
131
+ dataLength,
132
+ rootCompoundName,
133
+ rootChildren,
134
+ rootEndOffset
135
+ };
136
+ }
137
+ function readLevelDatExperiments(levelDatPath) {
138
+ if (!fs.existsSync(levelDatPath)) return null;
139
+ try {
140
+ const buf = fs.readFileSync(levelDatPath);
141
+ const parsed = parseBedrockLevelDat(buf);
142
+ let experimentsEverUsed = false;
143
+ const everUsedTag = parsed.rootChildren.get("experiments_ever_used");
144
+ if (everUsedTag && everUsedTag.type === TAG_BYTE && Number(everUsedTag.value) === 1) {
145
+ experimentsEverUsed = true;
146
+ }
147
+ let savedWithToggledExperiments = false;
148
+ const savedTag = parsed.rootChildren.get("saved_with_toggled_experiments");
149
+ if (savedTag && savedTag.type === TAG_BYTE && Number(savedTag.value) === 1) {
150
+ savedWithToggledExperiments = true;
151
+ }
152
+ const experiments = {};
153
+ let hasBetaApis = false;
154
+ const expCompoundTag = parsed.rootChildren.get("experiments");
155
+ if (expCompoundTag && expCompoundTag.type === TAG_COMPOUND) {
156
+ const expChildren = parseCompoundChildren(buf, expCompoundTag.valueOffset).children;
157
+ const innerEverUsed = expChildren.get("experiments_ever_used");
158
+ if (innerEverUsed && Number(innerEverUsed.value) === 1) {
159
+ experimentsEverUsed = true;
160
+ }
161
+ const innerSaved = expChildren.get("saved_with_toggled_experiments");
162
+ if (innerSaved && Number(innerSaved.value) === 1) {
163
+ savedWithToggledExperiments = true;
164
+ }
165
+ for (const [name, meta] of expChildren.entries()) {
166
+ if (meta.type === TAG_BYTE) {
167
+ const num = Number(meta.value);
168
+ experiments[name] = num;
169
+ if (name === "gametest" && num === 1) {
170
+ hasBetaApis = true;
171
+ }
172
+ }
173
+ }
174
+ }
175
+ return {
176
+ experimentsEverUsed,
177
+ savedWithToggledExperiments,
178
+ experiments,
179
+ hasBetaApis
180
+ };
181
+ } catch {
182
+ return null;
183
+ }
184
+ }
185
+ function createByteTagBuffer(name, value) {
186
+ const nameBuf = Buffer.from(name, "utf8");
187
+ const buf = Buffer.alloc(1 + 2 + nameBuf.length + 1);
188
+ buf.writeUInt8(TAG_BYTE, 0);
189
+ buf.writeUInt16LE(nameBuf.length, 1);
190
+ nameBuf.copy(buf, 3);
191
+ buf.writeInt8(value, 3 + nameBuf.length);
192
+ return buf;
193
+ }
194
+ function createCompoundTagBuffer(name, byteTags) {
195
+ const nameBuf = Buffer.from(name, "utf8");
196
+ const childBuffers = [];
197
+ for (const [k, v] of Object.entries(byteTags)) {
198
+ childBuffers.push(createByteTagBuffer(k, v));
199
+ }
200
+ childBuffers.push(Buffer.from([TAG_END]));
201
+ const header = Buffer.alloc(1 + 2 + nameBuf.length);
202
+ header.writeUInt8(TAG_COMPOUND, 0);
203
+ header.writeUInt16LE(nameBuf.length, 1);
204
+ nameBuf.copy(header, 3);
205
+ return Buffer.concat([header, ...childBuffers]);
206
+ }
207
+ async function enableBetaApisInLevelDat(levelDatPath) {
208
+ if (!fs.existsSync(levelDatPath)) {
209
+ return { success: false, changed: false, error: `File not found: ${levelDatPath}` };
210
+ }
211
+ try {
212
+ const raw = await fs.promises.readFile(levelDatPath);
213
+ const parsed = parseBedrockLevelDat(raw);
214
+ const expCompoundTag = parsed.rootChildren.get("experiments");
215
+ let currentBetaState = false;
216
+ if (expCompoundTag && expCompoundTag.type === TAG_COMPOUND) {
217
+ const expChildren = parseCompoundChildren(raw, expCompoundTag.valueOffset).children;
218
+ const gametest = expChildren.get("gametest");
219
+ if (gametest && Number(gametest.value) === 1) {
220
+ currentBetaState = true;
221
+ }
222
+ }
223
+ if (currentBetaState) {
224
+ return {
225
+ success: true,
226
+ changed: false,
227
+ previousBetaApisState: true
228
+ };
229
+ }
230
+ const backupPath = `${levelDatPath}.bak`;
231
+ await fs.promises.copyFile(levelDatPath, backupPath);
232
+ let nbtBody;
233
+ if (!expCompoundTag) {
234
+ const insertCompoundBuf = createCompoundTagBuffer("experiments", {
235
+ experiments_ever_used: 1,
236
+ saved_with_toggled_experiments: 1,
237
+ gametest: 1
238
+ });
239
+ const rootEndTagIndex = parsed.rootEndOffset - 1;
240
+ const beforeEnd = raw.subarray(8, rootEndTagIndex);
241
+ const afterEnd = raw.subarray(rootEndTagIndex);
242
+ nbtBody = Buffer.concat([beforeEnd, insertCompoundBuf, afterEnd]);
243
+ } else {
244
+ const { children: expChildren, compoundEndOffset: expEndOffset } = parseCompoundChildren(
245
+ raw,
246
+ expCompoundTag.valueOffset
247
+ );
248
+ const expEndTagIndex = expEndOffset - 1;
249
+ const toAppend = [];
250
+ let mutatedRaw = Buffer.from(raw);
251
+ const gametestTag = expChildren.get("gametest");
252
+ if (gametestTag) {
253
+ mutatedRaw.writeInt8(1, gametestTag.valueOffset);
254
+ } else {
255
+ toAppend.push(createByteTagBuffer("gametest", 1));
256
+ }
257
+ const everUsedTag = expChildren.get("experiments_ever_used");
258
+ if (everUsedTag) {
259
+ mutatedRaw.writeInt8(1, everUsedTag.valueOffset);
260
+ } else {
261
+ toAppend.push(createByteTagBuffer("experiments_ever_used", 1));
262
+ }
263
+ const savedTag = expChildren.get("saved_with_toggled_experiments");
264
+ if (savedTag) {
265
+ mutatedRaw.writeInt8(1, savedTag.valueOffset);
266
+ } else {
267
+ toAppend.push(createByteTagBuffer("saved_with_toggled_experiments", 1));
268
+ }
269
+ const rootEverUsed = parsed.rootChildren.get("experiments_ever_used");
270
+ if (rootEverUsed) {
271
+ mutatedRaw.writeInt8(1, rootEverUsed.valueOffset);
272
+ }
273
+ const rootSaved = parsed.rootChildren.get("saved_with_toggled_experiments");
274
+ if (rootSaved) {
275
+ mutatedRaw.writeInt8(1, rootSaved.valueOffset);
276
+ }
277
+ if (toAppend.length > 0) {
278
+ const beforeExpEnd = mutatedRaw.subarray(8, expEndTagIndex);
279
+ const afterExpEnd = mutatedRaw.subarray(expEndTagIndex);
280
+ nbtBody = Buffer.concat([beforeExpEnd, ...toAppend, afterExpEnd]);
281
+ } else {
282
+ nbtBody = mutatedRaw.subarray(8);
283
+ }
284
+ }
285
+ const newHeader = Buffer.alloc(8);
286
+ newHeader.writeUInt32LE(parsed.version, 0);
287
+ newHeader.writeUInt32LE(nbtBody.length, 4);
288
+ const finalFileBuffer = Buffer.concat([newHeader, nbtBody]);
289
+ const tmpFile = `${levelDatPath}.${process.pid}.tmp`;
290
+ await fs.promises.writeFile(tmpFile, finalFileBuffer);
291
+ await fs.promises.rename(tmpFile, levelDatPath);
292
+ return {
293
+ success: true,
294
+ changed: true,
295
+ backupPath,
296
+ previousBetaApisState: false
297
+ };
298
+ } catch (err) {
299
+ return {
300
+ success: false,
301
+ changed: false,
302
+ error: err instanceof Error ? err.message : String(err)
303
+ };
304
+ }
305
+ }
306
+ export {
307
+ TAG_BYTE,
308
+ TAG_BYTE_ARRAY,
309
+ TAG_COMPOUND,
310
+ TAG_DOUBLE,
311
+ TAG_END,
312
+ TAG_FLOAT,
313
+ TAG_INT,
314
+ TAG_INT_ARRAY,
315
+ TAG_LIST,
316
+ TAG_LONG,
317
+ TAG_LONG_ARRAY,
318
+ TAG_SHORT,
319
+ TAG_STRING,
320
+ enableBetaApisInLevelDat,
321
+ parseBedrockLevelDat,
322
+ parseCompoundChildren,
323
+ readLevelDatExperiments,
324
+ skipNbtPayload
325
+ };
326
+ //# sourceMappingURL=level-dat.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/level-dat.ts"],
4
+ "sourcesContent": ["/**\n * level-dat.ts \u2014 Minecraft \u57FA\u5CA9\u7248\u4E16\u754C\u5B58\u6863 level.dat \u5C0F\u7AEF\u5E8F NBT \u89E3\u6790\u4E0E\u5B9E\u9A8C\u6027\u73A9\u6CD5\u5B89\u5168\u4FEE\u6539\u5668\n *\n * \u57FA\u5CA9\u7248 level.dat \u89C4\u8303\uFF1A\n * - Header\uFF088 \u5B57\u8282\uFF09\uFF1A\n * - [0..3] uint32 LE\uFF1A\u5B58\u50A8\u683C\u5F0F\u7248\u672C\uFF08\u5F53\u524D\u7248\u672C\u901A\u5E38\u4E3A 10\uFF09\n * - [4..7] uint32 LE\uFF1A\u6709\u6548 NBT \u6570\u636E\u5B57\u8282\u957F\u5EA6\uFF08data_length\uFF09\n * - Payload\uFF1A\u672A\u538B\u7F29\u7684\u5C0F\u7AEF\u5E8F\uFF08Little-Endian\uFF09\u6807\u51C6 NBT \u590D\u5408\u6807\u7B7E\uFF08TAG_Compound\uFF09\n *\n * \u6838\u5FC3\u80FD\u529B\uFF1A\n * - \u539F\u751F\u65E0\u5916\u90E8\u9ED1\u76D2\u4F9D\u8D56\uFF0CBuffer \u7EA7\u89E3\u6790\u4E0E\u7CBE\u786E\u5B57\u8282\u4F4D\u79FB\n * - \u8BFB\u53D6\u4E16\u754C\u5B9E\u9A8C\u6027\u73A9\u6CD5\u7684\u5F00\u542F\u72B6\u6001\uFF08\u7279\u522B\u662F Beta APIs / gametest\uFF09\n * - \u5B89\u5168\u6CE8\u5165\u6216\u5207\u6362\u5B9E\u9A8C\u6027\u5F00\u5173\u5E76\u81EA\u52A8\u5907\u4EFD\u539F\u6587\u4EF6\uFF08.bak\uFF09\u4E0E\u6821\u51C6 Header data_length\n */\n\nimport fs from \"node:fs\";\n\nexport const TAG_END = 0;\nexport const TAG_BYTE = 1;\nexport const TAG_SHORT = 2;\nexport const TAG_INT = 3;\nexport const TAG_LONG = 4;\nexport const TAG_FLOAT = 5;\nexport const TAG_DOUBLE = 6;\nexport const TAG_BYTE_ARRAY = 7;\nexport const TAG_STRING = 8;\nexport const TAG_LIST = 9;\nexport const TAG_COMPOUND = 10;\nexport const TAG_INT_ARRAY = 11;\nexport const TAG_LONG_ARRAY = 12;\n\nexport interface NbtTagMeta {\n type: number;\n name: string;\n startOffset: number; // \u5305\u542B tagType \u7684\u8D77\u59CB\u7EDD\u5BF9 offset\n nameOffset: number; // \u6807\u7B7E\u540D\u79F0\u8D77\u59CB offset\n valueOffset: number; // \u8F7D\u8377\u8D77\u59CB offset\n endOffset: number; // \u6807\u7B7E\u7ED3\u675F\u7EDD\u5BF9 offset\n value?: unknown;\n}\n\nexport interface LevelDatExperimentsInfo {\n experimentsEverUsed: boolean;\n savedWithToggledExperiments: boolean;\n experiments: Record<string, number | boolean>;\n hasBetaApis: boolean;\n}\n\nexport interface LevelDatMutateResult {\n success: boolean;\n changed: boolean;\n backupPath?: string;\n error?: string;\n previousBetaApisState?: boolean;\n}\n\n/**\n * \u904D\u5386\u5E76\u8DF3\u8FC7\u6307\u5B9A\u7C7B\u578B\u7684 NBT \u8F7D\u8377\uFF0C\u8FD4\u56DE\u4E0B\u4E00\u4E2A tag \u7684 offset\u3002\n */\nexport function skipNbtPayload(buf: Buffer, offset: number, type: number): number {\n switch (type) {\n case TAG_BYTE:\n return offset + 1;\n case TAG_SHORT:\n return offset + 2;\n case TAG_INT:\n case TAG_FLOAT:\n return offset + 4;\n case TAG_LONG:\n case TAG_DOUBLE:\n return offset + 8;\n case TAG_BYTE_ARRAY: {\n if (offset + 4 > buf.length) throw new Error(\"Unexpected EOF reading TAG_Byte_Array length\");\n const len = buf.readInt32LE(offset);\n return offset + 4 + Math.max(0, len);\n }\n case TAG_STRING: {\n if (offset + 2 > buf.length) throw new Error(\"Unexpected EOF reading TAG_String length\");\n const len = buf.readUInt16LE(offset);\n return offset + 2 + len;\n }\n case TAG_LIST: {\n if (offset + 5 > buf.length) throw new Error(\"Unexpected EOF reading TAG_List header\");\n const elemType = buf.readUInt8(offset);\n const count = buf.readInt32LE(offset + 1);\n let cur = offset + 5;\n for (let i = 0; i < count; i++) {\n cur = skipNbtPayload(buf, cur, elemType);\n }\n return cur;\n }\n case TAG_COMPOUND: {\n let cur = offset;\n while (cur < buf.length) {\n const t = buf.readUInt8(cur);\n if (t === TAG_END) {\n return cur + 1;\n }\n if (cur + 3 > buf.length) throw new Error(\"Unexpected EOF reading compound child header\");\n const nameLen = buf.readUInt16LE(cur + 1);\n const childValOffset = cur + 3 + nameLen;\n cur = skipNbtPayload(buf, childValOffset, t);\n }\n return cur;\n }\n case TAG_INT_ARRAY: {\n if (offset + 4 > buf.length) throw new Error(\"Unexpected EOF reading TAG_Int_Array length\");\n const len = buf.readInt32LE(offset);\n return offset + 4 + Math.max(0, len) * 4;\n }\n case TAG_LONG_ARRAY: {\n if (offset + 4 > buf.length) throw new Error(\"Unexpected EOF reading TAG_Long_Array length\");\n const len = buf.readInt32LE(offset);\n return offset + 4 + Math.max(0, len) * 8;\n }\n default:\n throw new Error(`Unsupported or unknown NBT tag type: ${type} at offset ${offset}`);\n }\n}\n\n/**\n * \u89E3\u6790\u590D\u5408\u6807\u7B7E\u5185\u90E8\u6240\u6709\u76F4\u63A5\u5B50\u6807\u7B7E\u7684\u5143\u6570\u636E\u6620\u5C04\u3002\n */\nexport function parseCompoundChildren(\n buf: Buffer,\n compoundValueOffset: number\n): { children: Map<string, NbtTagMeta>; compoundEndOffset: number } {\n const children = new Map<string, NbtTagMeta>();\n let cur = compoundValueOffset;\n\n while (cur < buf.length) {\n const tagType = buf.readUInt8(cur);\n if (tagType === TAG_END) {\n return { children, compoundEndOffset: cur + 1 };\n }\n if (cur + 3 > buf.length) {\n throw new Error(`Unexpected EOF reading named tag header at offset ${cur}`);\n }\n const nameLen = buf.readUInt16LE(cur + 1);\n const nameOffset = cur + 3;\n if (nameOffset + nameLen > buf.length) {\n throw new Error(`Unexpected EOF reading tag name at offset ${cur}`);\n }\n const name = buf.toString(\"utf8\", nameOffset, nameOffset + nameLen);\n const valOffset = nameOffset + nameLen;\n const endOffset = skipNbtPayload(buf, valOffset, tagType);\n\n let val: unknown = undefined;\n if (tagType === TAG_BYTE) {\n val = buf.readInt8(valOffset);\n } else if (tagType === TAG_INT) {\n val = buf.readInt32LE(valOffset);\n } else if (tagType === TAG_STRING) {\n const sLen = buf.readUInt16LE(valOffset);\n val = buf.toString(\"utf8\", valOffset + 2, valOffset + 2 + sLen);\n }\n\n children.set(name, {\n type: tagType,\n name,\n startOffset: cur,\n nameOffset,\n valueOffset: valOffset,\n endOffset,\n value: val,\n });\n\n cur = endOffset;\n }\n\n return { children, compoundEndOffset: cur };\n}\n\n/**\n * \u89E3\u6790\u57FA\u5CA9\u7248 level.dat \u7684\u5B8C\u6574\u6587\u4EF6\u7ED3\u6784\u5E76\u5B9A\u4F4D\u6839 Compound\u3002\n */\nexport function parseBedrockLevelDat(buf: Buffer): {\n version: number;\n dataLength: number;\n rootCompoundName: string;\n rootChildren: Map<string, NbtTagMeta>;\n rootEndOffset: number;\n} {\n if (buf.length < 8) {\n throw new Error(\"Invalid level.dat: buffer smaller than 8-byte header\");\n }\n const version = buf.readUInt32LE(0);\n const dataLength = buf.readUInt32LE(4);\n\n // \u6839\u6807\u7B7E\u5FC5\u987B\u662F TAG_Compound\n if (buf.length < 9 || buf.readUInt8(8) !== TAG_COMPOUND) {\n throw new Error(\"Invalid level.dat: root tag is not TAG_Compound\");\n }\n const rootNameLen = buf.readUInt16LE(9);\n const rootCompoundName = buf.toString(\"utf8\", 11, 11 + rootNameLen);\n const rootValueOffset = 11 + rootNameLen;\n\n const { children: rootChildren, compoundEndOffset: rootEndOffset } = parseCompoundChildren(buf, rootValueOffset);\n\n return {\n version,\n dataLength,\n rootCompoundName,\n rootChildren,\n rootEndOffset,\n };\n}\n\n/**\n * \u8BFB\u53D6\u4E16\u754C\u5B58\u6863 level.dat \u7684\u5B9E\u9A8C\u6027\u914D\u7F6E\u3002\u82E5\u89E3\u6790\u5931\u8D25\u6216\u6587\u4EF6\u4E0D\u5B58\u5728\u8FD4\u56DE null\u3002\n */\nexport function readLevelDatExperiments(levelDatPath: string): LevelDatExperimentsInfo | null {\n if (!fs.existsSync(levelDatPath)) return null;\n try {\n const buf = fs.readFileSync(levelDatPath);\n const parsed = parseBedrockLevelDat(buf);\n\n let experimentsEverUsed = false;\n const everUsedTag = parsed.rootChildren.get(\"experiments_ever_used\");\n if (everUsedTag && everUsedTag.type === TAG_BYTE && Number(everUsedTag.value) === 1) {\n experimentsEverUsed = true;\n }\n\n let savedWithToggledExperiments = false;\n const savedTag = parsed.rootChildren.get(\"saved_with_toggled_experiments\");\n if (savedTag && savedTag.type === TAG_BYTE && Number(savedTag.value) === 1) {\n savedWithToggledExperiments = true;\n }\n\n const experiments: Record<string, number | boolean> = {};\n let hasBetaApis = false;\n\n const expCompoundTag = parsed.rootChildren.get(\"experiments\");\n if (expCompoundTag && expCompoundTag.type === TAG_COMPOUND) {\n const expChildren = parseCompoundChildren(buf, expCompoundTag.valueOffset).children;\n\n // \u90E8\u5206\u7248\u672C experiments_ever_used \u4E5F\u53EF\u80FD\u4F4D\u4E8E experiments \u5185\u90E8\n const innerEverUsed = expChildren.get(\"experiments_ever_used\");\n if (innerEverUsed && Number(innerEverUsed.value) === 1) {\n experimentsEverUsed = true;\n }\n const innerSaved = expChildren.get(\"saved_with_toggled_experiments\");\n if (innerSaved && Number(innerSaved.value) === 1) {\n savedWithToggledExperiments = true;\n }\n\n for (const [name, meta] of expChildren.entries()) {\n if (meta.type === TAG_BYTE) {\n const num = Number(meta.value);\n experiments[name] = num;\n if (name === \"gametest\" && num === 1) {\n hasBetaApis = true;\n }\n }\n }\n }\n\n return {\n experimentsEverUsed,\n savedWithToggledExperiments,\n experiments,\n hasBetaApis,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * \u6784\u9020\u4E00\u4E2A TAG_Byte \u7684\u4E8C\u8FDB\u5236 Buffer\u3002\n */\nfunction createByteTagBuffer(name: string, value: number): Buffer {\n const nameBuf = Buffer.from(name, \"utf8\");\n const buf = Buffer.alloc(1 + 2 + nameBuf.length + 1);\n buf.writeUInt8(TAG_BYTE, 0);\n buf.writeUInt16LE(nameBuf.length, 1);\n nameBuf.copy(buf, 3);\n buf.writeInt8(value, 3 + nameBuf.length);\n return buf;\n}\n\n/**\n * \u6784\u9020\u4E00\u4E2A\u5305\u542B\u6307\u5B9A\u952E\u503C\u5BF9\u7684 TAG_Compound Buffer\u3002\n */\nfunction createCompoundTagBuffer(name: string, byteTags: Record<string, number>): Buffer {\n const nameBuf = Buffer.from(name, \"utf8\");\n const childBuffers: Buffer[] = [];\n for (const [k, v] of Object.entries(byteTags)) {\n childBuffers.push(createByteTagBuffer(k, v));\n }\n childBuffers.push(Buffer.from([TAG_END]));\n\n const header = Buffer.alloc(1 + 2 + nameBuf.length);\n header.writeUInt8(TAG_COMPOUND, 0);\n header.writeUInt16LE(nameBuf.length, 1);\n nameBuf.copy(header, 3);\n\n return Buffer.concat([header, ...childBuffers]);\n}\n\n/**\n * \u4E3A\u6307\u5B9A level.dat \u5F00\u542F Beta APIs\uFF08gametest\uFF09\u3002\n *\n * \u4FDD\u8BC1\uFF1A\n * - \u81EA\u52A8\u5907\u4EFD\u539F\u6587\u4EF6\u81F3 `${levelDatPath}.bak`\uFF1B\n * - \u81EA\u52A8\u66F4\u65B0 experiments \u590D\u5408\u6807\u7B7E\u4E2D\u7684 gametest = 1b\uFF1B\n * - \u81EA\u52A8\u66F4\u65B0 experiments_ever_used = 1b \u4E0E saved_with_toggled_experiments = 1b\uFF1B\n * - \u7CBE\u786E\u6821\u51C6 8 \u5B57\u8282\u6587\u4EF6\u5934\u90E8\u7684 dataLength\uFF1B\n * - \u539F\u5B50\u5199\u64CD\u4F5C\uFF08.tmp -> rename\uFF09\uFF1B\n * - \u82E5\u5DF2\u5904\u4E8E\u5F00\u542F\u72B6\u6001\uFF0C\u76F4\u63A5\u8FD4\u56DE changed: false\uFF0C\u4E0D\u7834\u574F\u6587\u4EF6\u3002\n */\nexport async function enableBetaApisInLevelDat(levelDatPath: string): Promise<LevelDatMutateResult> {\n if (!fs.existsSync(levelDatPath)) {\n return { success: false, changed: false, error: `File not found: ${levelDatPath}` };\n }\n\n try {\n const raw = await fs.promises.readFile(levelDatPath);\n const parsed = parseBedrockLevelDat(raw);\n\n const expCompoundTag = parsed.rootChildren.get(\"experiments\");\n let currentBetaState = false;\n\n if (expCompoundTag && expCompoundTag.type === TAG_COMPOUND) {\n const expChildren = parseCompoundChildren(raw, expCompoundTag.valueOffset).children;\n const gametest = expChildren.get(\"gametest\");\n if (gametest && Number(gametest.value) === 1) {\n currentBetaState = true;\n }\n }\n\n if (currentBetaState) {\n return {\n success: true,\n changed: false,\n previousBetaApisState: true,\n };\n }\n\n // \u9700\u8981\u8FDB\u884C\u5907\u4EFD\n const backupPath = `${levelDatPath}.bak`;\n await fs.promises.copyFile(levelDatPath, backupPath);\n\n let nbtBody: Buffer;\n\n if (!expCompoundTag) {\n // \u573A\u666F 1\uFF1A\u5B8C\u5168\u7F3A\u5931 experiments compound\uFF0C\u5728\u6839 compound \u7ED3\u675F\u6807\u7B7E\u524D\u8FFD\u52A0\u5B8C\u6574 experiments compound\n const insertCompoundBuf = createCompoundTagBuffer(\"experiments\", {\n experiments_ever_used: 1,\n saved_with_toggled_experiments: 1,\n gametest: 1,\n });\n\n // \u6839\u6807\u7B7E\u7ED3\u675F\u70B9\u5728 parsed.rootEndOffset - 1\uFF08TAG_END \u5B57\u8282\u6240\u5728\u4F4D\u7F6E\uFF09\n const rootEndTagIndex = parsed.rootEndOffset - 1;\n const beforeEnd = raw.subarray(8, rootEndTagIndex);\n const afterEnd = raw.subarray(rootEndTagIndex); // \u5305\u542B TAG_END \u53CA\u540E\u7EED\uFF08\u82E5\u6709\uFF09\n nbtBody = Buffer.concat([beforeEnd, insertCompoundBuf, afterEnd]);\n } else {\n // \u573A\u666F 2\uFF1A\u5DF2\u6709 experiments compound\uFF0C\u5728 experiments compound \u5185\u90E8\u66F4\u65B0\u6216\u63D2\u5165\u7F3A\u5931\u5B57\u6BB5\n const { children: expChildren, compoundEndOffset: expEndOffset } = parseCompoundChildren(\n raw,\n expCompoundTag.valueOffset\n );\n const expEndTagIndex = expEndOffset - 1; // \u5185\u90E8 TAG_END \u6240\u5728\u7EDD\u5BF9\u7D22\u5F15\n\n // \u7EC4\u88C5\u8981\u5728 experiments \u5185\u90E8\u8FFD\u52A0\u7684 tag\uFF08\u82E5\u4E0D\u5B58\u5728\uFF09\n const toAppend: Buffer[] = [];\n let mutatedRaw = Buffer.from(raw);\n\n // \u5904\u7406 gametest\n const gametestTag = expChildren.get(\"gametest\");\n if (gametestTag) {\n mutatedRaw.writeInt8(1, gametestTag.valueOffset);\n } else {\n toAppend.push(createByteTagBuffer(\"gametest\", 1));\n }\n\n // \u5904\u7406 experiments_ever_used\n const everUsedTag = expChildren.get(\"experiments_ever_used\");\n if (everUsedTag) {\n mutatedRaw.writeInt8(1, everUsedTag.valueOffset);\n } else {\n toAppend.push(createByteTagBuffer(\"experiments_ever_used\", 1));\n }\n\n // \u5904\u7406 saved_with_toggled_experiments\n const savedTag = expChildren.get(\"saved_with_toggled_experiments\");\n if (savedTag) {\n mutatedRaw.writeInt8(1, savedTag.valueOffset);\n } else {\n toAppend.push(createByteTagBuffer(\"saved_with_toggled_experiments\", 1));\n }\n\n // \u4E5F\u628A root \u5C42\u7684 experiments_ever_used \u8BBE\u4E3A 1\uFF08\u82E5\u5B58\u5728\uFF09\n const rootEverUsed = parsed.rootChildren.get(\"experiments_ever_used\");\n if (rootEverUsed) {\n mutatedRaw.writeInt8(1, rootEverUsed.valueOffset);\n }\n const rootSaved = parsed.rootChildren.get(\"saved_with_toggled_experiments\");\n if (rootSaved) {\n mutatedRaw.writeInt8(1, rootSaved.valueOffset);\n }\n\n if (toAppend.length > 0) {\n const beforeExpEnd = mutatedRaw.subarray(8, expEndTagIndex);\n const afterExpEnd = mutatedRaw.subarray(expEndTagIndex);\n nbtBody = Buffer.concat([beforeExpEnd, ...toAppend, afterExpEnd]);\n } else {\n nbtBody = mutatedRaw.subarray(8);\n }\n }\n\n // \u91CD\u65B0\u6784\u9020 8 \u5B57\u8282 header\n const newHeader = Buffer.alloc(8);\n newHeader.writeUInt32LE(parsed.version, 0);\n newHeader.writeUInt32LE(nbtBody.length, 4);\n\n const finalFileBuffer = Buffer.concat([newHeader, nbtBody]);\n\n // \u539F\u5B50\u66FF\u6362\n const tmpFile = `${levelDatPath}.${process.pid}.tmp`;\n await fs.promises.writeFile(tmpFile, finalFileBuffer);\n await fs.promises.rename(tmpFile, levelDatPath);\n\n return {\n success: true,\n changed: true,\n backupPath,\n previousBetaApisState: false,\n };\n } catch (err) {\n return {\n success: false,\n changed: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n"],
5
+ "mappings": "AAeA,OAAO,QAAQ;AAER,MAAM,UAAU;AAChB,MAAM,WAAW;AACjB,MAAM,YAAY;AAClB,MAAM,UAAU;AAChB,MAAM,WAAW;AACjB,MAAM,YAAY;AAClB,MAAM,aAAa;AACnB,MAAM,iBAAiB;AACvB,MAAM,aAAa;AACnB,MAAM,WAAW;AACjB,MAAM,eAAe;AACrB,MAAM,gBAAgB;AACtB,MAAM,iBAAiB;AA8BvB,SAAS,eAAe,KAAa,QAAgB,MAAsB;AAChF,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,SAAS;AAAA,IAClB,KAAK;AACH,aAAO,SAAS;AAAA,IAClB,KAAK;AAAA,IACL,KAAK;AACH,aAAO,SAAS;AAAA,IAClB,KAAK;AAAA,IACL,KAAK;AACH,aAAO,SAAS;AAAA,IAClB,KAAK,gBAAgB;AACnB,UAAI,SAAS,IAAI,IAAI,OAAQ,OAAM,IAAI,MAAM,8CAA8C;AAC3F,YAAM,MAAM,IAAI,YAAY,MAAM;AAClC,aAAO,SAAS,IAAI,KAAK,IAAI,GAAG,GAAG;AAAA,IACrC;AAAA,IACA,KAAK,YAAY;AACf,UAAI,SAAS,IAAI,IAAI,OAAQ,OAAM,IAAI,MAAM,0CAA0C;AACvF,YAAM,MAAM,IAAI,aAAa,MAAM;AACnC,aAAO,SAAS,IAAI;AAAA,IACtB;AAAA,IACA,KAAK,UAAU;AACb,UAAI,SAAS,IAAI,IAAI,OAAQ,OAAM,IAAI,MAAM,wCAAwC;AACrF,YAAM,WAAW,IAAI,UAAU,MAAM;AACrC,YAAM,QAAQ,IAAI,YAAY,SAAS,CAAC;AACxC,UAAI,MAAM,SAAS;AACnB,eAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,cAAM,eAAe,KAAK,KAAK,QAAQ;AAAA,MACzC;AACA,aAAO;AAAA,IACT;AAAA,IACA,KAAK,cAAc;AACjB,UAAI,MAAM;AACV,aAAO,MAAM,IAAI,QAAQ;AACvB,cAAM,IAAI,IAAI,UAAU,GAAG;AAC3B,YAAI,MAAM,SAAS;AACjB,iBAAO,MAAM;AAAA,QACf;AACA,YAAI,MAAM,IAAI,IAAI,OAAQ,OAAM,IAAI,MAAM,8CAA8C;AACxF,cAAM,UAAU,IAAI,aAAa,MAAM,CAAC;AACxC,cAAM,iBAAiB,MAAM,IAAI;AACjC,cAAM,eAAe,KAAK,gBAAgB,CAAC;AAAA,MAC7C;AACA,aAAO;AAAA,IACT;AAAA,IACA,KAAK,eAAe;AAClB,UAAI,SAAS,IAAI,IAAI,OAAQ,OAAM,IAAI,MAAM,6CAA6C;AAC1F,YAAM,MAAM,IAAI,YAAY,MAAM;AAClC,aAAO,SAAS,IAAI,KAAK,IAAI,GAAG,GAAG,IAAI;AAAA,IACzC;AAAA,IACA,KAAK,gBAAgB;AACnB,UAAI,SAAS,IAAI,IAAI,OAAQ,OAAM,IAAI,MAAM,8CAA8C;AAC3F,YAAM,MAAM,IAAI,YAAY,MAAM;AAClC,aAAO,SAAS,IAAI,KAAK,IAAI,GAAG,GAAG,IAAI;AAAA,IACzC;AAAA,IACA;AACE,YAAM,IAAI,MAAM,wCAAwC,IAAI,cAAc,MAAM,EAAE;AAAA,EACtF;AACF;AAKO,SAAS,sBACd,KACA,qBACkE;AAClE,QAAM,WAAW,oBAAI,IAAwB;AAC7C,MAAI,MAAM;AAEV,SAAO,MAAM,IAAI,QAAQ;AACvB,UAAM,UAAU,IAAI,UAAU,GAAG;AACjC,QAAI,YAAY,SAAS;AACvB,aAAO,EAAE,UAAU,mBAAmB,MAAM,EAAE;AAAA,IAChD;AACA,QAAI,MAAM,IAAI,IAAI,QAAQ;AACxB,YAAM,IAAI,MAAM,qDAAqD,GAAG,EAAE;AAAA,IAC5E;AACA,UAAM,UAAU,IAAI,aAAa,MAAM,CAAC;AACxC,UAAM,aAAa,MAAM;AACzB,QAAI,aAAa,UAAU,IAAI,QAAQ;AACrC,YAAM,IAAI,MAAM,6CAA6C,GAAG,EAAE;AAAA,IACpE;AACA,UAAM,OAAO,IAAI,SAAS,QAAQ,YAAY,aAAa,OAAO;AAClE,UAAM,YAAY,aAAa;AAC/B,UAAM,YAAY,eAAe,KAAK,WAAW,OAAO;AAExD,QAAI,MAAe;AACnB,QAAI,YAAY,UAAU;AACxB,YAAM,IAAI,SAAS,SAAS;AAAA,IAC9B,WAAW,YAAY,SAAS;AAC9B,YAAM,IAAI,YAAY,SAAS;AAAA,IACjC,WAAW,YAAY,YAAY;AACjC,YAAM,OAAO,IAAI,aAAa,SAAS;AACvC,YAAM,IAAI,SAAS,QAAQ,YAAY,GAAG,YAAY,IAAI,IAAI;AAAA,IAChE;AAEA,aAAS,IAAI,MAAM;AAAA,MACjB,MAAM;AAAA,MACN;AAAA,MACA,aAAa;AAAA,MACb;AAAA,MACA,aAAa;AAAA,MACb;AAAA,MACA,OAAO;AAAA,IACT,CAAC;AAED,UAAM;AAAA,EACR;AAEA,SAAO,EAAE,UAAU,mBAAmB,IAAI;AAC5C;AAKO,SAAS,qBAAqB,KAMnC;AACA,MAAI,IAAI,SAAS,GAAG;AAClB,UAAM,IAAI,MAAM,sDAAsD;AAAA,EACxE;AACA,QAAM,UAAU,IAAI,aAAa,CAAC;AAClC,QAAM,aAAa,IAAI,aAAa,CAAC;AAGrC,MAAI,IAAI,SAAS,KAAK,IAAI,UAAU,CAAC,MAAM,cAAc;AACvD,UAAM,IAAI,MAAM,iDAAiD;AAAA,EACnE;AACA,QAAM,cAAc,IAAI,aAAa,CAAC;AACtC,QAAM,mBAAmB,IAAI,SAAS,QAAQ,IAAI,KAAK,WAAW;AAClE,QAAM,kBAAkB,KAAK;AAE7B,QAAM,EAAE,UAAU,cAAc,mBAAmB,cAAc,IAAI,sBAAsB,KAAK,eAAe;AAE/G,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAKO,SAAS,wBAAwB,cAAsD;AAC5F,MAAI,CAAC,GAAG,WAAW,YAAY,EAAG,QAAO;AACzC,MAAI;AACF,UAAM,MAAM,GAAG,aAAa,YAAY;AACxC,UAAM,SAAS,qBAAqB,GAAG;AAEvC,QAAI,sBAAsB;AAC1B,UAAM,cAAc,OAAO,aAAa,IAAI,uBAAuB;AACnE,QAAI,eAAe,YAAY,SAAS,YAAY,OAAO,YAAY,KAAK,MAAM,GAAG;AACnF,4BAAsB;AAAA,IACxB;AAEA,QAAI,8BAA8B;AAClC,UAAM,WAAW,OAAO,aAAa,IAAI,gCAAgC;AACzE,QAAI,YAAY,SAAS,SAAS,YAAY,OAAO,SAAS,KAAK,MAAM,GAAG;AAC1E,oCAA8B;AAAA,IAChC;AAEA,UAAM,cAAgD,CAAC;AACvD,QAAI,cAAc;AAElB,UAAM,iBAAiB,OAAO,aAAa,IAAI,aAAa;AAC5D,QAAI,kBAAkB,eAAe,SAAS,cAAc;AAC1D,YAAM,cAAc,sBAAsB,KAAK,eAAe,WAAW,EAAE;AAG3E,YAAM,gBAAgB,YAAY,IAAI,uBAAuB;AAC7D,UAAI,iBAAiB,OAAO,cAAc,KAAK,MAAM,GAAG;AACtD,8BAAsB;AAAA,MACxB;AACA,YAAM,aAAa,YAAY,IAAI,gCAAgC;AACnE,UAAI,cAAc,OAAO,WAAW,KAAK,MAAM,GAAG;AAChD,sCAA8B;AAAA,MAChC;AAEA,iBAAW,CAAC,MAAM,IAAI,KAAK,YAAY,QAAQ,GAAG;AAChD,YAAI,KAAK,SAAS,UAAU;AAC1B,gBAAM,MAAM,OAAO,KAAK,KAAK;AAC7B,sBAAY,IAAI,IAAI;AACpB,cAAI,SAAS,cAAc,QAAQ,GAAG;AACpC,0BAAc;AAAA,UAChB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,SAAS,oBAAoB,MAAc,OAAuB;AAChE,QAAM,UAAU,OAAO,KAAK,MAAM,MAAM;AACxC,QAAM,MAAM,OAAO,MAAM,IAAI,IAAI,QAAQ,SAAS,CAAC;AACnD,MAAI,WAAW,UAAU,CAAC;AAC1B,MAAI,cAAc,QAAQ,QAAQ,CAAC;AACnC,UAAQ,KAAK,KAAK,CAAC;AACnB,MAAI,UAAU,OAAO,IAAI,QAAQ,MAAM;AACvC,SAAO;AACT;AAKA,SAAS,wBAAwB,MAAc,UAA0C;AACvF,QAAM,UAAU,OAAO,KAAK,MAAM,MAAM;AACxC,QAAM,eAAyB,CAAC;AAChC,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,QAAQ,GAAG;AAC7C,iBAAa,KAAK,oBAAoB,GAAG,CAAC,CAAC;AAAA,EAC7C;AACA,eAAa,KAAK,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC;AAExC,QAAM,SAAS,OAAO,MAAM,IAAI,IAAI,QAAQ,MAAM;AAClD,SAAO,WAAW,cAAc,CAAC;AACjC,SAAO,cAAc,QAAQ,QAAQ,CAAC;AACtC,UAAQ,KAAK,QAAQ,CAAC;AAEtB,SAAO,OAAO,OAAO,CAAC,QAAQ,GAAG,YAAY,CAAC;AAChD;AAaA,eAAsB,yBAAyB,cAAqD;AAClG,MAAI,CAAC,GAAG,WAAW,YAAY,GAAG;AAChC,WAAO,EAAE,SAAS,OAAO,SAAS,OAAO,OAAO,mBAAmB,YAAY,GAAG;AAAA,EACpF;AAEA,MAAI;AACF,UAAM,MAAM,MAAM,GAAG,SAAS,SAAS,YAAY;AACnD,UAAM,SAAS,qBAAqB,GAAG;AAEvC,UAAM,iBAAiB,OAAO,aAAa,IAAI,aAAa;AAC5D,QAAI,mBAAmB;AAEvB,QAAI,kBAAkB,eAAe,SAAS,cAAc;AAC1D,YAAM,cAAc,sBAAsB,KAAK,eAAe,WAAW,EAAE;AAC3E,YAAM,WAAW,YAAY,IAAI,UAAU;AAC3C,UAAI,YAAY,OAAO,SAAS,KAAK,MAAM,GAAG;AAC5C,2BAAmB;AAAA,MACrB;AAAA,IACF;AAEA,QAAI,kBAAkB;AACpB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS;AAAA,QACT,uBAAuB;AAAA,MACzB;AAAA,IACF;AAGA,UAAM,aAAa,GAAG,YAAY;AAClC,UAAM,GAAG,SAAS,SAAS,cAAc,UAAU;AAEnD,QAAI;AAEJ,QAAI,CAAC,gBAAgB;AAEnB,YAAM,oBAAoB,wBAAwB,eAAe;AAAA,QAC/D,uBAAuB;AAAA,QACvB,gCAAgC;AAAA,QAChC,UAAU;AAAA,MACZ,CAAC;AAGD,YAAM,kBAAkB,OAAO,gBAAgB;AAC/C,YAAM,YAAY,IAAI,SAAS,GAAG,eAAe;AACjD,YAAM,WAAW,IAAI,SAAS,eAAe;AAC7C,gBAAU,OAAO,OAAO,CAAC,WAAW,mBAAmB,QAAQ,CAAC;AAAA,IAClE,OAAO;AAEL,YAAM,EAAE,UAAU,aAAa,mBAAmB,aAAa,IAAI;AAAA,QACjE;AAAA,QACA,eAAe;AAAA,MACjB;AACA,YAAM,iBAAiB,eAAe;AAGtC,YAAM,WAAqB,CAAC;AAC5B,UAAI,aAAa,OAAO,KAAK,GAAG;AAGhC,YAAM,cAAc,YAAY,IAAI,UAAU;AAC9C,UAAI,aAAa;AACf,mBAAW,UAAU,GAAG,YAAY,WAAW;AAAA,MACjD,OAAO;AACL,iBAAS,KAAK,oBAAoB,YAAY,CAAC,CAAC;AAAA,MAClD;AAGA,YAAM,cAAc,YAAY,IAAI,uBAAuB;AAC3D,UAAI,aAAa;AACf,mBAAW,UAAU,GAAG,YAAY,WAAW;AAAA,MACjD,OAAO;AACL,iBAAS,KAAK,oBAAoB,yBAAyB,CAAC,CAAC;AAAA,MAC/D;AAGA,YAAM,WAAW,YAAY,IAAI,gCAAgC;AACjE,UAAI,UAAU;AACZ,mBAAW,UAAU,GAAG,SAAS,WAAW;AAAA,MAC9C,OAAO;AACL,iBAAS,KAAK,oBAAoB,kCAAkC,CAAC,CAAC;AAAA,MACxE;AAGA,YAAM,eAAe,OAAO,aAAa,IAAI,uBAAuB;AACpE,UAAI,cAAc;AAChB,mBAAW,UAAU,GAAG,aAAa,WAAW;AAAA,MAClD;AACA,YAAM,YAAY,OAAO,aAAa,IAAI,gCAAgC;AAC1E,UAAI,WAAW;AACb,mBAAW,UAAU,GAAG,UAAU,WAAW;AAAA,MAC/C;AAEA,UAAI,SAAS,SAAS,GAAG;AACvB,cAAM,eAAe,WAAW,SAAS,GAAG,cAAc;AAC1D,cAAM,cAAc,WAAW,SAAS,cAAc;AACtD,kBAAU,OAAO,OAAO,CAAC,cAAc,GAAG,UAAU,WAAW,CAAC;AAAA,MAClE,OAAO;AACL,kBAAU,WAAW,SAAS,CAAC;AAAA,MACjC;AAAA,IACF;AAGA,UAAM,YAAY,OAAO,MAAM,CAAC;AAChC,cAAU,cAAc,OAAO,SAAS,CAAC;AACzC,cAAU,cAAc,QAAQ,QAAQ,CAAC;AAEzC,UAAM,kBAAkB,OAAO,OAAO,CAAC,WAAW,OAAO,CAAC;AAG1D,UAAM,UAAU,GAAG,YAAY,IAAI,QAAQ,GAAG;AAC9C,UAAM,GAAG,SAAS,UAAU,SAAS,eAAe;AACpD,UAAM,GAAG,SAAS,OAAO,SAAS,YAAY;AAE9C,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS;AAAA,MACT;AAAA,MACA,uBAAuB;AAAA,IACzB;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS;AAAA,MACT,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACxD;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,125 @@
1
+ import assert from "node:assert/strict";
2
+ import fs from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import test from "node:test";
6
+ import {
7
+ enableBetaApisInLevelDat,
8
+ parseBedrockLevelDat,
9
+ readLevelDatExperiments,
10
+ TAG_BYTE,
11
+ TAG_COMPOUND,
12
+ TAG_END
13
+ } from "./level-dat.js";
14
+ function buildMockLevelDat(includeExperiments, gametestVal) {
15
+ const rootName = "";
16
+ const rootNameBuf = Buffer.from(rootName, "utf8");
17
+ const childBuffers = [];
18
+ const sampleName = Buffer.from("LevelName", "utf8");
19
+ const sampleVal = Buffer.from("TestWorld", "utf8");
20
+ const strTag = Buffer.alloc(1 + 2 + sampleName.length + 2 + sampleVal.length);
21
+ strTag.writeUInt8(8, 0);
22
+ strTag.writeUInt16LE(sampleName.length, 1);
23
+ sampleName.copy(strTag, 3);
24
+ strTag.writeUInt16LE(sampleVal.length, 3 + sampleName.length);
25
+ sampleVal.copy(strTag, 5 + sampleName.length);
26
+ childBuffers.push(strTag);
27
+ if (includeExperiments) {
28
+ const expName = Buffer.from("experiments", "utf8");
29
+ const expChildren = [];
30
+ const everUsedName = Buffer.from("experiments_ever_used", "utf8");
31
+ const b1 = Buffer.alloc(1 + 2 + everUsedName.length + 1);
32
+ b1.writeUInt8(TAG_BYTE, 0);
33
+ b1.writeUInt16LE(everUsedName.length, 1);
34
+ everUsedName.copy(b1, 3);
35
+ b1.writeInt8(0, 3 + everUsedName.length);
36
+ expChildren.push(b1);
37
+ if (gametestVal !== void 0) {
38
+ const gtName = Buffer.from("gametest", "utf8");
39
+ const b2 = Buffer.alloc(1 + 2 + gtName.length + 1);
40
+ b2.writeUInt8(TAG_BYTE, 0);
41
+ b2.writeUInt16LE(gtName.length, 1);
42
+ gtName.copy(b2, 3);
43
+ b2.writeInt8(gametestVal, 3 + gtName.length);
44
+ expChildren.push(b2);
45
+ }
46
+ expChildren.push(Buffer.from([TAG_END]));
47
+ const expHeader = Buffer.alloc(1 + 2 + expName.length);
48
+ expHeader.writeUInt8(TAG_COMPOUND, 0);
49
+ expHeader.writeUInt16LE(expName.length, 1);
50
+ expName.copy(expHeader, 3);
51
+ childBuffers.push(Buffer.concat([expHeader, ...expChildren]));
52
+ }
53
+ childBuffers.push(Buffer.from([TAG_END]));
54
+ const rootHeader = Buffer.alloc(1 + 2 + rootNameBuf.length);
55
+ rootHeader.writeUInt8(TAG_COMPOUND, 0);
56
+ rootHeader.writeUInt16LE(rootNameBuf.length, 1);
57
+ rootNameBuf.copy(rootHeader, 3);
58
+ const nbtBody = Buffer.concat([rootHeader, ...childBuffers]);
59
+ const fileHeader = Buffer.alloc(8);
60
+ fileHeader.writeUInt32LE(10, 0);
61
+ fileHeader.writeUInt32LE(nbtBody.length, 4);
62
+ return Buffer.concat([fileHeader, nbtBody]);
63
+ }
64
+ test("readLevelDatExperiments: correctly reads experiments status", () => {
65
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "sfmc-lvl-test-"));
66
+ try {
67
+ const file = path.join(tmpDir, "level.dat");
68
+ fs.writeFileSync(file, buildMockLevelDat(true));
69
+ const info1 = readLevelDatExperiments(file);
70
+ assert.ok(info1);
71
+ assert.equal(info1.hasBetaApis, false);
72
+ assert.equal(info1.experimentsEverUsed, false);
73
+ fs.writeFileSync(file, buildMockLevelDat(true, 1));
74
+ const info2 = readLevelDatExperiments(file);
75
+ assert.ok(info2);
76
+ assert.equal(info2.hasBetaApis, true);
77
+ } finally {
78
+ fs.rmSync(tmpDir, { recursive: true, force: true });
79
+ }
80
+ });
81
+ test("enableBetaApisInLevelDat: enables gametest and updates header length", async () => {
82
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "sfmc-lvl-test-"));
83
+ try {
84
+ const file = path.join(tmpDir, "level.dat");
85
+ fs.writeFileSync(file, buildMockLevelDat(true));
86
+ const res1 = await enableBetaApisInLevelDat(file);
87
+ assert.equal(res1.success, true);
88
+ assert.equal(res1.changed, true);
89
+ assert.ok(res1.backupPath && fs.existsSync(res1.backupPath));
90
+ const info = readLevelDatExperiments(file);
91
+ assert.ok(info);
92
+ assert.equal(info.hasBetaApis, true);
93
+ assert.equal(info.experimentsEverUsed, true);
94
+ assert.equal(info.savedWithToggledExperiments, true);
95
+ const finalBuf = fs.readFileSync(file);
96
+ const parsed = parseBedrockLevelDat(finalBuf);
97
+ assert.equal(parsed.dataLength, finalBuf.length - 8);
98
+ const res2 = await enableBetaApisInLevelDat(file);
99
+ assert.equal(res2.success, true);
100
+ assert.equal(res2.changed, false);
101
+ } finally {
102
+ fs.rmSync(tmpDir, { recursive: true, force: true });
103
+ }
104
+ });
105
+ test("enableBetaApisInLevelDat: creates experiments compound if completely absent", async () => {
106
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "sfmc-lvl-test-"));
107
+ try {
108
+ const file = path.join(tmpDir, "level.dat");
109
+ fs.writeFileSync(file, buildMockLevelDat(false));
110
+ const res = await enableBetaApisInLevelDat(file);
111
+ assert.equal(res.success, true);
112
+ assert.equal(res.changed, true);
113
+ const info = readLevelDatExperiments(file);
114
+ assert.ok(info);
115
+ assert.equal(info.hasBetaApis, true);
116
+ assert.equal(info.experimentsEverUsed, true);
117
+ assert.equal(info.savedWithToggledExperiments, true);
118
+ const finalBuf = fs.readFileSync(file);
119
+ const parsed = parseBedrockLevelDat(finalBuf);
120
+ assert.equal(parsed.dataLength, finalBuf.length - 8);
121
+ } finally {
122
+ fs.rmSync(tmpDir, { recursive: true, force: true });
123
+ }
124
+ });
125
+ //# sourceMappingURL=level-dat.test.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/level-dat.test.ts"],
4
+ "sourcesContent": ["import assert from \"node:assert/strict\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport test from \"node:test\";\nimport {\n enableBetaApisInLevelDat,\n parseBedrockLevelDat,\n readLevelDatExperiments,\n TAG_BYTE,\n TAG_COMPOUND,\n TAG_END,\n} from \"./level-dat.js\";\n\nfunction buildMockLevelDat(includeExperiments: boolean, gametestVal?: number): Buffer {\n const rootName = \"\";\n const rootNameBuf = Buffer.from(rootName, \"utf8\");\n\n const childBuffers: Buffer[] = [];\n\n // Random sample tag\n const sampleName = Buffer.from(\"LevelName\", \"utf8\");\n const sampleVal = Buffer.from(\"TestWorld\", \"utf8\");\n const strTag = Buffer.alloc(1 + 2 + sampleName.length + 2 + sampleVal.length);\n strTag.writeUInt8(8, 0); // TAG_String\n strTag.writeUInt16LE(sampleName.length, 1);\n sampleName.copy(strTag, 3);\n strTag.writeUInt16LE(sampleVal.length, 3 + sampleName.length);\n sampleVal.copy(strTag, 5 + sampleName.length);\n childBuffers.push(strTag);\n\n if (includeExperiments) {\n const expName = Buffer.from(\"experiments\", \"utf8\");\n const expChildren: Buffer[] = [];\n\n // experiments_ever_used = 0\n const everUsedName = Buffer.from(\"experiments_ever_used\", \"utf8\");\n const b1 = Buffer.alloc(1 + 2 + everUsedName.length + 1);\n b1.writeUInt8(TAG_BYTE, 0);\n b1.writeUInt16LE(everUsedName.length, 1);\n everUsedName.copy(b1, 3);\n b1.writeInt8(0, 3 + everUsedName.length);\n expChildren.push(b1);\n\n if (gametestVal !== undefined) {\n const gtName = Buffer.from(\"gametest\", \"utf8\");\n const b2 = Buffer.alloc(1 + 2 + gtName.length + 1);\n b2.writeUInt8(TAG_BYTE, 0);\n b2.writeUInt16LE(gtName.length, 1);\n gtName.copy(b2, 3);\n b2.writeInt8(gametestVal, 3 + gtName.length);\n expChildren.push(b2);\n }\n\n expChildren.push(Buffer.from([TAG_END]));\n\n const expHeader = Buffer.alloc(1 + 2 + expName.length);\n expHeader.writeUInt8(TAG_COMPOUND, 0);\n expHeader.writeUInt16LE(expName.length, 1);\n expName.copy(expHeader, 3);\n\n childBuffers.push(Buffer.concat([expHeader, ...expChildren]));\n }\n\n childBuffers.push(Buffer.from([TAG_END]));\n\n const rootHeader = Buffer.alloc(1 + 2 + rootNameBuf.length);\n rootHeader.writeUInt8(TAG_COMPOUND, 0);\n rootHeader.writeUInt16LE(rootNameBuf.length, 1);\n rootNameBuf.copy(rootHeader, 3);\n\n const nbtBody = Buffer.concat([rootHeader, ...childBuffers]);\n\n const fileHeader = Buffer.alloc(8);\n fileHeader.writeUInt32LE(10, 0); // version 10\n fileHeader.writeUInt32LE(nbtBody.length, 4);\n\n return Buffer.concat([fileHeader, nbtBody]);\n}\n\ntest(\"readLevelDatExperiments: correctly reads experiments status\", () => {\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), \"sfmc-lvl-test-\"));\n try {\n const file = path.join(tmpDir, \"level.dat\");\n\n // 1. Without gametest\n fs.writeFileSync(file, buildMockLevelDat(true));\n const info1 = readLevelDatExperiments(file);\n assert.ok(info1);\n assert.equal(info1.hasBetaApis, false);\n assert.equal(info1.experimentsEverUsed, false);\n\n // 2. With gametest = 1\n fs.writeFileSync(file, buildMockLevelDat(true, 1));\n const info2 = readLevelDatExperiments(file);\n assert.ok(info2);\n assert.equal(info2.hasBetaApis, true);\n } finally {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n }\n});\n\ntest(\"enableBetaApisInLevelDat: enables gametest and updates header length\", async () => {\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), \"sfmc-lvl-test-\"));\n try {\n const file = path.join(tmpDir, \"level.dat\");\n fs.writeFileSync(file, buildMockLevelDat(true));\n\n const res1 = await enableBetaApisInLevelDat(file);\n assert.equal(res1.success, true);\n assert.equal(res1.changed, true);\n assert.ok(res1.backupPath && fs.existsSync(res1.backupPath));\n\n // Check after change\n const info = readLevelDatExperiments(file);\n assert.ok(info);\n assert.equal(info.hasBetaApis, true);\n assert.equal(info.experimentsEverUsed, true);\n assert.equal(info.savedWithToggledExperiments, true);\n\n // Verify header length matches buffer length\n const finalBuf = fs.readFileSync(file);\n const parsed = parseBedrockLevelDat(finalBuf);\n assert.equal(parsed.dataLength, finalBuf.length - 8);\n\n // Idempotency test: second run shouldn't change\n const res2 = await enableBetaApisInLevelDat(file);\n assert.equal(res2.success, true);\n assert.equal(res2.changed, false);\n } finally {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n }\n});\n\ntest(\"enableBetaApisInLevelDat: creates experiments compound if completely absent\", async () => {\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), \"sfmc-lvl-test-\"));\n try {\n const file = path.join(tmpDir, \"level.dat\");\n fs.writeFileSync(file, buildMockLevelDat(false));\n\n const res = await enableBetaApisInLevelDat(file);\n assert.equal(res.success, true);\n assert.equal(res.changed, true);\n\n const info = readLevelDatExperiments(file);\n assert.ok(info);\n assert.equal(info.hasBetaApis, true);\n assert.equal(info.experimentsEverUsed, true);\n assert.equal(info.savedWithToggledExperiments, true);\n\n const finalBuf = fs.readFileSync(file);\n const parsed = parseBedrockLevelDat(finalBuf);\n assert.equal(parsed.dataLength, finalBuf.length - 8);\n } finally {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n }\n});\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -11,6 +11,8 @@
11
11
  * - 世界部署与清单激活:将包部署至 BDS `<level>/behavior_packs` 与 `resource_packs`,并同步维护 `world_behavior_packs.json`
12
12
  */
13
13
  import { copyDirAsync, copyFileAsync } from "./fsx.js";
14
+ import { type PackManifestDependency } from "./dependency-negotiator.js";
15
+ export * from "./dependency-negotiator.js";
14
16
  export interface AssembleBehaviorPackOpts {
15
17
  /** 已完成打包的 `scripts/main.js` 所在源码目录(即 esbuild 输出目录)。 */
16
18
  srcDir: string;
@@ -28,6 +30,8 @@ export interface AssembleBehaviorPackOpts {
28
30
  uuid?: string | undefined;
29
31
  /** 稳定的 `script module uuid`(缺省时随机生成)。 */
30
32
  moduleUuid?: string | undefined;
33
+ /** 自定义/动态协商后的 dependencies(缺省使用 BASELINE_BEDROCK_DEPENDENCIES)。 */
34
+ dependencies?: PackManifestDependency[] | undefined;
31
35
  }
32
36
  export interface AssembleResourcePackOpts {
33
37
  /** 需合并资源包目录的模块映射字典(`Record<moduleId, resourcePackDir>`)。 */
@@ -85,11 +89,15 @@ export declare function serverPropertiesPath(bdsRoot: string): string;
85
89
  export declare function bdsWorldsDir(bdsRoot: string): string;
86
90
  /** `<bdsRoot>/worlds/<level>` */
87
91
  export declare function bdsWorldLevelDir(bdsRoot: string, levelName: string): string;
92
+ /** `<bdsRoot>/worlds/<level>/level.dat` — 世界存档权威路径 */
93
+ export declare function levelDatPath(bdsRoot: string, levelName: string): string;
88
94
  /** 世界 enable-list JSON 绝对路径(单一权威,供读写两侧) */
89
95
  export declare function worldPackListFile(worldsDir: string, levelName: string, kind: "behavior" | "resource"): string;
90
96
  /** `<bdsRoot>/config/<bpUuid>/permission.json` — Script API 权限文件权威路径 */
91
97
  export declare function configPermissionPath(bdsRoot: string, bpUuid: string): string;
92
- /** 是否已有 Script API permission.json(只读,供 preflight/status) */
98
+ /** `<bdsRoot>/config/<bpUuid>/permissions.json` — BDS 官方规范复数权限文件路径 */
99
+ export declare function configPermissionsPath(bdsRoot: string, bpUuid: string): string;
100
+ /** 是否已有 Script API permission.json 或 permissions.json(只读,供 preflight/status) */
93
101
  export declare function hasConfigPermission(bdsRoot: string, bpUuid: string): boolean;
94
102
  /** 随机生成 BP/RP manifest.json header.uuid (RFC 4122 v4) */
95
103
  export declare function randomUuid(): string;
@@ -121,17 +129,21 @@ export declare function readLevelName(bdsRoot: string): Promise<string>;
121
129
  */
122
130
  export declare function deployToBDS(opts: DeployOpts): Promise<DeployResult>;
123
131
  /**
124
- * 确保 BDS Script API 侧 `<bdsRoot>/config/<bpUuid>/permission.json` 存在。
125
- * 已存在则跳过(不覆盖用户手工改动)。
126
- * @returns true = 新写入; false = 已存在跳过
132
+ * 确保 BDS Script API 侧权限文件存在并包含完整的 SFMC 所需模块权限。
133
+ * - 自动增量合并现有 allowed_modules,自动补齐新增权限(如 @minecraft/diagnostics)
134
+ * - 同时维护 BDS 官方规范的 permissions.json 与历史兼容的 permission.json
135
+ * - 同时更新 moduleUuid(若提供)与 config/default/permissions.json 兜底权限
136
+ * @returns true = 有新增/更新; false = 已是最新无需修改
127
137
  */
128
- export declare function ensureConfigPermission(bdsRoot: string, bpUuid: string): Promise<boolean>;
138
+ export declare function ensureConfigPermission(bdsRoot: string, bpUuid: string, moduleUuid?: string): Promise<boolean>;
129
139
  /** 从已装配 BP/RP 目录读取 header.uuid + version;失败返回 null。 */
130
140
  export declare function readPackManifestHeader(packDir: string): {
131
141
  uuid: string;
132
142
  version: [number, number, number];
133
143
  moduleUuid?: string;
134
144
  } | null;
145
+ /** 从已装配 BP/RP 目录读取 dependencies 列表;若无或失败返回 []。 */
146
+ export declare function readPackManifestDependencies(packDir: string): PackManifestDependency[];
135
147
  /**
136
148
  * Write `@minecraft/*` allowed_modules into a behavior pack's
137
149
  * `permissions.json`. Idempotent: rewrites any pre-existing file.
@@ -151,7 +163,7 @@ export declare function writeBehaviorPackManifest(outDir: string, header: {
151
163
  version: [number, number, number];
152
164
  description?: string | undefined;
153
165
  moduleUuid?: string | undefined;
154
- }): Promise<void>;
166
+ }, dependencies?: PackManifestDependency[] | undefined): Promise<void>;
155
167
  export declare function writeResourcePackManifest(outDir: string, header: {
156
168
  name: string;
157
169
  uuid: string;
@@ -1 +1 @@
1
- {"version":3,"file":"pack-manager.d.ts","sourceRoot":"","sources":["../src/pack-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pack-manager.d.ts","sourceRoot":"","sources":["../src/pack-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAgB,MAAM,UAAU,CAAC;AACrE,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,4BAA4B,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAI3C,MAAM,WAAW,wBAAwB;IACvC,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,oFAAoF;IACpF,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IAC/C,+BAA+B;IAC/B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,yCAAyC;IACzC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,mEAAmE;IACnE,YAAY,CAAC,EAAE,sBAAsB,EAAE,GAAG,SAAS,CAAC;CACrD;AAED,MAAM,WAAW,wBAAwB;IACvC,4DAA4D;IAC5D,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,oFAAoF;IACpF,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IAC/C,+BAA+B;IAC/B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,kCAAkC;IAClC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAGD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,UAAU,GAAG,UAAU,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAID,4DAA4D;AAC5D,eAAO,MAAM,gBAAgB,YAC3B,mBAAmB,EACnB,sBAAsB,EACtB,yBAAyB,EACzB,4BAA4B,EAC5B,uBAAuB,EACvB,0BAA0B,EAC1B,wBAAwB,CAChB,CAAC;AAEX,sEAAsE;AACtE,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,4DAA4D;AAC5D,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,iCAAiC;AACjC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAE3E;AAED,sDAAsD;AACtD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED,2CAA2C;AAC3C,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,UAAU,GAAG,UAAU,GAC5B,MAAM,CAGR;AAED,wEAAwE;AACxE,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED,sEAAsE;AACtE,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED,gFAAgF;AAChF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAE5E;AAED,yDAAyD;AACzD,wBAAgB,UAAU,IAAI,MAAM,CAGnC;AAID;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,wBAAwB,GAAG,OAAO,CAAC,cAAc,CAAC,CA2BlG;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,wBAAwB,GAAG,OAAO,CAAC,cAAc,CAAC,CAmBlG;AAeD,4DAA4D;AAC5D,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED,0CAA0C;AAC1C,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEpE;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAmBzE;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,CAAC,CAyClB;AAED,uDAAuD;AACvD,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,GACd;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAiBjF;AAGD,kDAAkD;AAClD,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,MAAM,GAAG,sBAAsB,EAAE,CAStF;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvE;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3E;AAED,0DAA0D;AAC1D,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5E;AA8BD,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,MAAM,EACd,MAAM,EAAE;IACN,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC,EACD,YAAY,CAAC,EAAE,sBAAsB,EAAE,GAAG,SAAS,GAClD,OAAO,CAAC,IAAI,CAAC,CAyBf;AAED,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,MAAM,EACd,MAAM,EAAE;IACN,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC,GACA,OAAO,CAAC,IAAI,CAAC,CAqBf;AAID,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC;AAIvC;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAiBlF;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAelF;AAED;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC,CAAC;IACvE,6BAA6B;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,UAAU,GAAG,UAAU,GAC5B,uBAAuB,CAsBzB;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,UAAU,GAAG,UAAU,GAC5B,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC,CAE/D;AAED,wDAAwD;AACxD,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,UAAU,GAAG,UAAU,EAC7B,QAAQ,EAAE,MAAM,GACf,OAAO,CAET"}