@sfmc-bds/bds-tools 0.2.0-beta.8 → 0.2.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.
Files changed (114) hide show
  1. package/LICENSE +663 -0
  2. package/README.md +1 -1
  3. package/dist/bds-manager.d.ts +16 -6
  4. package/dist/bds-manager.d.ts.map +1 -1
  5. package/dist/bds-manager.js +59 -66
  6. package/dist/bds-manager.js.map +2 -2
  7. package/dist/changelog.d.ts +11 -7
  8. package/dist/changelog.d.ts.map +1 -1
  9. package/dist/changelog.js +60 -34
  10. package/dist/changelog.js.map +2 -2
  11. package/dist/check-update.d.ts.map +1 -1
  12. package/dist/check-update.js +59 -23
  13. package/dist/check-update.js.map +2 -2
  14. package/dist/cli-pack-manager.js +11 -1
  15. package/dist/cli-pack-manager.js.map +2 -2
  16. package/dist/dependency-negotiator.d.ts +73 -0
  17. package/dist/dependency-negotiator.d.ts.map +1 -0
  18. package/dist/dependency-negotiator.js +151 -0
  19. package/dist/dependency-negotiator.js.map +7 -0
  20. package/dist/fsx.d.ts +17 -14
  21. package/dist/fsx.d.ts.map +1 -1
  22. package/dist/fsx.js +67 -19
  23. package/dist/fsx.js.map +2 -2
  24. package/dist/host-platform.d.ts +25 -0
  25. package/dist/host-platform.d.ts.map +1 -0
  26. package/dist/host-platform.js +50 -0
  27. package/dist/host-platform.js.map +7 -0
  28. package/dist/http.d.ts +49 -11
  29. package/dist/http.d.ts.map +1 -1
  30. package/dist/http.js.map +2 -2
  31. package/dist/level-dat.d.ts +105 -0
  32. package/dist/level-dat.d.ts.map +1 -0
  33. package/dist/level-dat.js +490 -0
  34. package/dist/level-dat.js.map +7 -0
  35. package/dist/pack-manager.d.ts +41 -34
  36. package/dist/pack-manager.d.ts.map +1 -1
  37. package/dist/pack-manager.js +79 -25
  38. package/dist/pack-manager.js.map +2 -2
  39. package/dist/pack-update/bindings.d.ts +16 -0
  40. package/dist/pack-update/bindings.d.ts.map +1 -0
  41. package/dist/pack-update/bindings.js +69 -0
  42. package/dist/pack-update/bindings.js.map +7 -0
  43. package/dist/pack-update/config.d.ts +16 -0
  44. package/dist/pack-update/config.d.ts.map +1 -0
  45. package/dist/pack-update/config.js +146 -0
  46. package/dist/pack-update/config.js.map +7 -0
  47. package/dist/pack-update/deps.d.ts +28 -0
  48. package/dist/pack-update/deps.d.ts.map +1 -0
  49. package/dist/pack-update/deps.js +20 -0
  50. package/dist/pack-update/deps.js.map +7 -0
  51. package/dist/pack-update/index.d.ts +55 -0
  52. package/dist/pack-update/index.d.ts.map +1 -0
  53. package/dist/pack-update/index.js +72 -0
  54. package/dist/pack-update/index.js.map +7 -0
  55. package/dist/pack-update/providers/curseforge.d.ts +23 -0
  56. package/dist/pack-update/providers/curseforge.d.ts.map +1 -0
  57. package/dist/pack-update/providers/curseforge.js +229 -0
  58. package/dist/pack-update/providers/curseforge.js.map +7 -0
  59. package/dist/pack-update/providers/index.d.ts +16 -0
  60. package/dist/pack-update/providers/index.d.ts.map +1 -0
  61. package/dist/pack-update/providers/index.js +37 -0
  62. package/dist/pack-update/providers/index.js.map +7 -0
  63. package/dist/pack-update/service.d.ts +28 -0
  64. package/dist/pack-update/service.d.ts.map +1 -0
  65. package/dist/pack-update/service.js +570 -0
  66. package/dist/pack-update/service.js.map +7 -0
  67. package/dist/pack-update/types.d.ts +126 -0
  68. package/dist/pack-update/types.d.ts.map +1 -0
  69. package/dist/pack-update/types.js +8 -0
  70. package/dist/pack-update/types.js.map +7 -0
  71. package/dist/pack-update/version-policy.d.ts +81 -0
  72. package/dist/pack-update/version-policy.d.ts.map +1 -0
  73. package/dist/pack-update/version-policy.js +210 -0
  74. package/dist/pack-update/version-policy.js.map +7 -0
  75. package/dist/paths.d.ts +1 -1
  76. package/dist/paths.d.ts.map +1 -1
  77. package/dist/paths.js +3 -5
  78. package/dist/paths.js.map +2 -2
  79. package/dist/process-probe.d.ts +34 -0
  80. package/dist/process-probe.d.ts.map +1 -0
  81. package/dist/process-probe.js +152 -0
  82. package/dist/process-probe.js.map +7 -0
  83. package/dist/qq-events-notify.d.ts +16 -0
  84. package/dist/qq-events-notify.d.ts.map +1 -0
  85. package/dist/qq-events-notify.js +70 -0
  86. package/dist/qq-events-notify.js.map +7 -0
  87. package/dist/qqutil.d.ts +10 -5
  88. package/dist/qqutil.d.ts.map +1 -1
  89. package/dist/qqutil.js +53 -10
  90. package/dist/qqutil.js.map +2 -2
  91. package/dist/rollback.d.ts.map +1 -1
  92. package/dist/rollback.js +2 -2
  93. package/dist/rollback.js.map +2 -2
  94. package/dist/server-properties-i18n.d.ts +17 -0
  95. package/dist/server-properties-i18n.d.ts.map +1 -0
  96. package/dist/server-properties-i18n.js +201 -0
  97. package/dist/server-properties-i18n.js.map +7 -0
  98. package/dist/server-properties.d.ts +25 -0
  99. package/dist/server-properties.d.ts.map +1 -1
  100. package/dist/server-properties.js +141 -1
  101. package/dist/server-properties.js.map +2 -2
  102. package/dist/types.d.ts +1 -0
  103. package/dist/types.d.ts.map +1 -1
  104. package/dist/upstream.d.ts +18 -9
  105. package/dist/upstream.d.ts.map +1 -1
  106. package/dist/upstream.js +8 -7
  107. package/dist/upstream.js.map +2 -2
  108. package/dist/version.js +2 -2
  109. package/dist/version.js.map +2 -2
  110. package/dist/world-packs.d.ts +108 -8
  111. package/dist/world-packs.d.ts.map +1 -1
  112. package/dist/world-packs.js +245 -12
  113. package/dist/world-packs.js.map +3 -3
  114. package/package.json +24 -17
@@ -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 KnownExperimentDefinition {\n id: string;\n nbtKey: string;\n nameZh: string;\n nameEn: string;\n aliases?: string[];\n isRootTag?: boolean;\n extraExpTags?: string[];\n}\n\nexport const KNOWN_EXPERIMENTS: readonly KnownExperimentDefinition[] = [\n {\n id: \"gametest\",\n nbtKey: \"gametest\",\n nameZh: \"\u6D4B\u8BD5\u7248 API\",\n nameEn: \"Beta APIs (gametest)\",\n aliases: [\"beta\", \"beta_apis\", \"betapis\", \"gametest\"],\n },\n {\n id: \"upcoming_creator_features\",\n nbtKey: \"upcoming_creator_features\",\n nameZh: \"\u5373\u5C06\u63A8\u51FA\u7684\u521B\u4F5C\u8005\u529F\u80FD\",\n nameEn: \"Upcoming Creator Features\",\n aliases: [\"upcoming\", \"creator_features\", \"upcoming_features\"],\n },\n {\n id: \"experimental_creator_cameras\",\n nbtKey: \"experimental_creator_cameras\",\n nameZh: \"\u521B\u5EFA\u8005\u7167\u76F8\u673A\u7684\u5B9E\u9A8C\u6027\u529F\u80FD\",\n nameEn: \"Experimental Creator Cameras\",\n aliases: [\"camera\", \"cameras\", \"creator_cameras\", \"creator_camera\"],\n },\n {\n id: \"voxel_shapes\",\n nbtKey: \"voxel_shapes\",\n nameZh: \"\u5B9E\u9A8C\u6027Voxel\u5F62\u72B6\u7279\u5F81\",\n nameEn: \"Experimental Voxel Shapes\",\n aliases: [\"voxel\", \"voxel_shape\", \"experimental_voxel_shapes\", \"voxelshapes\"],\n },\n {\n id: \"villager_trades_rebalance\",\n nbtKey: \"villager_trades_rebalance\",\n nameZh: \"\u6751\u6C11\u8D38\u6613\u518D\u5E73\u8861\",\n nameEn: \"Villager Trade Rebalance\",\n aliases: [\"villager\", \"trades\", \"villager_trades\", \"trade_rebalance\"],\n },\n {\n id: \"drop_3_2026\",\n nbtKey: \"drop_3_2026\",\n nameZh: \"2026\u5E74\u7B2C3\u6B21\u66F4\u65B0\",\n nameEn: \"Drop 3 of 2026\",\n aliases: [\n \"drop3\",\n \"drop_3\",\n \"drop_3_2026\",\n \"wilderness\",\n \"wilderness_bound\",\n \"update_2026_drop_3\",\n \"update_26_3\",\n \"update_drop_3\",\n ],\n extraExpTags: [\"update_2026_drop_3\"],\n },\n {\n id: \"education\",\n nbtKey: \"educationFeaturesEnabled\",\n nameZh: \"Minecraft Education \u529F\u80FD\",\n nameEn: \"Minecraft Education Features\",\n isRootTag: true,\n aliases: [\"edu\", \"education\", \"education_edition\", \"educationfeatures\"],\n extraExpTags: [\"education\"],\n },\n] as const;\n\nexport function resolveExperimentDefinition(query: string): KnownExperimentDefinition | null {\n const q = query.trim().toLowerCase().replace(/[-_]/g, \"\");\n for (const def of KNOWN_EXPERIMENTS) {\n if (def.id.replace(/[-_]/g, \"\") === q) return def;\n if (def.nbtKey.replace(/[-_]/g, \"\") === q) return def;\n if (def.aliases) {\n for (const a of def.aliases) {\n if (a.replace(/[-_]/g, \"\") === q) return def;\n }\n }\n }\n return null;\n}\n\nexport interface LevelDatExperimentsInfo {\n experimentsEverUsed: boolean;\n savedWithToggledExperiments: boolean;\n experiments: Record<string, number | boolean>;\n hasBetaApis: boolean;\n knownExperiments: Record<string, boolean>;\n}\n\nexport interface LevelDatMutateResult {\n success: boolean;\n changed: boolean;\n backupPath?: string;\n error?: string;\n previousBetaApisState?: boolean;\n enabledExperiments?: string[];\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 const knownExperiments: Record<string, boolean> = {};\n for (const def of KNOWN_EXPERIMENTS) {\n let enabled = false;\n if (def.isRootTag) {\n const rootTag = parsed.rootChildren.get(def.nbtKey);\n if (rootTag && Number(rootTag.value) === 1) {\n enabled = true;\n }\n }\n const keysToCheck = [def.nbtKey, ...(def.aliases ?? [])];\n for (const k of keysToCheck) {\n if (experiments[k] === 1) {\n enabled = true;\n break;\n }\n }\n knownExperiments[def.id] = enabled;\n }\n\n return {\n experimentsEverUsed,\n savedWithToggledExperiments,\n experiments,\n hasBetaApis,\n knownExperiments,\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\u6307\u5B9A\u7684\u5B9E\u9A8C\u6027\u5F00\u5173\uFF08\u82E5\u672A\u6307\u5B9A\u6216\u4F20 \"all\" \u5219\u5F00\u542F\u5168\u90E8\u5DF2\u77E5\u5B9E\u9A8C\u6027\u5F00\u5173\uFF09\u3002\n *\n * \u4FDD\u8BC1\uFF1A\n * - \u81EA\u52A8\u5907\u4EFD\u539F\u6587\u4EF6\u81F3 `${levelDatPath}.bak`\uFF1B\n * - \u81EA\u52A8\u66F4\u65B0 root \u4E0E experiments \u590D\u5408\u6807\u7B7E\u4E2D\u7684\u76EE\u6807 byte tags\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\u6240\u8BF7\u6C42\u5F00\u5173\u5DF2\u5168\u90E8\u5904\u4E8E\u5F00\u542F\u72B6\u6001\uFF0C\u76F4\u63A5\u8FD4\u56DE changed: false\uFF0C\u4E0D\u7834\u574F\u6587\u4EF6\u3002\n */\nexport async function enableExperimentsInLevelDat(\n levelDatPath: string,\n targetExperimentIds?: string[] | \"all\"\n): 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 // \u89E3\u6790\u76EE\u6807\u5B9E\u9A8C\u9879\n let targetDefs: KnownExperimentDefinition[] = [];\n if (!targetExperimentIds || targetExperimentIds === \"all\") {\n targetDefs = [...KNOWN_EXPERIMENTS];\n } else {\n const seen = new Set<string>();\n for (const id of targetExperimentIds) {\n const def = resolveExperimentDefinition(id);\n if (def && !seen.has(def.id)) {\n seen.add(def.id);\n targetDefs.push(def);\n }\n }\n if (targetDefs.length === 0) {\n return { success: true, changed: false, enabledExperiments: [] };\n }\n }\n\n const expCompoundTag = parsed.rootChildren.get(\"experiments\");\n const existingExpChildren =\n expCompoundTag && expCompoundTag.type === TAG_COMPOUND\n ? parseCompoundChildren(raw, expCompoundTag.valueOffset).children\n : new Map<string, NbtTagMeta>();\n\n // \u68C0\u67E5\u5F53\u524D\u72B6\u6001\n let needsChange = false;\n const enabledIds: string[] = [];\n\n // 1. \u68C0\u67E5 experiments compound \u53CA\u5185\u90E8\u5FC5\u8981\u7CFB\u7EDF\u6807\u7B7E\n if (!expCompoundTag) {\n needsChange = true;\n } else {\n const expEverUsed = existingExpChildren.get(\"experiments_ever_used\");\n if (!expEverUsed || Number(expEverUsed.value) !== 1) needsChange = true;\n\n const expSaved = existingExpChildren.get(\"saved_with_toggled_experiments\");\n if (!expSaved || Number(expSaved.value) !== 1) needsChange = true;\n }\n\n // \u82E5 root \u5C42\u5B58\u5728\u7CFB\u7EDF\u6807\u7B7E\u4F46\u672A\u8BBE\u4E3A 1\uFF0C\u4E5F\u9700\u4FEE\u6B63\n const rootEverUsed = parsed.rootChildren.get(\"experiments_ever_used\");\n if (rootEverUsed && Number(rootEverUsed.value) !== 1) needsChange = true;\n\n const rootSaved = parsed.rootChildren.get(\"saved_with_toggled_experiments\");\n if (rootSaved && Number(rootSaved.value) !== 1) needsChange = true;\n\n let previousBetaApisState = false;\n const currentGametest = existingExpChildren.get(\"gametest\");\n if (currentGametest && Number(currentGametest.value) === 1) {\n previousBetaApisState = true;\n }\n\n for (const def of targetDefs) {\n enabledIds.push(def.id);\n if (def.isRootTag) {\n const rootTag = parsed.rootChildren.get(def.nbtKey);\n if (!rootTag || Number(rootTag.value) !== 1) {\n needsChange = true;\n }\n }\n if (!def.isRootTag) {\n const tag = existingExpChildren.get(def.nbtKey);\n if (!tag || Number(tag.value) !== 1) {\n needsChange = true;\n }\n }\n if (def.extraExpTags) {\n for (const extra of def.extraExpTags) {\n const tag = existingExpChildren.get(extra);\n if (!tag || Number(tag.value) !== 1) {\n needsChange = true;\n }\n }\n }\n }\n\n if (!needsChange) {\n return {\n success: true,\n changed: false,\n previousBetaApisState,\n enabledExperiments: enabledIds,\n };\n }\n\n // \u5907\u4EFD\u539F\u6587\u4EF6\n const backupPath = `${levelDatPath}.bak`;\n await fs.promises.copyFile(levelDatPath, backupPath);\n\n let mutatedRaw = Buffer.from(raw);\n let nbtBody: Buffer;\n\n // \u6536\u96C6\u9700\u8981\u5728 experiments \u590D\u5408\u6807\u7B7E\u4E2D\u8BBE\u7F6E\u7684 tags\n const requiredExpTags: Record<string, number> = {\n experiments_ever_used: 1,\n saved_with_toggled_experiments: 1,\n };\n for (const def of targetDefs) {\n if (!def.isRootTag) {\n requiredExpTags[def.nbtKey] = 1;\n }\n if (def.extraExpTags) {\n for (const extra of def.extraExpTags) {\n requiredExpTags[extra] = 1;\n }\n }\n }\n\n // \u6536\u96C6 root \u5C42\u9700\u8981\u66F4\u65B0\u6216\u63D2\u5165\u7684 tags\n const rootNeedsEducation = targetDefs.some((d) => d.id === \"education\");\n\n // \u66F4\u65B0 root \u5C42\u5DF2\u5B58\u5728\u7684\u76F8\u5173 tags\n if (rootEverUsed) {\n mutatedRaw.writeInt8(1, rootEverUsed.valueOffset);\n }\n if (rootSaved) {\n mutatedRaw.writeInt8(1, rootSaved.valueOffset);\n }\n if (rootNeedsEducation) {\n const eduTag = parsed.rootChildren.get(\"educationFeaturesEnabled\");\n if (eduTag) {\n mutatedRaw.writeInt8(1, eduTag.valueOffset);\n }\n const optOut = parsed.rootChildren.get(\"has_opted_out_of_education\");\n if (optOut) {\n mutatedRaw.writeInt8(0, optOut.valueOffset);\n }\n }\n\n const rootTagsToAppend: Buffer[] = [];\n if (rootNeedsEducation && !parsed.rootChildren.has(\"educationFeaturesEnabled\")) {\n rootTagsToAppend.push(createByteTagBuffer(\"educationFeaturesEnabled\", 1));\n }\n\n if (!expCompoundTag) {\n // \u573A\u666F 1\uFF1A\u5B8C\u5168\u7F3A\u5931 experiments compound\n const newExpCompoundBuf = createCompoundTagBuffer(\"experiments\", requiredExpTags);\n const rootEndTagIndex = parsed.rootEndOffset - 1;\n const beforeEnd = mutatedRaw.subarray(8, rootEndTagIndex);\n const afterEnd = mutatedRaw.subarray(rootEndTagIndex);\n nbtBody = Buffer.concat([beforeEnd, ...rootTagsToAppend, newExpCompoundBuf, afterEnd]);\n } else {\n // \u573A\u666F 2\uFF1A\u5DF2\u6709 experiments compound\n const { compoundEndOffset: expEndOffset } = parseCompoundChildren(raw, expCompoundTag.valueOffset);\n const expEndTagIndex = expEndOffset - 1;\n const rootEndTagIndex = parsed.rootEndOffset - 1;\n\n const expTagsToAppend: Buffer[] = [];\n for (const [name, val] of Object.entries(requiredExpTags)) {\n const existing = existingExpChildren.get(name);\n if (existing) {\n mutatedRaw.writeInt8(val, existing.valueOffset);\n } else {\n expTagsToAppend.push(createByteTagBuffer(name, val));\n }\n }\n\n // \u7EC4\u88C5\u65B0 NBT body\n // Part 1: root \u5F00\u59CB\u5230 experiments TAG_END \u524D\n const part1 = mutatedRaw.subarray(8, expEndTagIndex);\n // Part 2: \u8FFD\u52A0\u5230 experiments \u5185\u90E8\u7684 tags\n const part2 = Buffer.concat(expTagsToAppend);\n // Part 3: experiments TAG_END \u5230 root TAG_END \u524D\n const part3 = mutatedRaw.subarray(expEndTagIndex, rootEndTagIndex);\n // Part 4: \u8FFD\u52A0\u5230 root \u5C42\u7684 tags (\u5982 educationFeaturesEnabled)\n const part4 = Buffer.concat(rootTagsToAppend);\n // Part 5: root TAG_END \u53CA\u540E\u7EED\n const part5 = mutatedRaw.subarray(rootEndTagIndex);\n\n nbtBody = Buffer.concat([part1, part2, part3, part4, part5]);\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,\n enabledExperiments: enabledIds,\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\n/**\n * \u4E3A\u6307\u5B9A level.dat \u5F00\u542F Beta APIs\uFF08gametest\uFF09\u3002\n * \u4FDD\u6301\u5411\u540E\u517C\u5BB9\uFF0C\u59D4\u6258\u7ED9 enableExperimentsInLevelDat\u3002\n */\nexport async function enableBetaApisInLevelDat(levelDatPath: string): Promise<LevelDatMutateResult> {\n return await enableExperimentsInLevelDat(levelDatPath, [\"gametest\"]);\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -1,53 +1,52 @@
1
1
  /**
2
- * pack-manager.ts — Bedrock 行为包/资源包 装配 + 部署到 BDS 根。
2
+ * pack-manager.ts — Bedrock 行为包(BP)与资源包(RP)组装及部署引擎
3
3
  *
4
- * 纯函数库,两条消费路径:
4
+ * 核心设计与调用路径:
5
+ * - 进程内直连(推荐):`@sfmc-bds/bds-tools/pack-manager-lib` 供 CLI 编排与生命周期管理直接调用(遵循依赖倒置原则)
6
+ * - 独立 CLI:由 `cli-pack-manager.ts` 暴露命令行子命令供脚本与手工调试使用
5
7
  *
6
- * - 同进程(推荐): sfmc/pack-lifecycle 经 `@sfmc-bds/bds-tools/pack-manager-lib`
7
- * 直连本模块(DIP);world-packs 等同理。
8
- * - CLI: `cli-pack-manager.js` 仍暴露相同动词,供外部脚本/手工调试;
9
- * CLI 只是本库的薄适配,不再是 sfmc 主路径。
10
- *
11
- * 约束:本文件不引入 esbuild / 重型 npm-only 包,保持可被 Node 子进程直接加载。
12
- *
13
- * 已有依赖 (bds-tools/package.json):
14
- * - @sfmc-bds/sdk/logs createTerminalProgress: 进度条(BDS 更新等)
15
- * - node-html-parser: changelog 抓取 (本文件用不到)
16
- * - jszip: zip 解压(模块 zip / BDS server.zip)
8
+ * 核心能力:
9
+ * - 行为包组装:将 esbuild 打包后的 `scripts/main.js`、元数据 manifest 与图标封装为 BDS 行为包结构
10
+ * - 资源包聚合:将各模块私有的 `resource_pack` 目录无冲突递归合并为聚合资源包
11
+ * - 世界部署与清单激活:将包部署至 BDS `<level>/behavior_packs` 与 `resource_packs`,并同步维护 `world_behavior_packs.json`
17
12
  */
18
13
  import { copyDirAsync, copyFileAsync } from "./fsx.js";
14
+ import { type PackManifestDependency } from "./dependency-negotiator.js";
15
+ export * from "./dependency-negotiator.js";
19
16
  export interface AssembleBehaviorPackOpts {
20
- /** Where the bundled scripts/main.js already exists (esbuild output dir) */
17
+ /** 已完成打包的 `scripts/main.js` 所在源码目录(即 esbuild 输出目录)。 */
21
18
  srcDir: string;
22
- /** Output behavior pack directory (created if missing) */
19
+ /** 行为包目标输出目录(若不存在则自动创建)。 */
23
20
  outDir: string;
24
- /** BP 目录名 — 默认 'sfmc-modules' */
21
+ /** BP 项目/目录名(默认为 `'sfmc-modules'`)。 */
25
22
  projectName: string;
26
- /** manifest.json 的 header.version [major, minor, patch]; 默认 [1, 0, 0] */
23
+ /** `manifest.json` 中的 `header.version` `[major, minor, patch]`(默认为 `[1, 0, 0]`)。 */
27
24
  version?: [number, number, number] | undefined;
28
- /** manifest.json 的 description */
25
+ /** `manifest.json` 中的包描述信息。 */
29
26
  description?: string | undefined;
30
- /** pack_icon.png 源文件 (optional, 不提供则跳过) */
27
+ /** `pack_icon.png` 图标源文件路径(可选,未提供则跳过)。 */
31
28
  iconSrc?: string | undefined;
32
- /** 稳定 header.uuid;省略则随机生成(首次装配) */
29
+ /** 稳定的 `header.uuid`(缺省时将在首次装配时随机生成)。 */
33
30
  uuid?: string | undefined;
34
- /** 稳定 script module uuid;省略则随机 */
31
+ /** 稳定的 `script module uuid`(缺省时随机生成)。 */
35
32
  moduleUuid?: string | undefined;
33
+ /** 自定义/动态协商后的 dependencies(缺省使用 BASELINE_BEDROCK_DEPENDENCIES)。 */
34
+ dependencies?: PackManifestDependency[] | undefined;
36
35
  }
37
36
  export interface AssembleResourcePackOpts {
38
- /** Modules whose resource_pack/** should be merged. Map<moduleId, resourcePackDir>. */
37
+ /** 需合并资源包目录的模块映射字典(`Record<moduleId, resourcePackDir>`)。 */
39
38
  moduleResourceDirs: Record<string, string>;
40
- /** Output resource pack directory (created if missing) */
39
+ /** 资源包目标输出目录(若不存在则自动创建)。 */
41
40
  outDir: string;
42
- /** RP 目录名 */
41
+ /** RP 项目/目录名。 */
43
42
  projectName: string;
44
- /** manifest.json 的 header.version [major, minor, patch]; 默认 [1, 0, 0] */
43
+ /** `manifest.json` 中的 `header.version` `[major, minor, patch]`(默认为 `[1, 0, 0]`)。 */
45
44
  version?: [number, number, number] | undefined;
46
- /** manifest.json 的 description */
45
+ /** `manifest.json` 中的包描述信息。 */
47
46
  description?: string | undefined;
48
- /** 稳定 header.uuid;省略则随机生成(首次装配) */
47
+ /** 稳定的 `header.uuid`(缺省时随机生成)。 */
49
48
  uuid?: string | undefined;
50
- /** 稳定 resources module uuid;省略则随机 */
49
+ /** 稳定的 `resources module uuid`(缺省时随机生成)。 */
51
50
  moduleUuid?: string | undefined;
52
51
  }
53
52
  export interface AssembleResult {
@@ -90,11 +89,15 @@ export declare function serverPropertiesPath(bdsRoot: string): string;
90
89
  export declare function bdsWorldsDir(bdsRoot: string): string;
91
90
  /** `<bdsRoot>/worlds/<level>` */
92
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;
93
94
  /** 世界 enable-list JSON 绝对路径(单一权威,供读写两侧) */
94
95
  export declare function worldPackListFile(worldsDir: string, levelName: string, kind: "behavior" | "resource"): string;
95
96
  /** `<bdsRoot>/config/<bpUuid>/permission.json` — Script API 权限文件权威路径 */
96
97
  export declare function configPermissionPath(bdsRoot: string, bpUuid: string): string;
97
- /** 是否已有 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) */
98
101
  export declare function hasConfigPermission(bdsRoot: string, bpUuid: string): boolean;
99
102
  /** 随机生成 BP/RP manifest.json header.uuid (RFC 4122 v4) */
100
103
  export declare function randomUuid(): string;
@@ -126,17 +129,21 @@ export declare function readLevelName(bdsRoot: string): Promise<string>;
126
129
  */
127
130
  export declare function deployToBDS(opts: DeployOpts): Promise<DeployResult>;
128
131
  /**
129
- * 确保 BDS Script API 侧 `<bdsRoot>/config/<bpUuid>/permission.json` 存在。
130
- * 已存在则跳过(不覆盖用户手工改动)。
131
- * @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 = 已是最新无需修改
132
137
  */
133
- export declare function ensureConfigPermission(bdsRoot: string, bpUuid: string): Promise<boolean>;
138
+ export declare function ensureConfigPermission(bdsRoot: string, bpUuid: string, moduleUuid?: string): Promise<boolean>;
134
139
  /** 从已装配 BP/RP 目录读取 header.uuid + version;失败返回 null。 */
135
140
  export declare function readPackManifestHeader(packDir: string): {
136
141
  uuid: string;
137
142
  version: [number, number, number];
138
143
  moduleUuid?: string;
139
144
  } | null;
145
+ /** 从已装配 BP/RP 目录读取 dependencies 列表;若无或失败返回 []。 */
146
+ export declare function readPackManifestDependencies(packDir: string): PackManifestDependency[];
140
147
  /**
141
148
  * Write `@minecraft/*` allowed_modules into a behavior pack's
142
149
  * `permissions.json`. Idempotent: rewrites any pre-existing file.
@@ -156,7 +163,7 @@ export declare function writeBehaviorPackManifest(outDir: string, header: {
156
163
  version: [number, number, number];
157
164
  description?: string | undefined;
158
165
  moduleUuid?: string | undefined;
159
- }): Promise<void>;
166
+ }, dependencies?: PackManifestDependency[] | undefined): Promise<void>;
160
167
  export declare function writeResourcePackManifest(outDir: string, header: {
161
168
  name: string;
162
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":"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"}
@@ -1,6 +1,10 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { copyDirAsync, copyFileAsync, readJsonFile } from "./fsx.js";
4
+ import {
5
+ BASELINE_BEDROCK_DEPENDENCIES
6
+ } from "./dependency-negotiator.js";
7
+ export * from "./dependency-negotiator.js";
4
8
  const SFMC_PERMISSIONS = [
5
9
  "@minecraft/server",
6
10
  "@minecraft/server-ui",
@@ -19,6 +23,9 @@ function bdsWorldsDir(bdsRoot) {
19
23
  function bdsWorldLevelDir(bdsRoot, levelName) {
20
24
  return path.join(bdsWorldsDir(bdsRoot), levelName);
21
25
  }
26
+ function levelDatPath(bdsRoot, levelName) {
27
+ return path.join(bdsWorldLevelDir(bdsRoot, levelName), "level.dat");
28
+ }
22
29
  function worldPackListFile(worldsDir, levelName, kind) {
23
30
  const name = kind === "behavior" ? "world_behavior_packs.json" : "world_resource_packs.json";
24
31
  return path.join(worldsDir, levelName, name);
@@ -26,8 +33,11 @@ function worldPackListFile(worldsDir, levelName, kind) {
26
33
  function configPermissionPath(bdsRoot, bpUuid) {
27
34
  return path.join(bdsRoot, "config", bpUuid, "permission.json");
28
35
  }
36
+ function configPermissionsPath(bdsRoot, bpUuid) {
37
+ return path.join(bdsRoot, "config", bpUuid, "permissions.json");
38
+ }
29
39
  function hasConfigPermission(bdsRoot, bpUuid) {
30
- return fs.existsSync(configPermissionPath(bdsRoot, bpUuid));
40
+ return fs.existsSync(configPermissionsPath(bdsRoot, bpUuid)) || fs.existsSync(configPermissionPath(bdsRoot, bpUuid));
31
41
  }
32
42
  function randomUuid() {
33
43
  return crypto.randomUUID();
@@ -43,13 +53,17 @@ async function assembleBehaviorPack(opts) {
43
53
  await fs.promises.mkdir(path.join(opts.outDir, "scripts"), { recursive: true });
44
54
  await fs.promises.writeFile(path.join(opts.outDir, "scripts", "main.js"), "/* no scripts */\n", "utf8");
45
55
  }
46
- await writeBehaviorPackManifest(opts.outDir, {
47
- name: opts.projectName,
48
- uuid: bpUuid,
49
- version,
50
- description: opts.description,
51
- moduleUuid: opts.moduleUuid
52
- });
56
+ await writeBehaviorPackManifest(
57
+ opts.outDir,
58
+ {
59
+ name: opts.projectName,
60
+ uuid: bpUuid,
61
+ version,
62
+ description: opts.description,
63
+ moduleUuid: opts.moduleUuid
64
+ },
65
+ opts.dependencies
66
+ );
53
67
  if (opts.iconSrc && fs.existsSync(opts.iconSrc)) {
54
68
  await copyFileAsync(opts.iconSrc, path.join(opts.outDir, "pack_icon.png"));
55
69
  }
@@ -109,16 +123,42 @@ async function deployToBDS(opts) {
109
123
  }
110
124
  return { bpDir: bpDst, rpDir };
111
125
  }
112
- async function ensureConfigPermission(bdsRoot, bpUuid) {
113
- const file = configPermissionPath(bdsRoot, bpUuid);
114
- if (fs.existsSync(file)) return false;
115
- const dir = path.dirname(file);
116
- await fs.promises.mkdir(dir, { recursive: true });
117
- const payload = { allowed_modules: [...SFMC_PERMISSIONS] };
118
- const tmp = path.join(dir, `.permission.${process.pid}.tmp`);
119
- await fs.promises.writeFile(tmp, JSON.stringify(payload, null, 2) + "\n", "utf8");
120
- await fs.promises.rename(tmp, file);
121
- return true;
126
+ async function ensureConfigPermission(bdsRoot, bpUuid, moduleUuid) {
127
+ let changed = false;
128
+ const updateFile = async (filePath) => {
129
+ let currentModules = [];
130
+ let restConfig = {};
131
+ if (fs.existsSync(filePath)) {
132
+ try {
133
+ const raw = readJsonFile(filePath);
134
+ if (Array.isArray(raw.allowed_modules)) {
135
+ currentModules = raw.allowed_modules;
136
+ }
137
+ const { allowed_modules: _, ...rest } = raw;
138
+ restConfig = rest;
139
+ } catch {
140
+ }
141
+ }
142
+ const merged = Array.from(/* @__PURE__ */ new Set([...currentModules, ...SFMC_PERMISSIONS]));
143
+ if (merged.length === currentModules.length && fs.existsSync(filePath)) {
144
+ return false;
145
+ }
146
+ const dir = path.dirname(filePath);
147
+ await fs.promises.mkdir(dir, { recursive: true });
148
+ const payload = { allowed_modules: merged, ...restConfig };
149
+ const tmp = path.join(dir, `.permission.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`);
150
+ await fs.promises.writeFile(tmp, JSON.stringify(payload, null, 2) + "\n", "utf8");
151
+ await fs.promises.rename(tmp, filePath);
152
+ return true;
153
+ };
154
+ const uuids = Array.from(/* @__PURE__ */ new Set([bpUuid, ...moduleUuid ? [moduleUuid] : []]));
155
+ for (const u of uuids) {
156
+ if (await updateFile(configPermissionsPath(bdsRoot, u))) changed = true;
157
+ if (await updateFile(configPermissionPath(bdsRoot, u))) changed = true;
158
+ }
159
+ const defaultFile = path.join(bdsRoot, "config", "default", "permissions.json");
160
+ if (await updateFile(defaultFile)) changed = true;
161
+ return changed;
122
162
  }
123
163
  function readPackManifestHeader(packDir) {
124
164
  const file = path.join(packDir, "manifest.json");
@@ -135,6 +175,16 @@ function readPackManifestHeader(packDir) {
135
175
  return null;
136
176
  }
137
177
  }
178
+ function readPackManifestDependencies(packDir) {
179
+ const file = path.join(packDir, "manifest.json");
180
+ if (!fs.existsSync(file)) return [];
181
+ try {
182
+ const raw = readJsonFile(file);
183
+ return Array.isArray(raw.dependencies) ? raw.dependencies : [];
184
+ } catch {
185
+ return [];
186
+ }
187
+ }
138
188
  async function writePermissionsJson(bpDir) {
139
189
  const payload = { allowed_modules: [...SFMC_PERMISSIONS] };
140
190
  await fs.promises.mkdir(bpDir, { recursive: true });
@@ -164,7 +214,7 @@ async function editWorldPackList(opts, mode) {
164
214
  await fs.promises.writeFile(tmp, JSON.stringify(entries, null, 2) + "\n", "utf8");
165
215
  await fs.promises.rename(tmp, file);
166
216
  }
167
- async function writeBehaviorPackManifest(outDir, header) {
217
+ async function writeBehaviorPackManifest(outDir, header, dependencies) {
168
218
  const manifest = {
169
219
  format_version: 2,
170
220
  header: {
@@ -183,11 +233,7 @@ async function writeBehaviorPackManifest(outDir, header) {
183
233
  version: header.version
184
234
  }
185
235
  ],
186
- dependencies: [
187
- { module_name: "@minecraft/server", version: "1.18.0" },
188
- { module_name: "@minecraft/server-admin", version: "1.0.0-beta" },
189
- { module_name: "@minecraft/diagnostics", version: "1.0.0-beta" }
190
- ]
236
+ dependencies: dependencies && dependencies.length > 0 ? dependencies : BASELINE_BEDROCK_DEPENDENCIES
191
237
  };
192
238
  const file = path.join(outDir, "manifest.json");
193
239
  await fs.promises.mkdir(outDir, { recursive: true });
@@ -219,7 +265,12 @@ function scanModuleResourcePacks(modulesDir) {
219
265
  const out = {};
220
266
  if (!fs.existsSync(modulesDir)) return out;
221
267
  for (const entry of fs.readdirSync(modulesDir, { withFileTypes: true })) {
222
- if (!entry.isDirectory()) continue;
268
+ if (entry.name.startsWith(".")) continue;
269
+ try {
270
+ if (!fs.statSync(path.join(modulesDir, entry.name)).isDirectory()) continue;
271
+ } catch {
272
+ continue;
273
+ }
223
274
  const rpDir = path.join(modulesDir, entry.name, "resource_pack");
224
275
  if (fs.existsSync(rpDir)) {
225
276
  out[entry.name] = rpDir;
@@ -276,6 +327,7 @@ export {
276
327
  bdsWorldLevelDir,
277
328
  bdsWorldsDir,
278
329
  configPermissionPath,
330
+ configPermissionsPath,
279
331
  copyDirAsync,
280
332
  copyFileAsync,
281
333
  deployToBDS,
@@ -283,10 +335,12 @@ export {
283
335
  enablePackInWorld,
284
336
  ensureConfigPermission,
285
337
  hasConfigPermission,
338
+ levelDatPath,
286
339
  loadModuleResourcePackMap,
287
340
  randomUuid,
288
341
  readLevelName,
289
342
  readLevelNameSync,
343
+ readPackManifestDependencies,
290
344
  readPackManifestHeader,
291
345
  readWorldPackList,
292
346
  readWorldPackListResult,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/pack-manager.ts"],
4
- "sourcesContent": ["/**\n * pack-manager.ts \u2014 Bedrock \u884C\u4E3A\u5305/\u8D44\u6E90\u5305 \u88C5\u914D + \u90E8\u7F72\u5230 BDS \u6839\u3002\n *\n * \u7EAF\u51FD\u6570\u5E93,\u4E24\u6761\u6D88\u8D39\u8DEF\u5F84:\n *\n * - \u540C\u8FDB\u7A0B(\u63A8\u8350): sfmc/pack-lifecycle \u7ECF `@sfmc-bds/bds-tools/pack-manager-lib`\n * \u76F4\u8FDE\u672C\u6A21\u5757\uFF08DIP\uFF09\uFF1Bworld-packs \u7B49\u540C\u7406\u3002\n * - CLI: `cli-pack-manager.js` \u4ECD\u66B4\u9732\u76F8\u540C\u52A8\u8BCD\uFF0C\u4F9B\u5916\u90E8\u811A\u672C/\u624B\u5DE5\u8C03\u8BD5\uFF1B\n * CLI \u53EA\u662F\u672C\u5E93\u7684\u8584\u9002\u914D\uFF0C\u4E0D\u518D\u662F sfmc \u4E3B\u8DEF\u5F84\u3002\n *\n * \u7EA6\u675F:\u672C\u6587\u4EF6\u4E0D\u5F15\u5165 esbuild / \u91CD\u578B npm-only \u5305\uFF0C\u4FDD\u6301\u53EF\u88AB Node \u5B50\u8FDB\u7A0B\u76F4\u63A5\u52A0\u8F7D\u3002\n *\n * \u5DF2\u6709\u4F9D\u8D56 (bds-tools/package.json):\n * - @sfmc-bds/sdk/logs createTerminalProgress: \u8FDB\u5EA6\u6761\uFF08BDS \u66F4\u65B0\u7B49\uFF09\n * - node-html-parser: changelog \u6293\u53D6 (\u672C\u6587\u4EF6\u7528\u4E0D\u5230)\n * - jszip: zip \u89E3\u538B(\u6A21\u5757 zip / BDS server.zip)\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { copyDirAsync, copyFileAsync, readJsonFile } from \"./fsx.js\";\n\n/* \u2500\u2500 \u7C7B\u578B \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nexport interface AssembleBehaviorPackOpts {\n /** Where the bundled scripts/main.js already exists (esbuild output dir) */\n srcDir: string;\n /** Output behavior pack directory (created if missing) */\n outDir: string;\n /** BP \u76EE\u5F55\u540D \u2014 \u9ED8\u8BA4 'sfmc-modules' */\n projectName: string;\n /** manifest.json \u7684 header.version [major, minor, patch]; \u9ED8\u8BA4 [1, 0, 0] */\n version?: [number, number, number] | undefined;\n /** manifest.json \u7684 description */\n description?: string | undefined;\n /** pack_icon.png \u6E90\u6587\u4EF6 (optional, \u4E0D\u63D0\u4F9B\u5219\u8DF3\u8FC7) */\n iconSrc?: string | undefined;\n /** \u7A33\u5B9A header.uuid;\u7701\u7565\u5219\u968F\u673A\u751F\u6210(\u9996\u6B21\u88C5\u914D) */\n uuid?: string | undefined;\n /** \u7A33\u5B9A script module uuid;\u7701\u7565\u5219\u968F\u673A */\n moduleUuid?: string | undefined;\n}\n\nexport interface AssembleResourcePackOpts {\n /** Modules whose resource_pack/** should be merged. Map<moduleId, resourcePackDir>. */\n moduleResourceDirs: Record<string, string>;\n /** Output resource pack directory (created if missing) */\n outDir: string;\n /** RP \u76EE\u5F55\u540D */\n projectName: string;\n /** manifest.json \u7684 header.version [major, minor, patch]; \u9ED8\u8BA4 [1, 0, 0] */\n version?: [number, number, number] | undefined;\n /** manifest.json \u7684 description */\n description?: string | undefined;\n /** \u7A33\u5B9A header.uuid;\u7701\u7565\u5219\u968F\u673A\u751F\u6210(\u9996\u6B21\u88C5\u914D) */\n uuid?: string | undefined;\n /** \u7A33\u5B9A resources module uuid;\u7701\u7565\u5219\u968F\u673A */\n moduleUuid?: string | undefined;\n}\n\nexport interface AssembleResult {\n uuid: string;\n version: [number, number, number];\n}\n\nexport interface DeployOpts {\n bdsRoot: string;\n levelName: string;\n /** \u5DF2\u7EC4\u88C5\u597D\u7684 BP \u6E90\u76EE\u5F55 */\n behaviorPackSrc: string;\n /** \u5DF2\u7EC4\u88C5\u597D\u7684 RP \u6E90\u76EE\u5F55 (\u53EF\u7701\u7565,\u53EA\u7528 BP \u4E5F\u5408\u6CD5) */\n resourcePackSrc?: string;\n /** BP \u76EE\u6807\u76EE\u5F55\u540D (worlds/<level>/behavior_packs/<bpName>) */\n bpName: string;\n /** RP \u76EE\u6807\u76EE\u5F55\u540D (worlds/<level>/resource_packs/<rpName>);\u7701\u7565\u65F6\u590D\u7528 bpName + '-rp' */\n rpName?: string;\n /**\n * \u65E0 resourcePackSrc \u65F6\u662F\u5426\u5220\u9664\u4E16\u754C\u5185\u5DF2\u6709 RP \u76EE\u5F55\u3002\n * \u7528\u4E8E\u6A21\u5757\u4E0D\u518D\u63D0\u4F9B RP \u65F6\u6E05\u7406\u805A\u5408\u5305\u6B8B\u7559(\u9ED8\u8BA4 false,\u907F\u514D\u8BEF\u5220\u672A\u58F0\u660E\u7684 RP)\u3002\n */\n clearResourcePack?: boolean;\n}\n\nexport interface DeployResult {\n bpDir: string;\n rpDir: string | null;\n}\n\nexport interface EnablePackOpts {\n worldsDir: string;\n levelName: string;\n kind: \"behavior\" | \"resource\";\n packUuid: string;\n version: [number, number, number];\n}\n\n/* \u2500\u2500 \u8DEF\u5F84\u5E38\u91CF \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/** SFMC \u5408\u6210 BP \u7684\u56FA\u5B9A @minecraft/* permissions,\u6240\u6709\u7528\u5230\u7684\u547D\u540D\u7A7A\u95F4\u90FD\u6253\u5F00\u3002 */\nexport const SFMC_PERMISSIONS = [\n \"@minecraft/server\",\n \"@minecraft/server-ui\",\n \"@minecraft/server-admin\",\n \"@minecraft/server-gametest\",\n \"@minecraft/server-net\",\n \"@minecraft/server-editor\",\n \"@minecraft/diagnostics\",\n] as const;\n\n/** `<bdsRoot>/server.properties` \u2014 level-name / telemetry \u7B49\u5171\u7528\uFF08DRY\uFF09 */\nexport function serverPropertiesPath(bdsRoot: string): string {\n return path.join(bdsRoot, \"server.properties\");\n}\n\n/** `<bdsRoot>/worlds` \u2014 enable-list / \u90E8\u7F72\u8C03\u7528\u65B9\u52FF\u518D\u786C\u62FC\uFF08Demeter\uFF09 */\nexport function bdsWorldsDir(bdsRoot: string): string {\n return path.join(bdsRoot, \"worlds\");\n}\n\n/** `<bdsRoot>/worlds/<level>` */\nexport function bdsWorldLevelDir(bdsRoot: string, levelName: string): string {\n return path.join(bdsWorldsDir(bdsRoot), levelName);\n}\n\n/** \u4E16\u754C enable-list JSON \u7EDD\u5BF9\u8DEF\u5F84\uFF08\u5355\u4E00\u6743\u5A01\uFF0C\u4F9B\u8BFB\u5199\u4E24\u4FA7\uFF09 */\nexport function worldPackListFile(\n worldsDir: string,\n levelName: string,\n kind: \"behavior\" | \"resource\"\n): string {\n const name = kind === \"behavior\" ? \"world_behavior_packs.json\" : \"world_resource_packs.json\";\n return path.join(worldsDir, levelName, name);\n}\n\n/** `<bdsRoot>/config/<bpUuid>/permission.json` \u2014 Script API \u6743\u9650\u6587\u4EF6\u6743\u5A01\u8DEF\u5F84 */\nexport function configPermissionPath(bdsRoot: string, bpUuid: string): string {\n return path.join(bdsRoot, \"config\", bpUuid, \"permission.json\");\n}\n\n/** \u662F\u5426\u5DF2\u6709 Script API permission.json\uFF08\u53EA\u8BFB\uFF0C\u4F9B preflight/status\uFF09 */\nexport function hasConfigPermission(bdsRoot: string, bpUuid: string): boolean {\n return fs.existsSync(configPermissionPath(bdsRoot, bpUuid));\n}\n\n/** \u968F\u673A\u751F\u6210 BP/RP manifest.json header.uuid (RFC 4122 v4) */\nexport function randomUuid(): string {\n /* crypto.randomUUID \u662F Node 19+ \u5185\u7F6E,\u8FD9\u91CC\u76F4\u63A5\u7528 */\n return crypto.randomUUID();\n}\n\n/* \u2500\u2500 \u9AA8\u67B6\u51FD\u6570 (Commit 5 \u5B9E\u73B0) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/**\n * Assemble a Bedrock behavior pack directory at `outDir` from a prebuilt\n * `srcDir` (which must already contain `scripts/main.js` plus whatever else\n * was bundled by esbuild) and write a fresh `manifest.json` + `permissions.json`.\n *\n * The caller is responsible for running esbuild first; pack-manager does not\n * bundle scripts. That decoupling keeps pack assembly independent of the bundler.\n */\nexport async function assembleBehaviorPack(opts: AssembleBehaviorPackOpts): Promise<AssembleResult> {\n const version = opts.version ?? [1, 0, 0];\n const bpUuid = opts.uuid ?? randomUuid();\n await fs.promises.rm(opts.outDir, { recursive: true, force: true });\n await fs.promises.mkdir(opts.outDir, { recursive: true });\n if (fs.existsSync(opts.srcDir)) {\n await copyDirAsync(opts.srcDir, opts.outDir);\n } else {\n await fs.promises.mkdir(path.join(opts.outDir, \"scripts\"), { recursive: true });\n await fs.promises.writeFile(path.join(opts.outDir, \"scripts\", \"main.js\"), \"/* no scripts */\\n\", \"utf8\");\n }\n await writeBehaviorPackManifest(opts.outDir, {\n name: opts.projectName,\n uuid: bpUuid,\n version,\n description: opts.description,\n moduleUuid: opts.moduleUuid,\n });\n if (opts.iconSrc && fs.existsSync(opts.iconSrc)) {\n await copyFileAsync(opts.iconSrc, path.join(opts.outDir, \"pack_icon.png\"));\n }\n await writePermissionsJson(opts.outDir);\n return { uuid: bpUuid, version };\n}\n\n/**\n * Merge every enabled module's `resource_pack/**` tree into one RP directory\n * at `outDir`, with a single fresh `manifest.json`. Per-module subfolders are\n * preserved so resource pack authors can disambiguate (e.g. `peace/textures/...`).\n */\nexport async function assembleResourcePack(opts: AssembleResourcePackOpts): Promise<AssembleResult> {\n const version = opts.version ?? [1, 0, 0];\n const rpUuid = opts.uuid ?? randomUuid();\n await fs.promises.rm(opts.outDir, { recursive: true, force: true });\n await fs.promises.mkdir(opts.outDir, { recursive: true });\n for (const [moduleId, rpDir] of Object.entries(opts.moduleResourceDirs)) {\n if (!fs.existsSync(rpDir)) continue;\n const dst = path.join(opts.outDir, moduleId);\n await fs.promises.mkdir(dst, { recursive: true });\n await copyDirAsync(rpDir, dst);\n }\n await writeResourcePackManifest(opts.outDir, {\n name: opts.projectName,\n uuid: rpUuid,\n version,\n description: opts.description,\n moduleUuid: opts.moduleUuid,\n });\n return { uuid: rpUuid, version };\n}\n\n/**\n * Read the `level-name=` value from `<bdsRoot>/server.properties`.\n * Falls back to \"Bedrock level\" (BDS default) when the file is missing or\n * the key is absent.\n */\nfunction parseLevelNameFromProperties(text: string): string {\n for (const line of text.split(/\\r?\\n/)) {\n const m = /^\\s*level-name\\s*=\\s*(.+?)\\s*$/.exec(line);\n if (m && m[1]) return m[1];\n }\n return \"Bedrock level\";\n}\n\n/** \u540C\u6B65\u8BFB level-name\uFF08\u4F9B sfmc resolveBdsContext \u7B49\u540C\u8FDB\u7A0B\u8C03\u7528\u65B9\uFF0CDRY\uFF09\u3002 */\nexport function readLevelNameSync(bdsRoot: string): string {\n const file = serverPropertiesPath(bdsRoot);\n if (!fs.existsSync(file)) return \"Bedrock level\";\n return parseLevelNameFromProperties(fs.readFileSync(file, \"utf8\"));\n}\n\n/** \u4E0E sync \u540C\u5951\u7EA6\uFF1BCLI / async \u8C03\u7528\u65B9\u8D70\u6B64\u5165\u53E3\uFF08LSP\uFF09 */\nexport async function readLevelName(bdsRoot: string): Promise<string> {\n return readLevelNameSync(bdsRoot);\n}\n\n/**\n * Copy BP/RP source dirs into the world's behavior_packs/ + resource_packs/\n * folders, and write a fresh `permissions.json` into the BP target.\n *\n * Does NOT edit world_behavior_packs.json \u2014 that's a separate step the caller\n * must invoke after restart, because BDS only reads that file at startup.\n */\nexport async function deployToBDS(opts: DeployOpts): Promise<DeployResult> {\n /* levelDir = worlds/<level>\uFF1B\u4E0E EnablePackOpts.worldsDir(=worlds/) \u8BED\u4E49\u4E0D\u540C \u2014 \u52FF\u6DF7\u7528\uFF08LSP\uFF09 */\n const levelDir = bdsWorldLevelDir(opts.bdsRoot, opts.levelName);\n const bpDst = path.join(levelDir, \"behavior_packs\", opts.bpName);\n const rpDst = path.join(levelDir, \"resource_packs\", opts.rpName ?? `${opts.bpName}-rp`);\n await fs.promises.mkdir(levelDir, { recursive: true });\n await fs.promises.rm(bpDst, { recursive: true, force: true });\n await copyDirAsync(opts.behaviorPackSrc, bpDst);\n await writePermissionsJson(bpDst);\n let rpDir: string | null = null;\n if (opts.resourcePackSrc && fs.existsSync(opts.resourcePackSrc)) {\n await fs.promises.rm(rpDst, { recursive: true, force: true });\n await copyDirAsync(opts.resourcePackSrc, rpDst);\n rpDir = rpDst;\n } else if (opts.clearResourcePack) {\n /* \u8C03\u7528\u65B9\u663E\u5F0F\u58F0\u660E\u4E0D\u518D\u90E8\u7F72 RP \u2014 \u6E05\u6389\u805A\u5408 RP \u76EE\u5F55\u6B8B\u7559 */\n await fs.promises.rm(rpDst, { recursive: true, force: true });\n }\n return { bpDir: bpDst, rpDir };\n}\n\n/**\n * \u786E\u4FDD BDS Script API \u4FA7 `<bdsRoot>/config/<bpUuid>/permission.json` \u5B58\u5728\u3002\n * \u5DF2\u5B58\u5728\u5219\u8DF3\u8FC7(\u4E0D\u8986\u76D6\u7528\u6237\u624B\u5DE5\u6539\u52A8)\u3002\n * @returns true = \u65B0\u5199\u5165; false = \u5DF2\u5B58\u5728\u8DF3\u8FC7\n */\nexport async function ensureConfigPermission(bdsRoot: string, bpUuid: string): Promise<boolean> {\n const file = configPermissionPath(bdsRoot, bpUuid);\n if (fs.existsSync(file)) return false;\n const dir = path.dirname(file);\n await fs.promises.mkdir(dir, { recursive: true });\n const payload = { allowed_modules: [...SFMC_PERMISSIONS] };\n const tmp = path.join(dir, `.permission.${process.pid}.tmp`);\n await fs.promises.writeFile(tmp, JSON.stringify(payload, null, 2) + \"\\n\", \"utf8\");\n await fs.promises.rename(tmp, file);\n return true;\n}\n\n/** \u4ECE\u5DF2\u88C5\u914D BP/RP \u76EE\u5F55\u8BFB\u53D6 header.uuid + version;\u5931\u8D25\u8FD4\u56DE null\u3002 */\nexport function readPackManifestHeader(\n packDir: string\n): { uuid: string; version: [number, number, number]; moduleUuid?: string } | null {\n const file = path.join(packDir, \"manifest.json\");\n if (!fs.existsSync(file)) return null;\n try {\n const raw = readJsonFile<{\n header?: { uuid?: string; version?: number[] };\n modules?: Array<{ uuid?: string }>;\n }>(file);\n const uuid = raw.header?.uuid;\n const ver = raw.header?.version;\n if (typeof uuid !== \"string\" || !Array.isArray(ver) || ver.length < 3) return null;\n const version: [number, number, number] = [Number(ver[0]), Number(ver[1]), Number(ver[2])];\n const moduleUuid = raw.modules?.[0]?.uuid;\n return { uuid, version, ...(typeof moduleUuid === \"string\" ? { moduleUuid } : {}) };\n } catch {\n return null;\n }\n}\n\n/**\n * Write `@minecraft/*` allowed_modules into a behavior pack's\n * `permissions.json`. Idempotent: rewrites any pre-existing file.\n */\nexport async function writePermissionsJson(bpDir: string): Promise<void> {\n const payload = { allowed_modules: [...SFMC_PERMISSIONS] };\n await fs.promises.mkdir(bpDir, { recursive: true });\n const tmp = path.join(bpDir, `.permissions.${process.pid}.tmp`);\n await fs.promises.writeFile(tmp, JSON.stringify(payload, null, 2) + \"\\n\", \"utf8\");\n await fs.promises.rename(tmp, path.join(bpDir, \"permissions.json\"));\n}\n\n/**\n * Add `{ pack_id, version }` to `worlds/<level>/world_behavior_packs.json`\n * (or `world_resource_packs.json`). If the pack_id already exists, replace its\n * version. File missing \u2192 initialize as `[]`.\n */\nexport async function enablePackInWorld(opts: EnablePackOpts): Promise<void> {\n await editWorldPackList(opts, \"enable\");\n}\n\n/** Remove a pack_id from the world's enable-list JSON. */\nexport async function disablePackInWorld(opts: EnablePackOpts): Promise<void> {\n await editWorldPackList(opts, \"disable\");\n}\n\ninterface WorldPackEntry {\n pack_id: string;\n version: [number, number, number];\n}\n\nasync function editWorldPackList(\n opts: EnablePackOpts,\n mode: \"enable\" | \"disable\"\n): Promise<void> {\n const file = worldPackListFile(opts.worldsDir, opts.levelName, opts.kind);\n /* \u4E0E readWorldPackList \u540C\u6E90\u89E3\u6790,\u518D\u5199\u56DE(DRY);\u5F02\u6B65\u5199\u8DEF\u5F84\u4FDD\u7559\u539F\u8BED\u4E49 */\n let entries: WorldPackEntry[] = readWorldPackList(opts.worldsDir, opts.levelName, opts.kind);\n const idx = entries.findIndex((e) => e.pack_id === opts.packUuid);\n if (mode === \"enable\") {\n const next: WorldPackEntry = { pack_id: opts.packUuid, version: opts.version };\n if (idx >= 0) entries[idx] = next;\n else entries.push(next);\n } else {\n if (idx >= 0) entries.splice(idx, 1);\n }\n await fs.promises.mkdir(path.dirname(file), { recursive: true });\n const tmp = `${file}.${process.pid}.tmp`;\n await fs.promises.writeFile(tmp, JSON.stringify(entries, null, 2) + \"\\n\", \"utf8\");\n await fs.promises.rename(tmp, file);\n}\n\n/* \u2500\u2500 \u4F4E\u5C42 helpers (Commit 5 \u5B9E\u73B0) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nexport async function writeBehaviorPackManifest(\n outDir: string,\n header: {\n name: string;\n uuid: string;\n version: [number, number, number];\n description?: string | undefined;\n moduleUuid?: string | undefined;\n }\n): Promise<void> {\n const manifest = {\n format_version: 2,\n header: {\n name: header.name,\n uuid: header.uuid,\n version: header.version,\n description: header.description ? `${header.description} (behavior pack)` : \"SFMC behavior pack\",\n min_engine_version: [1, 21, 0],\n },\n modules: [\n {\n type: \"script\",\n language: \"javascript\",\n entry: \"scripts/main.js\",\n uuid: header.moduleUuid ?? crypto.randomUUID(),\n version: header.version,\n },\n ],\n dependencies: [\n { module_name: \"@minecraft/server\", version: \"1.18.0\" },\n { module_name: \"@minecraft/server-admin\", version: \"1.0.0-beta\" },\n { module_name: \"@minecraft/diagnostics\", version: \"1.0.0-beta\" },\n ],\n };\n const file = path.join(outDir, \"manifest.json\");\n await fs.promises.mkdir(outDir, { recursive: true });\n await fs.promises.writeFile(file, JSON.stringify(manifest, null, 2) + \"\\n\", \"utf8\");\n}\n\nexport async function writeResourcePackManifest(\n outDir: string,\n header: {\n name: string;\n uuid: string;\n version: [number, number, number];\n description?: string | undefined;\n moduleUuid?: string | undefined;\n }\n): Promise<void> {\n const manifest = {\n format_version: 2,\n header: {\n name: header.name,\n uuid: header.uuid,\n version: header.version,\n description: header.description ? `${header.description} (resource pack)` : \"SFMC resource pack\",\n min_engine_version: [1, 21, 0],\n },\n modules: [\n {\n type: \"resources\",\n uuid: header.moduleUuid ?? crypto.randomUUID(),\n version: header.version,\n },\n ],\n };\n const file = path.join(outDir, \"manifest.json\");\n await fs.promises.mkdir(outDir, { recursive: true });\n await fs.promises.writeFile(file, JSON.stringify(manifest, null, 2) + \"\\n\", \"utf8\");\n}\n\n/* Re-export copyFileAsync so callers can copy icon without\n * pulling in the full fsx surface area. */\nexport { copyFileAsync, copyDirAsync };\n\n/* \u2500\u2500 Discovery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/**\n * Walk `<modulesDir>/<id>/resource_pack/` for every installed module and\n * return a map { id: absoluteDir }. Modules without a resource_pack folder\n * are silently skipped. Used by `assemble-rp` and the sfmc CLI to know which\n * modules to merge into the resource pack output.\n */\nexport function scanModuleResourcePacks(modulesDir: string): Record<string, string> {\n const out: Record<string, string> = {};\n if (!fs.existsSync(modulesDir)) return out;\n for (const entry of fs.readdirSync(modulesDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n const rpDir = path.join(modulesDir, entry.name, \"resource_pack\");\n if (fs.existsSync(rpDir)) {\n out[entry.name] = rpDir;\n }\n }\n return out;\n}\n\n/**\n * \u4ECE JSON \u6587\u4EF6\u52A0\u8F7D\u663E\u5F0F moduleId \u2192 resource_pack \u76EE\u5F55\u6620\u5C04\u3002\n * \u4F9B assemble-rp --modules-json \u4F7F\u7528,\u907F\u514D\u8C03\u7528\u65B9\u518D\u505A\u4E34\u65F6\u76EE\u5F55\u955C\u50CF(OCP/DRY)\u3002\n */\nexport function loadModuleResourcePackMap(jsonPath: string): Record<string, string> {\n const raw = JSON.parse(fs.readFileSync(jsonPath, \"utf8\")) as unknown;\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new Error(`modules-json must be an object: ${jsonPath}`);\n }\n const out: Record<string, string> = {};\n for (const [id, dir] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof id !== \"string\" || !id || typeof dir !== \"string\" || !dir) continue;\n const abs = path.resolve(dir);\n if (!fs.existsSync(abs)) {\n throw new Error(`modules-json entry missing: ${id} \u2192 ${abs}`);\n }\n out[id] = abs;\n }\n return out;\n}\n\n/**\n * \u8BFB\u53D6\u4E16\u754C enable-list(\u5355\u4E00\u6743\u5A01,\u4F9B has-pack / list-packs / \u8C03\u7528\u65B9\u590D\u7528 \u2014 DRY)\u3002\n * \u6587\u4EF6\u7F3A\u5931 \u2192 entries=[]\uFF1BJSON \u635F\u574F \u2192 entries=[] \u4E14 parseFailedFile \u6709\u503C\uFF08\u4F9B doctor \u533A\u5206\uFF09\u3002\n */\nexport type WorldPackListReadResult = {\n entries: Array<{ pack_id: string; version: [number, number, number] }>;\n /** \u6587\u4EF6\u5B58\u5728\u4F46\u89E3\u6790\u5931\u8D25\u65F6\u4E3A\u8BE5 JSON \u7EDD\u5BF9\u8DEF\u5F84 */\n parseFailedFile?: string;\n};\n\nexport function readWorldPackListResult(\n worldsDir: string,\n levelName: string,\n kind: \"behavior\" | \"resource\"\n): WorldPackListReadResult {\n const file = worldPackListFile(worldsDir, levelName, kind);\n if (!fs.existsSync(file)) return { entries: [] };\n try {\n const arr = JSON.parse(fs.readFileSync(file, \"utf8\")) as unknown;\n if (!Array.isArray(arr)) return { entries: [], parseFailedFile: file };\n const out: Array<{ pack_id: string; version: [number, number, number] }> = [];\n for (const e of arr) {\n if (!e || typeof e !== \"object\") continue;\n const packId = (e as { pack_id?: unknown }).pack_id;\n const ver = (e as { version?: unknown }).version;\n if (typeof packId !== \"string\" || !packId) continue;\n const version: [number, number, number] =\n Array.isArray(ver) && ver.length >= 3\n ? [Number(ver[0]), Number(ver[1]), Number(ver[2])]\n : [1, 0, 0];\n out.push({ pack_id: packId, version });\n }\n return { entries: out };\n } catch {\n return { entries: [], parseFailedFile: file };\n }\n}\n\n/** \u517C\u5BB9\u8BFB\u4FA7\uFF1A\u53EA\u8981 entries\uFF08\u635F\u574F\u65F6\u4E0E\u7F3A\u5931\u540C\u4E3A []\uFF09\u3002\u8BE6\u7EC6\u7ED3\u679C\u89C1 readWorldPackListResult\u3002 */\nexport function readWorldPackList(\n worldsDir: string,\n levelName: string,\n kind: \"behavior\" | \"resource\"\n): Array<{ pack_id: string; version: [number, number, number] }> {\n return readWorldPackListResult(worldsDir, levelName, kind).entries;\n}\n\n/** \u4E16\u754C enable-list \u662F\u5426\u5DF2\u542B\u6307\u5B9A pack_id(\u53EA\u8BFB,\u4F9B preflight \u590D\u7528)\u3002 */\nexport function worldPackListHas(\n worldsDir: string,\n levelName: string,\n kind: \"behavior\" | \"resource\",\n packUuid: string\n): boolean {\n return readWorldPackList(worldsDir, levelName, kind).some((e) => e.pack_id === packUuid);\n}"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * pack-manager.ts \u2014 Bedrock \u884C\u4E3A\u5305\uFF08BP\uFF09\u4E0E\u8D44\u6E90\u5305\uFF08RP\uFF09\u7EC4\u88C5\u53CA\u90E8\u7F72\u5F15\u64CE\n *\n * \u6838\u5FC3\u8BBE\u8BA1\u4E0E\u8C03\u7528\u8DEF\u5F84\uFF1A\n * - \u8FDB\u7A0B\u5185\u76F4\u8FDE\uFF08\u63A8\u8350\uFF09\uFF1A`@sfmc-bds/bds-tools/pack-manager-lib` \u4F9B CLI \u7F16\u6392\u4E0E\u751F\u547D\u5468\u671F\u7BA1\u7406\u76F4\u63A5\u8C03\u7528\uFF08\u9075\u5FAA\u4F9D\u8D56\u5012\u7F6E\u539F\u5219\uFF09\n * - \u72EC\u7ACB CLI\uFF1A\u7531 `cli-pack-manager.ts` \u66B4\u9732\u547D\u4EE4\u884C\u5B50\u547D\u4EE4\u4F9B\u811A\u672C\u4E0E\u624B\u5DE5\u8C03\u8BD5\u4F7F\u7528\n *\n * \u6838\u5FC3\u80FD\u529B\uFF1A\n * - \u884C\u4E3A\u5305\u7EC4\u88C5\uFF1A\u5C06 esbuild \u6253\u5305\u540E\u7684 `scripts/main.js`\u3001\u5143\u6570\u636E manifest \u4E0E\u56FE\u6807\u5C01\u88C5\u4E3A BDS \u884C\u4E3A\u5305\u7ED3\u6784\n * - \u8D44\u6E90\u5305\u805A\u5408\uFF1A\u5C06\u5404\u6A21\u5757\u79C1\u6709\u7684 `resource_pack` \u76EE\u5F55\u65E0\u51B2\u7A81\u9012\u5F52\u5408\u5E76\u4E3A\u805A\u5408\u8D44\u6E90\u5305\n * - \u4E16\u754C\u90E8\u7F72\u4E0E\u6E05\u5355\u6FC0\u6D3B\uFF1A\u5C06\u5305\u90E8\u7F72\u81F3 BDS `<level>/behavior_packs` \u4E0E `resource_packs`\uFF0C\u5E76\u540C\u6B65\u7EF4\u62A4 `world_behavior_packs.json`\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { copyDirAsync, copyFileAsync, readJsonFile } from \"./fsx.js\";\nimport {\n BASELINE_BEDROCK_DEPENDENCIES,\n type PackManifestDependency,\n} from \"./dependency-negotiator.js\";\nexport * from \"./dependency-negotiator.js\";\n\n/* \u2500\u2500 \u7C7B\u578B\u5B9A\u4E49 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nexport interface AssembleBehaviorPackOpts {\n /** \u5DF2\u5B8C\u6210\u6253\u5305\u7684 `scripts/main.js` \u6240\u5728\u6E90\u7801\u76EE\u5F55\uFF08\u5373 esbuild \u8F93\u51FA\u76EE\u5F55\uFF09\u3002 */\n srcDir: string;\n /** \u884C\u4E3A\u5305\u76EE\u6807\u8F93\u51FA\u76EE\u5F55\uFF08\u82E5\u4E0D\u5B58\u5728\u5219\u81EA\u52A8\u521B\u5EFA\uFF09\u3002 */\n outDir: string;\n /** BP \u9879\u76EE/\u76EE\u5F55\u540D\uFF08\u9ED8\u8BA4\u4E3A `'sfmc-modules'`\uFF09\u3002 */\n projectName: string;\n /** `manifest.json` \u4E2D\u7684 `header.version` `[major, minor, patch]`\uFF08\u9ED8\u8BA4\u4E3A `[1, 0, 0]`\uFF09\u3002 */\n version?: [number, number, number] | undefined;\n /** `manifest.json` \u4E2D\u7684\u5305\u63CF\u8FF0\u4FE1\u606F\u3002 */\n description?: string | undefined;\n /** `pack_icon.png` \u56FE\u6807\u6E90\u6587\u4EF6\u8DEF\u5F84\uFF08\u53EF\u9009\uFF0C\u672A\u63D0\u4F9B\u5219\u8DF3\u8FC7\uFF09\u3002 */\n iconSrc?: string | undefined;\n /** \u7A33\u5B9A\u7684 `header.uuid`\uFF08\u7F3A\u7701\u65F6\u5C06\u5728\u9996\u6B21\u88C5\u914D\u65F6\u968F\u673A\u751F\u6210\uFF09\u3002 */\n uuid?: string | undefined;\n /** \u7A33\u5B9A\u7684 `script module uuid`\uFF08\u7F3A\u7701\u65F6\u968F\u673A\u751F\u6210\uFF09\u3002 */\n moduleUuid?: string | undefined;\n /** \u81EA\u5B9A\u4E49/\u52A8\u6001\u534F\u5546\u540E\u7684 dependencies\uFF08\u7F3A\u7701\u4F7F\u7528 BASELINE_BEDROCK_DEPENDENCIES\uFF09\u3002 */\n dependencies?: PackManifestDependency[] | undefined;\n}\n\nexport interface AssembleResourcePackOpts {\n /** \u9700\u5408\u5E76\u8D44\u6E90\u5305\u76EE\u5F55\u7684\u6A21\u5757\u6620\u5C04\u5B57\u5178\uFF08`Record<moduleId, resourcePackDir>`\uFF09\u3002 */\n moduleResourceDirs: Record<string, string>;\n /** \u8D44\u6E90\u5305\u76EE\u6807\u8F93\u51FA\u76EE\u5F55\uFF08\u82E5\u4E0D\u5B58\u5728\u5219\u81EA\u52A8\u521B\u5EFA\uFF09\u3002 */\n outDir: string;\n /** RP \u9879\u76EE/\u76EE\u5F55\u540D\u3002 */\n projectName: string;\n /** `manifest.json` \u4E2D\u7684 `header.version` `[major, minor, patch]`\uFF08\u9ED8\u8BA4\u4E3A `[1, 0, 0]`\uFF09\u3002 */\n version?: [number, number, number] | undefined;\n /** `manifest.json` \u4E2D\u7684\u5305\u63CF\u8FF0\u4FE1\u606F\u3002 */\n description?: string | undefined;\n /** \u7A33\u5B9A\u7684 `header.uuid`\uFF08\u7F3A\u7701\u65F6\u968F\u673A\u751F\u6210\uFF09\u3002 */\n uuid?: string | undefined;\n /** \u7A33\u5B9A\u7684 `resources module uuid`\uFF08\u7F3A\u7701\u65F6\u968F\u673A\u751F\u6210\uFF09\u3002 */\n moduleUuid?: string | undefined;\n}\n\n\nexport interface AssembleResult {\n uuid: string;\n version: [number, number, number];\n}\n\nexport interface DeployOpts {\n bdsRoot: string;\n levelName: string;\n /** \u5DF2\u7EC4\u88C5\u597D\u7684 BP \u6E90\u76EE\u5F55 */\n behaviorPackSrc: string;\n /** \u5DF2\u7EC4\u88C5\u597D\u7684 RP \u6E90\u76EE\u5F55 (\u53EF\u7701\u7565,\u53EA\u7528 BP \u4E5F\u5408\u6CD5) */\n resourcePackSrc?: string;\n /** BP \u76EE\u6807\u76EE\u5F55\u540D (worlds/<level>/behavior_packs/<bpName>) */\n bpName: string;\n /** RP \u76EE\u6807\u76EE\u5F55\u540D (worlds/<level>/resource_packs/<rpName>);\u7701\u7565\u65F6\u590D\u7528 bpName + '-rp' */\n rpName?: string;\n /**\n * \u65E0 resourcePackSrc \u65F6\u662F\u5426\u5220\u9664\u4E16\u754C\u5185\u5DF2\u6709 RP \u76EE\u5F55\u3002\n * \u7528\u4E8E\u6A21\u5757\u4E0D\u518D\u63D0\u4F9B RP \u65F6\u6E05\u7406\u805A\u5408\u5305\u6B8B\u7559(\u9ED8\u8BA4 false,\u907F\u514D\u8BEF\u5220\u672A\u58F0\u660E\u7684 RP)\u3002\n */\n clearResourcePack?: boolean;\n}\n\nexport interface DeployResult {\n bpDir: string;\n rpDir: string | null;\n}\n\nexport interface EnablePackOpts {\n worldsDir: string;\n levelName: string;\n kind: \"behavior\" | \"resource\";\n packUuid: string;\n version: [number, number, number];\n}\n\n/* \u2500\u2500 \u8DEF\u5F84\u5E38\u91CF \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/** SFMC \u5408\u6210 BP \u7684\u56FA\u5B9A @minecraft/* permissions,\u6240\u6709\u7528\u5230\u7684\u547D\u540D\u7A7A\u95F4\u90FD\u6253\u5F00\u3002 */\nexport const SFMC_PERMISSIONS = [\n \"@minecraft/server\",\n \"@minecraft/server-ui\",\n \"@minecraft/server-admin\",\n \"@minecraft/server-gametest\",\n \"@minecraft/server-net\",\n \"@minecraft/server-editor\",\n \"@minecraft/diagnostics\",\n] as const;\n\n/** `<bdsRoot>/server.properties` \u2014 level-name / telemetry \u7B49\u5171\u7528\uFF08DRY\uFF09 */\nexport function serverPropertiesPath(bdsRoot: string): string {\n return path.join(bdsRoot, \"server.properties\");\n}\n\n/** `<bdsRoot>/worlds` \u2014 enable-list / \u90E8\u7F72\u8C03\u7528\u65B9\u52FF\u518D\u786C\u62FC\uFF08Demeter\uFF09 */\nexport function bdsWorldsDir(bdsRoot: string): string {\n return path.join(bdsRoot, \"worlds\");\n}\n\n/** `<bdsRoot>/worlds/<level>` */\nexport function bdsWorldLevelDir(bdsRoot: string, levelName: string): string {\n return path.join(bdsWorldsDir(bdsRoot), levelName);\n}\n\n/** `<bdsRoot>/worlds/<level>/level.dat` \u2014 \u4E16\u754C\u5B58\u6863\u6743\u5A01\u8DEF\u5F84 */\nexport function levelDatPath(bdsRoot: string, levelName: string): string {\n return path.join(bdsWorldLevelDir(bdsRoot, levelName), \"level.dat\");\n}\n\n/** \u4E16\u754C enable-list JSON \u7EDD\u5BF9\u8DEF\u5F84\uFF08\u5355\u4E00\u6743\u5A01\uFF0C\u4F9B\u8BFB\u5199\u4E24\u4FA7\uFF09 */\nexport function worldPackListFile(\n worldsDir: string,\n levelName: string,\n kind: \"behavior\" | \"resource\"\n): string {\n const name = kind === \"behavior\" ? \"world_behavior_packs.json\" : \"world_resource_packs.json\";\n return path.join(worldsDir, levelName, name);\n}\n\n/** `<bdsRoot>/config/<bpUuid>/permission.json` \u2014 Script API \u6743\u9650\u6587\u4EF6\u6743\u5A01\u8DEF\u5F84 */\nexport function configPermissionPath(bdsRoot: string, bpUuid: string): string {\n return path.join(bdsRoot, \"config\", bpUuid, \"permission.json\");\n}\n\n/** `<bdsRoot>/config/<bpUuid>/permissions.json` \u2014 BDS \u5B98\u65B9\u89C4\u8303\u590D\u6570\u6743\u9650\u6587\u4EF6\u8DEF\u5F84 */\nexport function configPermissionsPath(bdsRoot: string, bpUuid: string): string {\n return path.join(bdsRoot, \"config\", bpUuid, \"permissions.json\");\n}\n\n/** \u662F\u5426\u5DF2\u6709 Script API permission.json \u6216 permissions.json\uFF08\u53EA\u8BFB\uFF0C\u4F9B preflight/status\uFF09 */\nexport function hasConfigPermission(bdsRoot: string, bpUuid: string): boolean {\n return fs.existsSync(configPermissionsPath(bdsRoot, bpUuid)) || fs.existsSync(configPermissionPath(bdsRoot, bpUuid));\n}\n\n/** \u968F\u673A\u751F\u6210 BP/RP manifest.json header.uuid (RFC 4122 v4) */\nexport function randomUuid(): string {\n /* crypto.randomUUID \u662F Node 19+ \u5185\u7F6E,\u8FD9\u91CC\u76F4\u63A5\u7528 */\n return crypto.randomUUID();\n}\n\n/* \u2500\u2500 \u9AA8\u67B6\u51FD\u6570 (Commit 5 \u5B9E\u73B0) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/**\n * Assemble a Bedrock behavior pack directory at `outDir` from a prebuilt\n * `srcDir` (which must already contain `scripts/main.js` plus whatever else\n * was bundled by esbuild) and write a fresh `manifest.json` + `permissions.json`.\n *\n * The caller is responsible for running esbuild first; pack-manager does not\n * bundle scripts. That decoupling keeps pack assembly independent of the bundler.\n */\nexport async function assembleBehaviorPack(opts: AssembleBehaviorPackOpts): Promise<AssembleResult> {\n const version = opts.version ?? [1, 0, 0];\n const bpUuid = opts.uuid ?? randomUuid();\n await fs.promises.rm(opts.outDir, { recursive: true, force: true });\n await fs.promises.mkdir(opts.outDir, { recursive: true });\n if (fs.existsSync(opts.srcDir)) {\n await copyDirAsync(opts.srcDir, opts.outDir);\n } else {\n await fs.promises.mkdir(path.join(opts.outDir, \"scripts\"), { recursive: true });\n await fs.promises.writeFile(path.join(opts.outDir, \"scripts\", \"main.js\"), \"/* no scripts */\\n\", \"utf8\");\n }\n await writeBehaviorPackManifest(\n opts.outDir,\n {\n name: opts.projectName,\n uuid: bpUuid,\n version,\n description: opts.description,\n moduleUuid: opts.moduleUuid,\n },\n opts.dependencies\n );\n if (opts.iconSrc && fs.existsSync(opts.iconSrc)) {\n await copyFileAsync(opts.iconSrc, path.join(opts.outDir, \"pack_icon.png\"));\n }\n await writePermissionsJson(opts.outDir);\n return { uuid: bpUuid, version };\n}\n\n/**\n * Merge every enabled module's `resource_pack/**` tree into one RP directory\n * at `outDir`, with a single fresh `manifest.json`. Per-module subfolders are\n * preserved so resource pack authors can disambiguate (e.g. `peace/textures/...`).\n */\nexport async function assembleResourcePack(opts: AssembleResourcePackOpts): Promise<AssembleResult> {\n const version = opts.version ?? [1, 0, 0];\n const rpUuid = opts.uuid ?? randomUuid();\n await fs.promises.rm(opts.outDir, { recursive: true, force: true });\n await fs.promises.mkdir(opts.outDir, { recursive: true });\n for (const [moduleId, rpDir] of Object.entries(opts.moduleResourceDirs)) {\n if (!fs.existsSync(rpDir)) continue;\n const dst = path.join(opts.outDir, moduleId);\n await fs.promises.mkdir(dst, { recursive: true });\n await copyDirAsync(rpDir, dst);\n }\n await writeResourcePackManifest(opts.outDir, {\n name: opts.projectName,\n uuid: rpUuid,\n version,\n description: opts.description,\n moduleUuid: opts.moduleUuid,\n });\n return { uuid: rpUuid, version };\n}\n\n/**\n * Read the `level-name=` value from `<bdsRoot>/server.properties`.\n * Falls back to \"Bedrock level\" (BDS default) when the file is missing or\n * the key is absent.\n */\nfunction parseLevelNameFromProperties(text: string): string {\n for (const line of text.split(/\\r?\\n/)) {\n const m = /^\\s*level-name\\s*=\\s*(.+?)\\s*$/.exec(line);\n if (m && m[1]) return m[1];\n }\n return \"Bedrock level\";\n}\n\n/** \u540C\u6B65\u8BFB level-name\uFF08\u4F9B sfmc resolveBdsContext \u7B49\u540C\u8FDB\u7A0B\u8C03\u7528\u65B9\uFF0CDRY\uFF09\u3002 */\nexport function readLevelNameSync(bdsRoot: string): string {\n const file = serverPropertiesPath(bdsRoot);\n if (!fs.existsSync(file)) return \"Bedrock level\";\n return parseLevelNameFromProperties(fs.readFileSync(file, \"utf8\"));\n}\n\n/** \u4E0E sync \u540C\u5951\u7EA6\uFF1BCLI / async \u8C03\u7528\u65B9\u8D70\u6B64\u5165\u53E3\uFF08LSP\uFF09 */\nexport async function readLevelName(bdsRoot: string): Promise<string> {\n return readLevelNameSync(bdsRoot);\n}\n\n/**\n * Copy BP/RP source dirs into the world's behavior_packs/ + resource_packs/\n * folders, and write a fresh `permissions.json` into the BP target.\n *\n * Does NOT edit world_behavior_packs.json \u2014 that's a separate step the caller\n * must invoke after restart, because BDS only reads that file at startup.\n */\nexport async function deployToBDS(opts: DeployOpts): Promise<DeployResult> {\n /* levelDir = worlds/<level>\uFF1B\u4E0E EnablePackOpts.worldsDir(=worlds/) \u8BED\u4E49\u4E0D\u540C \u2014 \u52FF\u6DF7\u7528\uFF08LSP\uFF09 */\n const levelDir = bdsWorldLevelDir(opts.bdsRoot, opts.levelName);\n const bpDst = path.join(levelDir, \"behavior_packs\", opts.bpName);\n const rpDst = path.join(levelDir, \"resource_packs\", opts.rpName ?? `${opts.bpName}-rp`);\n await fs.promises.mkdir(levelDir, { recursive: true });\n await fs.promises.rm(bpDst, { recursive: true, force: true });\n await copyDirAsync(opts.behaviorPackSrc, bpDst);\n await writePermissionsJson(bpDst);\n let rpDir: string | null = null;\n if (opts.resourcePackSrc && fs.existsSync(opts.resourcePackSrc)) {\n await fs.promises.rm(rpDst, { recursive: true, force: true });\n await copyDirAsync(opts.resourcePackSrc, rpDst);\n rpDir = rpDst;\n } else if (opts.clearResourcePack) {\n /* \u8C03\u7528\u65B9\u663E\u5F0F\u58F0\u660E\u4E0D\u518D\u90E8\u7F72 RP \u2014 \u6E05\u6389\u805A\u5408 RP \u76EE\u5F55\u6B8B\u7559 */\n await fs.promises.rm(rpDst, { recursive: true, force: true });\n }\n return { bpDir: bpDst, rpDir };\n}\n\n/**\n * \u786E\u4FDD BDS Script API \u4FA7\u6743\u9650\u6587\u4EF6\u5B58\u5728\u5E76\u5305\u542B\u5B8C\u6574\u7684 SFMC \u6240\u9700\u6A21\u5757\u6743\u9650\u3002\n * - \u81EA\u52A8\u589E\u91CF\u5408\u5E76\u73B0\u6709 allowed_modules\uFF0C\u81EA\u52A8\u8865\u9F50\u65B0\u589E\u6743\u9650\uFF08\u5982 @minecraft/diagnostics\uFF09\n * - \u540C\u65F6\u7EF4\u62A4 BDS \u5B98\u65B9\u89C4\u8303\u7684 permissions.json \u4E0E\u5386\u53F2\u517C\u5BB9\u7684 permission.json\n * - \u540C\u65F6\u66F4\u65B0 moduleUuid\uFF08\u82E5\u63D0\u4F9B\uFF09\u4E0E config/default/permissions.json \u515C\u5E95\u6743\u9650\n * @returns true = \u6709\u65B0\u589E/\u66F4\u65B0; false = \u5DF2\u662F\u6700\u65B0\u65E0\u9700\u4FEE\u6539\n */\nexport async function ensureConfigPermission(\n bdsRoot: string,\n bpUuid: string,\n moduleUuid?: string\n): Promise<boolean> {\n let changed = false;\n\n const updateFile = async (filePath: string): Promise<boolean> => {\n let currentModules: string[] = [];\n let restConfig: Record<string, unknown> = {};\n if (fs.existsSync(filePath)) {\n try {\n const raw = readJsonFile<{ allowed_modules?: string[]; [k: string]: unknown }>(filePath);\n if (Array.isArray(raw.allowed_modules)) {\n currentModules = raw.allowed_modules;\n }\n const { allowed_modules: _, ...rest } = raw;\n restConfig = rest;\n } catch {\n // \u6587\u4EF6\u635F\u574F\u5219\u6309\u5168\u65B0\u5199\u5165\n }\n }\n const merged = Array.from(new Set([...currentModules, ...SFMC_PERMISSIONS]));\n if (merged.length === currentModules.length && fs.existsSync(filePath)) {\n return false;\n }\n const dir = path.dirname(filePath);\n await fs.promises.mkdir(dir, { recursive: true });\n const payload = { allowed_modules: merged, ...restConfig };\n const tmp = path.join(dir, `.permission.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`);\n await fs.promises.writeFile(tmp, JSON.stringify(payload, null, 2) + \"\\n\", \"utf8\");\n await fs.promises.rename(tmp, filePath);\n return true;\n };\n\n const uuids = Array.from(new Set([bpUuid, ...(moduleUuid ? [moduleUuid] : [])]));\n for (const u of uuids) {\n if (await updateFile(configPermissionsPath(bdsRoot, u))) changed = true;\n if (await updateFile(configPermissionPath(bdsRoot, u))) changed = true;\n }\n\n const defaultFile = path.join(bdsRoot, \"config\", \"default\", \"permissions.json\");\n if (await updateFile(defaultFile)) changed = true;\n\n return changed;\n}\n\n/** \u4ECE\u5DF2\u88C5\u914D BP/RP \u76EE\u5F55\u8BFB\u53D6 header.uuid + version;\u5931\u8D25\u8FD4\u56DE null\u3002 */\nexport function readPackManifestHeader(\n packDir: string\n): { uuid: string; version: [number, number, number]; moduleUuid?: string } | null {\n const file = path.join(packDir, \"manifest.json\");\n if (!fs.existsSync(file)) return null;\n try {\n const raw = readJsonFile<{\n header?: { uuid?: string; version?: number[] };\n modules?: Array<{ uuid?: string }>;\n }>(file);\n const uuid = raw.header?.uuid;\n const ver = raw.header?.version;\n if (typeof uuid !== \"string\" || !Array.isArray(ver) || ver.length < 3) return null;\n const version: [number, number, number] = [Number(ver[0]), Number(ver[1]), Number(ver[2])];\n const moduleUuid = raw.modules?.[0]?.uuid;\n return { uuid, version, ...(typeof moduleUuid === \"string\" ? { moduleUuid } : {}) };\n } catch {\n return null;\n }\n}\n\n\n/** \u4ECE\u5DF2\u88C5\u914D BP/RP \u76EE\u5F55\u8BFB\u53D6 dependencies \u5217\u8868\uFF1B\u82E5\u65E0\u6216\u5931\u8D25\u8FD4\u56DE []\u3002 */\nexport function readPackManifestDependencies(packDir: string): PackManifestDependency[] {\n const file = path.join(packDir, \"manifest.json\");\n if (!fs.existsSync(file)) return [];\n try {\n const raw = readJsonFile<{ dependencies?: PackManifestDependency[] }>(file);\n return Array.isArray(raw.dependencies) ? raw.dependencies : [];\n } catch {\n return [];\n }\n}\n\n/**\n * Write `@minecraft/*` allowed_modules into a behavior pack's\n * `permissions.json`. Idempotent: rewrites any pre-existing file.\n */\nexport async function writePermissionsJson(bpDir: string): Promise<void> {\n const payload = { allowed_modules: [...SFMC_PERMISSIONS] };\n await fs.promises.mkdir(bpDir, { recursive: true });\n const tmp = path.join(bpDir, `.permissions.${process.pid}.tmp`);\n await fs.promises.writeFile(tmp, JSON.stringify(payload, null, 2) + \"\\n\", \"utf8\");\n await fs.promises.rename(tmp, path.join(bpDir, \"permissions.json\"));\n}\n\n/**\n * Add `{ pack_id, version }` to `worlds/<level>/world_behavior_packs.json`\n * (or `world_resource_packs.json`). If the pack_id already exists, replace its\n * version. File missing \u2192 initialize as `[]`.\n */\nexport async function enablePackInWorld(opts: EnablePackOpts): Promise<void> {\n await editWorldPackList(opts, \"enable\");\n}\n\n/** Remove a pack_id from the world's enable-list JSON. */\nexport async function disablePackInWorld(opts: EnablePackOpts): Promise<void> {\n await editWorldPackList(opts, \"disable\");\n}\n\ninterface WorldPackEntry {\n pack_id: string;\n version: [number, number, number];\n}\n\nasync function editWorldPackList(\n opts: EnablePackOpts,\n mode: \"enable\" | \"disable\"\n): Promise<void> {\n const file = worldPackListFile(opts.worldsDir, opts.levelName, opts.kind);\n /* \u4E0E readWorldPackList \u540C\u6E90\u89E3\u6790,\u518D\u5199\u56DE(DRY);\u5F02\u6B65\u5199\u8DEF\u5F84\u4FDD\u7559\u539F\u8BED\u4E49 */\n let entries: WorldPackEntry[] = readWorldPackList(opts.worldsDir, opts.levelName, opts.kind);\n const idx = entries.findIndex((e) => e.pack_id === opts.packUuid);\n if (mode === \"enable\") {\n const next: WorldPackEntry = { pack_id: opts.packUuid, version: opts.version };\n if (idx >= 0) entries[idx] = next;\n else entries.push(next);\n } else {\n if (idx >= 0) entries.splice(idx, 1);\n }\n await fs.promises.mkdir(path.dirname(file), { recursive: true });\n const tmp = `${file}.${process.pid}.tmp`;\n await fs.promises.writeFile(tmp, JSON.stringify(entries, null, 2) + \"\\n\", \"utf8\");\n await fs.promises.rename(tmp, file);\n}\n\n/* \u2500\u2500 \u4F4E\u5C42 helpers (Commit 5 \u5B9E\u73B0) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nexport async function writeBehaviorPackManifest(\n outDir: string,\n header: {\n name: string;\n uuid: string;\n version: [number, number, number];\n description?: string | undefined;\n moduleUuid?: string | undefined;\n },\n dependencies?: PackManifestDependency[] | undefined\n): Promise<void> {\n const manifest = {\n format_version: 2,\n header: {\n name: header.name,\n uuid: header.uuid,\n version: header.version,\n description: header.description ? `${header.description} (behavior pack)` : \"SFMC behavior pack\",\n min_engine_version: [1, 21, 0],\n },\n modules: [\n {\n type: \"script\",\n language: \"javascript\",\n entry: \"scripts/main.js\",\n uuid: header.moduleUuid ?? crypto.randomUUID(),\n version: header.version,\n },\n ],\n dependencies:\n dependencies && dependencies.length > 0 ? dependencies : BASELINE_BEDROCK_DEPENDENCIES,\n };\n const file = path.join(outDir, \"manifest.json\");\n await fs.promises.mkdir(outDir, { recursive: true });\n await fs.promises.writeFile(file, JSON.stringify(manifest, null, 2) + \"\\n\", \"utf8\");\n}\n\nexport async function writeResourcePackManifest(\n outDir: string,\n header: {\n name: string;\n uuid: string;\n version: [number, number, number];\n description?: string | undefined;\n moduleUuid?: string | undefined;\n }\n): Promise<void> {\n const manifest = {\n format_version: 2,\n header: {\n name: header.name,\n uuid: header.uuid,\n version: header.version,\n description: header.description ? `${header.description} (resource pack)` : \"SFMC resource pack\",\n min_engine_version: [1, 21, 0],\n },\n modules: [\n {\n type: \"resources\",\n uuid: header.moduleUuid ?? crypto.randomUUID(),\n version: header.version,\n },\n ],\n };\n const file = path.join(outDir, \"manifest.json\");\n await fs.promises.mkdir(outDir, { recursive: true });\n await fs.promises.writeFile(file, JSON.stringify(manifest, null, 2) + \"\\n\", \"utf8\");\n}\n\n/* Re-export copyFileAsync so callers can copy icon without\n * pulling in the full fsx surface area. */\nexport { copyFileAsync, copyDirAsync };\n\n/* \u2500\u2500 Discovery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/**\n * Walk `<modulesDir>/<id>/resource_pack/` for every installed module and\n * return a map { id: absoluteDir }. Modules without a resource_pack folder\n * are silently skipped. Used by `assemble-rp` and the sfmc CLI to know which\n * modules to merge into the resource pack output.\n */\nexport function scanModuleResourcePacks(modulesDir: string): Record<string, string> {\n const out: Record<string, string> = {};\n if (!fs.existsSync(modulesDir)) return out;\n for (const entry of fs.readdirSync(modulesDir, { withFileTypes: true })) {\n if (entry.name.startsWith(\".\")) continue;\n // \u8DDF\u968F symlink\uFF08--link \u5B89\u88C5\uFF09\uFF1BDirent.isDirectory() \u5BF9\u94FE\u63A5\u76EE\u5F55\u4E3A false\n try {\n if (!fs.statSync(path.join(modulesDir, entry.name)).isDirectory()) continue;\n } catch {\n continue;\n }\n const rpDir = path.join(modulesDir, entry.name, \"resource_pack\");\n if (fs.existsSync(rpDir)) {\n out[entry.name] = rpDir;\n }\n }\n return out;\n}\n\n/**\n * \u4ECE JSON \u6587\u4EF6\u52A0\u8F7D\u663E\u5F0F moduleId \u2192 resource_pack \u76EE\u5F55\u6620\u5C04\u3002\n * \u4F9B assemble-rp --modules-json \u4F7F\u7528,\u907F\u514D\u8C03\u7528\u65B9\u518D\u505A\u4E34\u65F6\u76EE\u5F55\u955C\u50CF(OCP/DRY)\u3002\n */\nexport function loadModuleResourcePackMap(jsonPath: string): Record<string, string> {\n const raw = JSON.parse(fs.readFileSync(jsonPath, \"utf8\")) as unknown;\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new Error(`modules-json must be an object: ${jsonPath}`);\n }\n const out: Record<string, string> = {};\n for (const [id, dir] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof id !== \"string\" || !id || typeof dir !== \"string\" || !dir) continue;\n const abs = path.resolve(dir);\n if (!fs.existsSync(abs)) {\n throw new Error(`modules-json entry missing: ${id} \u2192 ${abs}`);\n }\n out[id] = abs;\n }\n return out;\n}\n\n/**\n * \u8BFB\u53D6\u4E16\u754C enable-list(\u5355\u4E00\u6743\u5A01,\u4F9B has-pack / list-packs / \u8C03\u7528\u65B9\u590D\u7528 \u2014 DRY)\u3002\n * \u6587\u4EF6\u7F3A\u5931 \u2192 entries=[]\uFF1BJSON \u635F\u574F \u2192 entries=[] \u4E14 parseFailedFile \u6709\u503C\uFF08\u4F9B doctor \u533A\u5206\uFF09\u3002\n */\nexport type WorldPackListReadResult = {\n entries: Array<{ pack_id: string; version: [number, number, number] }>;\n /** \u6587\u4EF6\u5B58\u5728\u4F46\u89E3\u6790\u5931\u8D25\u65F6\u4E3A\u8BE5 JSON \u7EDD\u5BF9\u8DEF\u5F84 */\n parseFailedFile?: string;\n};\n\nexport function readWorldPackListResult(\n worldsDir: string,\n levelName: string,\n kind: \"behavior\" | \"resource\"\n): WorldPackListReadResult {\n const file = worldPackListFile(worldsDir, levelName, kind);\n if (!fs.existsSync(file)) return { entries: [] };\n try {\n const arr = JSON.parse(fs.readFileSync(file, \"utf8\")) as unknown;\n if (!Array.isArray(arr)) return { entries: [], parseFailedFile: file };\n const out: Array<{ pack_id: string; version: [number, number, number] }> = [];\n for (const e of arr) {\n if (!e || typeof e !== \"object\") continue;\n const packId = (e as { pack_id?: unknown }).pack_id;\n const ver = (e as { version?: unknown }).version;\n if (typeof packId !== \"string\" || !packId) continue;\n const version: [number, number, number] =\n Array.isArray(ver) && ver.length >= 3\n ? [Number(ver[0]), Number(ver[1]), Number(ver[2])]\n : [1, 0, 0];\n out.push({ pack_id: packId, version });\n }\n return { entries: out };\n } catch {\n return { entries: [], parseFailedFile: file };\n }\n}\n\n/** \u517C\u5BB9\u8BFB\u4FA7\uFF1A\u53EA\u8981 entries\uFF08\u635F\u574F\u65F6\u4E0E\u7F3A\u5931\u540C\u4E3A []\uFF09\u3002\u8BE6\u7EC6\u7ED3\u679C\u89C1 readWorldPackListResult\u3002 */\nexport function readWorldPackList(\n worldsDir: string,\n levelName: string,\n kind: \"behavior\" | \"resource\"\n): Array<{ pack_id: string; version: [number, number, number] }> {\n return readWorldPackListResult(worldsDir, levelName, kind).entries;\n}\n\n/** \u4E16\u754C enable-list \u662F\u5426\u5DF2\u542B\u6307\u5B9A pack_id(\u53EA\u8BFB,\u4F9B preflight \u590D\u7528)\u3002 */\nexport function worldPackListHas(\n worldsDir: string,\n levelName: string,\n kind: \"behavior\" | \"resource\",\n packUuid: string\n): boolean {\n return readWorldPackList(worldsDir, levelName, kind).some((e) => e.pack_id === packUuid);\n}"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }