mbler 0.2.4 → 0.2.7-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -41
- package/bin/mbler.js +3 -3
- package/bin/mcx-tsc.js +1 -1
- package/client.d.ts +17 -0
- package/dist/build.d.ts +18 -5
- package/dist/build.esm.mjs +834 -447
- package/dist/build.esm.mjs.map +1 -1
- package/dist/build.js +833 -447
- package/dist/build.js.map +1 -1
- package/dist/index.d.ts +22 -63
- package/dist/index.esm.mjs +665 -851
- package/dist/index.esm.mjs.map +1 -1
- package/dist/index.js +655 -839
- package/dist/index.js.map +1 -1
- package/dist/template/mcx/behavior/scripts/app.mcx +8 -5
- package/dist/template/mcx/behavior/scripts/component/ComponentTest.mcx +19 -0
- package/dist/template/mcx/behavior/scripts/config/config.json +5 -0
- package/dist/template/mcx/behavior/scripts/{event$1.mcx → event/event$1.mcx} +2 -3
- package/dist/template/mcx/behavior/scripts/event/event.mcx +10 -0
- package/dist/template/mcx/behavior/scripts/event/test.ts +3 -0
- package/dist/template/mcx/behavior/scripts/index.ts +5 -0
- package/dist/template/ts/behavior/scripts/index.ts +1 -1
- package/package.json +31 -20
- package/dist/template/mcx/behavior/pack_icon.png +0 -0
- package/dist/template/mcx/behavior/scripts/event.mcx +0 -9
- package/dist/template/mcx/behavior/scripts/index.mjs +0 -5
package/dist/build.js
CHANGED
|
@@ -2,25 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
var mcxDef = require('@mbler/mcx-core');
|
|
4
4
|
var _chalk = require('chalk');
|
|
5
|
-
var jsonPlugin = require('@rollup/plugin-json');
|
|
6
|
-
var resolvePlugin = require('@rollup/plugin-node-resolve');
|
|
7
5
|
var minifyPlugin = require('@rollup/plugin-terser');
|
|
8
6
|
var chokidar = require('chokidar');
|
|
9
|
-
var fs = require('node:fs/promises');
|
|
7
|
+
var fs$1 = require('node:fs/promises');
|
|
10
8
|
var path = require('node:path');
|
|
11
|
-
var
|
|
9
|
+
var rolldown = require('rolldown');
|
|
12
10
|
var readline = require('readline');
|
|
11
|
+
var fs = require('node:fs');
|
|
13
12
|
var os = require('node:os');
|
|
14
|
-
var npmRegistryFetch = require('npm-registry-fetch');
|
|
15
13
|
require('node:child_process');
|
|
16
|
-
var node_v8 = require('node:v8');
|
|
17
14
|
var crypto = require('node:crypto');
|
|
18
|
-
var fs$1 = require('node:fs');
|
|
19
15
|
var node_process = require('node:process');
|
|
20
|
-
var AdmZip = require('adm-zip');
|
|
21
|
-
var commonjs = require('@rollup/plugin-commonjs');
|
|
22
16
|
var mcxServer = require('@mbler/mcx-server');
|
|
23
|
-
var typescript = require('@rollup/plugin-typescript');
|
|
24
17
|
var ts = require('typescript');
|
|
25
18
|
var runTsc_js = require('@volar/typescript/lib/quickstart/runTsc.js');
|
|
26
19
|
|
|
@@ -42,48 +35,395 @@ function _interopNamespaceDefault(e) {
|
|
|
42
35
|
}
|
|
43
36
|
|
|
44
37
|
var mcxDef__namespace = /*#__PURE__*/_interopNamespaceDefault(mcxDef);
|
|
45
|
-
var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
|
|
38
|
+
var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs$1);
|
|
46
39
|
var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
47
|
-
var rollup__namespace = /*#__PURE__*/_interopNamespaceDefault(rollup);
|
|
48
40
|
var readline__namespace = /*#__PURE__*/_interopNamespaceDefault(readline);
|
|
49
|
-
var fs__namespace$1 = /*#__PURE__*/_interopNamespaceDefault(fs
|
|
41
|
+
var fs__namespace$1 = /*#__PURE__*/_interopNamespaceDefault(fs);
|
|
42
|
+
|
|
43
|
+
const LanguageNames = ['zh', 'en'];
|
|
44
|
+
const cmdList = [
|
|
45
|
+
'c',
|
|
46
|
+
'work',
|
|
47
|
+
'help',
|
|
48
|
+
'h',
|
|
49
|
+
'init',
|
|
50
|
+
'version',
|
|
51
|
+
'build',
|
|
52
|
+
'watch',
|
|
53
|
+
'lang',
|
|
54
|
+
'set-work-dir',
|
|
55
|
+
'publish',
|
|
56
|
+
'unpublish',
|
|
57
|
+
'install',
|
|
58
|
+
'uninstall',
|
|
59
|
+
'login',
|
|
60
|
+
'profile',
|
|
61
|
+
'log',
|
|
62
|
+
'view',
|
|
63
|
+
'config',
|
|
64
|
+
];
|
|
65
|
+
const templateMblerConfig = {
|
|
66
|
+
name: 'demo',
|
|
67
|
+
description: 'demo',
|
|
68
|
+
version: '0.0.0',
|
|
69
|
+
mcVersion: '1.21.100',
|
|
70
|
+
script: {
|
|
71
|
+
main: '',
|
|
72
|
+
},
|
|
73
|
+
minify: false,
|
|
74
|
+
outdir: {
|
|
75
|
+
behavior: '',
|
|
76
|
+
resources: '',
|
|
77
|
+
dist: '',
|
|
78
|
+
},
|
|
79
|
+
build: {
|
|
80
|
+
rollupPlugins: [],
|
|
81
|
+
cache: 'auto',
|
|
82
|
+
bundle: true,
|
|
83
|
+
outputDir: 'scripts',
|
|
84
|
+
outputFilename: '',
|
|
85
|
+
onEnd: () => { },
|
|
86
|
+
onStart: () => { },
|
|
87
|
+
onWarn: () => { },
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
var version = { version: "0.2.7-rc.1" };
|
|
92
|
+
|
|
93
|
+
var ZhLang = {
|
|
94
|
+
description: `MBLER
|
|
95
|
+
Minecraft Bedrock Edition
|
|
96
|
+
Addon Bulider In Nodejs
|
|
97
|
+
在基岩版我的世界上的 nodejs 构建工具
|
|
98
|
+
命令 : ${cmdList.join(', ')}
|
|
99
|
+
帮助命令 :
|
|
100
|
+
help
|
|
101
|
+
显示帮助信息
|
|
102
|
+
第二个参数为要查询的命令名称或空
|
|
103
|
+
别名: h
|
|
104
|
+
git https://github.com/RuanhoR/mbler/`,
|
|
105
|
+
help: {
|
|
106
|
+
cmds: cmdList,
|
|
107
|
+
help: 'mbler [help/h] [?:查看的命令名称]\n - 查看帮助',
|
|
108
|
+
h: '$help',
|
|
109
|
+
work: 'mbler [work/c] [?:相对或绝对路径]\n - 没有输入路径:查询当前工作目录\n - 输入路径:设置工作目录',
|
|
110
|
+
c: '$work',
|
|
111
|
+
init: 'mbler init\n - 初始化当前工作目录,可使用 mbler work 指定工作目录或使用参数一次确定(例: mbler init -in ./)\n - 将会询问选项以完成初始化',
|
|
112
|
+
build: 'mbler build\n - 在工作目录执行构建',
|
|
113
|
+
log: 'mbler log\n - 处理日志文件\n - mbler log point: 得到日志文件路径 \n - mbler log clean: 清除日志',
|
|
114
|
+
watch: 'mbler watch\n - 启动构建并开启监视模式,文件变化会自动重新构建',
|
|
115
|
+
lang: 'mbler lang\n- 无参数:显示当前语言\n- 跟 zh 或 en(如 mbler lang en): 设置语言',
|
|
116
|
+
version: 'mbler version - 版本管理命令\n- 无参数:显示当前版本和提交哈希\n- --show=<commit|version>:筛选显示内容\n- <新版本号>:更新package.json和配置文件的版本',
|
|
117
|
+
'set-work-dir': 'mbler set-work-dir <on|off>\n - on: 启用工作目录功能\n - off: 禁用工作目录功能,直接使用 process.cwd()',
|
|
118
|
+
publish: 'mbler publish\n - 将你的附加包发布到 pmnx\n- 参数:\n- -tag: 版本标签名称\n- -build <skip|always>: 是否跳过构建(默认 always)',
|
|
119
|
+
uninstall: 'mbler uninstall @<scope>/<name>@version\n从你的游戏中移除一个包',
|
|
120
|
+
install: 'mbler install @<scope>/<name>@version\n将一个包安装到你的游戏中',
|
|
121
|
+
unpublish: 'mbler unpublish @<scope>/<name>@version\n从 pmnx 取消发布一个包',
|
|
122
|
+
login: 'mbler login <?:token>\n使用 token 登录你的 pmnx 账户\n- 如果没有 token,会向你请求',
|
|
123
|
+
profile: 'mbler profile\n显示当前登录账户信息',
|
|
124
|
+
view: 'mbler view @<scope>/<name>\n查看包的版本列表',
|
|
125
|
+
config: 'mbler config get <key>\nmbler config set <key> <value>\nmbler config point <path>\nmbler config point get',
|
|
126
|
+
},
|
|
127
|
+
init: {
|
|
128
|
+
useUI: '使用UI模块? (y/n): ',
|
|
129
|
+
useGIT: '初始化GIT仓库? (y/n): ',
|
|
130
|
+
name: '项目名称: ',
|
|
131
|
+
welcome: '欢迎使用Mbler初始化向导 语言:中文 mbler 版本: ' + version.version,
|
|
132
|
+
description: '项目描述: ',
|
|
133
|
+
initDes: '初始化依赖? (y/n): ',
|
|
134
|
+
lang: '选择项目语言: ',
|
|
135
|
+
betaApi: '使用Beta Api? (y/n): ',
|
|
136
|
+
mcVersion: '项目使用的mc版本(x.x.x): ',
|
|
137
|
+
noLanguare: '没有输入项目语言,这是必要的',
|
|
138
|
+
noName: '没有项目名称,这是必要的',
|
|
139
|
+
noMCVersion: "输入的 '支持的mc版本' 格式不对",
|
|
140
|
+
},
|
|
141
|
+
default: {
|
|
142
|
+
unexpected: '不正确的命令,',
|
|
143
|
+
youis: '你是否想说: ',
|
|
144
|
+
},
|
|
145
|
+
workdir: {
|
|
146
|
+
set: '[工作目录] 设置为: ',
|
|
147
|
+
nfound: '找不到输入文件夹(无法创建或不是文件夹)',
|
|
148
|
+
disabled: '工作目录功能已禁用,将使用当前目录',
|
|
149
|
+
enabled: '工作目录功能已启用',
|
|
150
|
+
invalidParam: '参数错误,请使用 on 或 off',
|
|
151
|
+
},
|
|
152
|
+
publish: {
|
|
153
|
+
askTip: '输入MCBE游戏绝对目录 (如 /sdcard/Android/data/com.mojang.minecraftpe/files/games),以进行下一步: ',
|
|
154
|
+
notLoggedIn: '未登录,请先执行 `mbler login <token>`',
|
|
155
|
+
progress: '进度: {progress}%',
|
|
156
|
+
publishFailed: '发布失败: {error}',
|
|
157
|
+
publishing: '正在发布...',
|
|
158
|
+
building: '正在构建项目...',
|
|
159
|
+
publishToMarket: '正在上传到市场...',
|
|
160
|
+
publishSuccess: '发布成功',
|
|
161
|
+
publishResult: '+ {name}@{version} ({tag})',
|
|
162
|
+
projectPathNotExist: '项目路径不存在',
|
|
163
|
+
outdirNotFound: '未找到构建输出目录配置',
|
|
164
|
+
outdirNotExist: '构建输出目录不存在',
|
|
165
|
+
readmeNotFound: '未找到 README 文件',
|
|
166
|
+
metadataInvalid: '元数据无效',
|
|
167
|
+
packageNameInvalid: '包名格式必须是 @scope/name',
|
|
168
|
+
notLoginError: '未登录',
|
|
169
|
+
tokenMissing: '获取 token 失败',
|
|
170
|
+
unpublishReqFailed: '取消发布请求失败',
|
|
171
|
+
createSessionFailed: '创建发布会话失败',
|
|
172
|
+
uploadZipFailed: '上传 zip 文件失败',
|
|
173
|
+
packageJsonNotFound: '未找到 package.json',
|
|
174
|
+
noBuildScript: 'package.json 中未找到 build 脚本',
|
|
175
|
+
buildFailed: '构建失败,退出码: {code}',
|
|
176
|
+
},
|
|
177
|
+
install: {
|
|
178
|
+
failedNoPackageJson: '安装失败:工作目录必须包含 package.json',
|
|
179
|
+
failedNoBuildScript: '安装失败:package.json 必须包含 build 脚本',
|
|
180
|
+
installing: '正在安装包 {pkg}...',
|
|
181
|
+
packageNotFound: '未找到包 {pkg}',
|
|
182
|
+
noVersion: '包 {pkg} 没有可用版本',
|
|
183
|
+
usingLatest: '使用最新版本 {version}',
|
|
184
|
+
noValidAddon: '包内未找到有效 addon',
|
|
185
|
+
success: '包 {pkg}@{version} 已安装为 {id}',
|
|
186
|
+
failed: '安装失败: {error}',
|
|
187
|
+
},
|
|
188
|
+
uninstall: {
|
|
189
|
+
success: '包 {pkg}@{version} 卸载成功',
|
|
190
|
+
failed: '卸载失败: {error}',
|
|
191
|
+
},
|
|
192
|
+
unpublish: {
|
|
193
|
+
success: '包 {pkg}@{version} 取消发布成功',
|
|
194
|
+
failed: '取消发布失败: {error}',
|
|
195
|
+
},
|
|
196
|
+
view: {
|
|
197
|
+
usage: 'mbler view @<scope>/<name>',
|
|
198
|
+
packageNotFound: '未找到包 {pkg}',
|
|
199
|
+
title: '包 {pkg} 版本列表:',
|
|
200
|
+
versionLine: '- {version} [{tag}] by {user} at {time}',
|
|
201
|
+
failed: '查看失败: {error}',
|
|
202
|
+
},
|
|
203
|
+
config: {
|
|
204
|
+
usage: 'mbler config get <key> | set <key> <value> | point <path> | point get',
|
|
205
|
+
missingArg: '参数不足',
|
|
206
|
+
getResult: '{key} = {value}',
|
|
207
|
+
setSuccess: '已设置 {key} = {value}',
|
|
208
|
+
pointGet: '当前配置文件: {path}',
|
|
209
|
+
pointSetSuccess: '配置文件指向已设置为: {path}',
|
|
210
|
+
pointSetFailed: '配置文件指向设置失败: {error}',
|
|
211
|
+
failed: '配置操作失败: {error}',
|
|
212
|
+
},
|
|
213
|
+
commander: {
|
|
214
|
+
selectTip: '(按 b 确认,n 键选择下一个)',
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
var enLang = {
|
|
219
|
+
description: 'MBLER\nMinecraft Bedrock Edition\nAddon Bulider In Nodejs\nnodejs build tools on bedrock version of minecraft\nCommands: ' +
|
|
220
|
+
cmdList.join(', ') +
|
|
221
|
+
'\nHelp command:\n help\n Show help information\n The second parameter is the name of the command to be queried or empty\n Alias: -h, -help\n git https://github.com/RuanhoR/mbler/',
|
|
222
|
+
help: {
|
|
223
|
+
cmds: cmdList,
|
|
224
|
+
help: 'mbler [help/h] [?: command name]\n - see tip',
|
|
225
|
+
h: '$help',
|
|
226
|
+
work: 'mbler [work/c] [?: path]\n - No input path: see current work dir\n - input path: set as current dir',
|
|
227
|
+
c: '$work',
|
|
228
|
+
init: 'mbler init\n - Init current work dir, you can use `mbler work` command or use command param(like be: mbler init -in ./)',
|
|
229
|
+
build: 'mbler build\n - perform a build using the library API',
|
|
230
|
+
b: '$build',
|
|
231
|
+
log: 'mbler log\n - Handler log file\n - mbler log point: Get log file path \n - mbler log clean: Remove Log',
|
|
232
|
+
watch: 'mbler watch\n - run build and enter watch mode; changes will trigger rebuilds',
|
|
233
|
+
lang: 'mbler lang [?:language]\n- No args: show current language\n- language = "zh” | “en": set language',
|
|
234
|
+
version: 'mbler version\n - Version control command\n- No args: Shows version + commit hash\n- --show=<commit|version>: Filters output\n- <new_version>: Updates version in both package.json and config file',
|
|
235
|
+
'set-work-dir': 'mbler set-work-dir <on|off>\n - on: Enable work dir feature\n - off: Disable work dir feature, use process.cwd() directly',
|
|
236
|
+
publish: 'mbler publish\n - Publish your package to pmnx\n- Params:\n- -tag: version tag name\n- -build <skip|always>: skip or run build before publish (default: always)',
|
|
237
|
+
uninstall: 'mbler uninstall @<scope>/<name>@version\nRemove a package from your game',
|
|
238
|
+
install: 'mbler install @<scope>/<name>@version\nInstall a package to your game',
|
|
239
|
+
unpublish: 'mbler unpublish @<scope>/<name>@version\nUnpublish a package from pmnx',
|
|
240
|
+
login: 'mbler login <?:token>\nUse token login your pmnx account',
|
|
241
|
+
profile: 'mbler profile\nShow current logged-in account profile',
|
|
242
|
+
view: 'mbler view @<scope>/<name>\nShow package versions',
|
|
243
|
+
config: 'mbler config get <key>\nmbler config set <key> <value>\nmbler config point <path>\nmbler config point get',
|
|
244
|
+
},
|
|
245
|
+
init: {
|
|
246
|
+
useUI: 'Use UI? (y/n): ',
|
|
247
|
+
useGIT: 'Initialize GIT repository? (y/n): ',
|
|
248
|
+
name: 'Project name: ',
|
|
249
|
+
description: 'Project description: ',
|
|
250
|
+
initDes: 'Initialize dependencies? (y/n): ',
|
|
251
|
+
welcome: 'Welcome to use Mbler init wizard! Language: English mbler version: ' +
|
|
252
|
+
version.version,
|
|
253
|
+
lang: 'Project language: ',
|
|
254
|
+
betaApi: 'use beta api(y/n): ',
|
|
255
|
+
mcVersion: 'Minecraft version(be like: x.x.x): ',
|
|
256
|
+
noLanguare: 'project language is required',
|
|
257
|
+
noMCVersion: 'project mcVersion format is not right',
|
|
258
|
+
noName: 'project name is required',
|
|
259
|
+
},
|
|
260
|
+
default: {
|
|
261
|
+
unexpected: 'Not found this command,',
|
|
262
|
+
youis: 'You want to input: ',
|
|
263
|
+
},
|
|
264
|
+
workdir: {
|
|
265
|
+
set: '[path to]: ',
|
|
266
|
+
nfound: "not found this dir(can't create or not directory)",
|
|
267
|
+
disabled: 'Work dir disabled, will use current directory',
|
|
268
|
+
enabled: 'Work dir enabled',
|
|
269
|
+
invalidParam: 'Invalid parameter, use on or off',
|
|
270
|
+
},
|
|
271
|
+
publish: {
|
|
272
|
+
askTip: 'Plase input the absolute path of your MCBE game directory (like /sdcard/Android/data/com.mojang.minecraftpe/files/games) for next step: ',
|
|
273
|
+
notLoggedIn: 'Not logged in. Use `mbler login <token>` first.',
|
|
274
|
+
progress: 'Progress: {progress}%',
|
|
275
|
+
publishFailed: 'Publish failed: {error}',
|
|
276
|
+
publishing: 'Publishing...',
|
|
277
|
+
building: 'Building project...',
|
|
278
|
+
publishToMarket: 'Publishing to marketplace...',
|
|
279
|
+
publishSuccess: 'Publish successful',
|
|
280
|
+
publishResult: '+ {name}@{version} ({tag})',
|
|
281
|
+
projectPathNotExist: 'Project path does not exist',
|
|
282
|
+
outdirNotFound: 'Build output directories not found',
|
|
283
|
+
outdirNotExist: 'Build output directories do not exist',
|
|
284
|
+
readmeNotFound: 'README file not found',
|
|
285
|
+
metadataInvalid: 'Invalid metadata',
|
|
286
|
+
packageNameInvalid: 'Package name must be in the format of @scope/name',
|
|
287
|
+
notLoginError: 'Not logged in',
|
|
288
|
+
tokenMissing: 'Failed to get token',
|
|
289
|
+
unpublishReqFailed: 'Failed to unpublish package',
|
|
290
|
+
createSessionFailed: 'Failed to create publish session',
|
|
291
|
+
uploadZipFailed: 'Failed to upload zip file',
|
|
292
|
+
packageJsonNotFound: 'package.json not found',
|
|
293
|
+
noBuildScript: 'No build script found in package.json',
|
|
294
|
+
buildFailed: 'Build failed with code {code}',
|
|
295
|
+
},
|
|
296
|
+
install: {
|
|
297
|
+
failedNoPackageJson: 'Install failed: work directory must contain package.json',
|
|
298
|
+
failedNoBuildScript: 'Install failed: package.json must contain a build script',
|
|
299
|
+
installing: 'Installing package {pkg}...',
|
|
300
|
+
packageNotFound: 'Package {pkg} not found',
|
|
301
|
+
noVersion: 'Package {pkg} has no available version',
|
|
302
|
+
usingLatest: 'Using latest version {version}',
|
|
303
|
+
noValidAddon: 'No valid addon found in package',
|
|
304
|
+
success: 'Package {pkg}@{version} installed successfully as {id}',
|
|
305
|
+
failed: 'Install failed: {error}',
|
|
306
|
+
},
|
|
307
|
+
uninstall: {
|
|
308
|
+
success: 'Package {pkg}@{version} uninstalled successfully',
|
|
309
|
+
failed: 'Uninstall failed: {error}',
|
|
310
|
+
},
|
|
311
|
+
unpublish: {
|
|
312
|
+
success: 'Package {pkg}@{version} unpublished successfully',
|
|
313
|
+
failed: 'Unpublish failed: {error}',
|
|
314
|
+
},
|
|
315
|
+
view: {
|
|
316
|
+
usage: 'mbler view @<scope>/<name>',
|
|
317
|
+
packageNotFound: 'Package {pkg} not found',
|
|
318
|
+
title: 'Package {pkg} versions:',
|
|
319
|
+
versionLine: '- {version} [{tag}] by {user} at {time}',
|
|
320
|
+
failed: 'View failed: {error}',
|
|
321
|
+
},
|
|
322
|
+
config: {
|
|
323
|
+
usage: 'mbler config get <key> | set <key> <value> | point <path> | point get',
|
|
324
|
+
missingArg: 'Missing argument',
|
|
325
|
+
getResult: '{key} = {value}',
|
|
326
|
+
setSuccess: 'Set {key} = {value}',
|
|
327
|
+
pointGet: 'Current config file: {path}',
|
|
328
|
+
pointSetSuccess: 'Config file pointer set to: {path}',
|
|
329
|
+
pointSetFailed: 'Failed to set config pointer: {error}',
|
|
330
|
+
failed: 'Config command failed: {error}',
|
|
331
|
+
},
|
|
332
|
+
commander: {
|
|
333
|
+
selectTip: '(Press b to confirm, n to select next)',
|
|
334
|
+
},
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
const configPath = path.join(os.homedir(), // ~/.cache/mbler/lang.db: push language config
|
|
338
|
+
'.cache/mbler/lang.db');
|
|
339
|
+
function isLanguareName(language) {
|
|
340
|
+
return LanguageNames.includes(language);
|
|
341
|
+
}
|
|
342
|
+
class Lang {
|
|
343
|
+
currenyLang = 'zh';
|
|
344
|
+
init() {
|
|
345
|
+
try {
|
|
346
|
+
const TheyLang = fs.readFileSync(configPath, 'utf-8').toString().trim();
|
|
347
|
+
if (isLanguareName(TheyLang)) {
|
|
348
|
+
this.currenyLang = TheyLang;
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
throw new Error('[setup lang]: set lang error');
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
this.currenyLang = 'zh';
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
set(newLang) {
|
|
359
|
+
if (LanguageNames.includes(newLang)) {
|
|
360
|
+
if (!fs.existsSync(configPath)) {
|
|
361
|
+
fs.mkdirSync(path.dirname(configPath), {
|
|
362
|
+
recursive: true,
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
fs.writeFileSync(configPath, newLang);
|
|
366
|
+
this.currenyLang = newLang;
|
|
367
|
+
return true;
|
|
368
|
+
}
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
371
|
+
get() {
|
|
372
|
+
try {
|
|
373
|
+
if (this.currenyLang == 'zh')
|
|
374
|
+
return ZhLang;
|
|
375
|
+
return enLang;
|
|
376
|
+
}
|
|
377
|
+
catch {
|
|
378
|
+
return ZhLang;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
const lang = new Lang();
|
|
383
|
+
const i18n = {};
|
|
384
|
+
function Export(lang) {
|
|
385
|
+
const obj = lang.get();
|
|
386
|
+
Object.setPrototypeOf(i18n, {
|
|
387
|
+
...obj,
|
|
388
|
+
__internal: {
|
|
389
|
+
class: lang,
|
|
390
|
+
set: (newLang) => {
|
|
391
|
+
lang.set(newLang);
|
|
392
|
+
Export(lang);
|
|
393
|
+
},
|
|
394
|
+
},
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
lang.init();
|
|
398
|
+
Export(lang);
|
|
50
399
|
|
|
51
|
-
// 启用 raw mode 和键盘事件(仅在 TTY 环境中)
|
|
52
400
|
if (process.stdin.isTTY) {
|
|
53
401
|
process.stdin.setRawMode(true);
|
|
54
402
|
readline__namespace.emitKeypressEvents(process.stdin);
|
|
55
403
|
}
|
|
56
404
|
const promises = [];
|
|
57
405
|
const tasks = [];
|
|
58
|
-
process.on(
|
|
59
|
-
process.stdout.write(
|
|
406
|
+
process.on('exit', (_code) => {
|
|
407
|
+
process.stdout.write('\x1b[?25h');
|
|
60
408
|
});
|
|
61
409
|
const endTasks = [];
|
|
62
410
|
function onEnd(task) {
|
|
63
411
|
endTasks.push(task);
|
|
64
412
|
}
|
|
65
|
-
click(
|
|
413
|
+
click('c', {
|
|
66
414
|
ctrl: true,
|
|
67
415
|
}).then(() => {
|
|
68
416
|
endTasks.forEach((task) => task());
|
|
69
417
|
process.exit(0);
|
|
70
418
|
});
|
|
71
|
-
/**
|
|
72
|
-
* 监听键盘输入并触发对应的 Promise 或任务
|
|
73
|
-
*/
|
|
74
419
|
function handler(name, { ctrl, alt, }, raw) {
|
|
75
|
-
// 查找是否有匹配的 Promise 等待触发
|
|
76
420
|
const find = promises.find((e) => e.name === name && e.ctrl === ctrl && e.alt === alt);
|
|
77
421
|
if (find) {
|
|
78
422
|
find.resolve();
|
|
79
423
|
promises.splice(promises.indexOf(find), 1);
|
|
80
424
|
}
|
|
81
|
-
// 通知所有注册的监听任务
|
|
82
425
|
tasks.forEach((item) => item(name, ctrl, alt, raw));
|
|
83
426
|
}
|
|
84
|
-
/**
|
|
85
|
-
* 模拟等待某个按键被按下,返回一个 Promise
|
|
86
|
-
*/
|
|
87
427
|
function click(name, { ctrl = false, alt = false, }) {
|
|
88
428
|
return new Promise((resolve) => {
|
|
89
429
|
promises.push({
|
|
@@ -94,36 +434,21 @@ function click(name, { ctrl = false, alt = false, }) {
|
|
|
94
434
|
});
|
|
95
435
|
});
|
|
96
436
|
}
|
|
97
|
-
/**
|
|
98
|
-
* 工具类:提供控制台交互功能,比如高亮菜单渲染、交互式选择等
|
|
99
|
-
*/
|
|
100
437
|
class Input {
|
|
101
|
-
/**
|
|
102
|
-
* 渲染一个字符串数组,高亮当前选中的项
|
|
103
|
-
* @param arr 菜单项数组
|
|
104
|
-
* @param index 当前选中索引
|
|
105
|
-
* @returns 格式化后的字符串
|
|
106
|
-
*/
|
|
107
438
|
static render(arr, index) {
|
|
108
439
|
return arr
|
|
109
440
|
.map((item, pindex) => {
|
|
110
441
|
if (pindex === index)
|
|
111
|
-
return
|
|
112
|
-
return
|
|
442
|
+
return '\x1b[1m\x1b[32m' + item + '\x1b[0m'; // 亮绿,高亮
|
|
443
|
+
return '\x1b[1m\x1b[33m' + item + '\x1b[0m'; // 亮黄
|
|
113
444
|
})
|
|
114
|
-
.join(
|
|
445
|
+
.join(' ');
|
|
115
446
|
}
|
|
116
|
-
/**
|
|
117
|
-
* 提供一个交互式菜单选择器
|
|
118
|
-
* @param tip 提示文本
|
|
119
|
-
* @param arr 选项数组
|
|
120
|
-
* @returns 用户选中的选项内容(Promise<string>)
|
|
121
|
-
*/
|
|
122
447
|
static select(tip, arr) {
|
|
123
448
|
let index = 0;
|
|
124
449
|
let win = false;
|
|
125
|
-
console.log(`\x1b[2K\x1b[47m\x1b[1m\x1b[30m${tip}
|
|
126
|
-
console.log(Input.render(arr, index) +
|
|
450
|
+
console.log(`\x1b[2K\x1b[47m\x1b[1m\x1b[30m${tip} ${i18n.commander.selectTip} \x1b[0m\x1b[?25l`);
|
|
451
|
+
console.log(Input.render(arr, index) + '\n\x1b[1A');
|
|
127
452
|
const handlerNext = () => {
|
|
128
453
|
if (win)
|
|
129
454
|
return;
|
|
@@ -131,39 +456,32 @@ class Input {
|
|
|
131
456
|
if (index >= arr.length)
|
|
132
457
|
index = 0;
|
|
133
458
|
console.log(`\x1b[1A${Input.render(arr, index)}\n\x1b[1A`);
|
|
134
|
-
click(
|
|
459
|
+
click('n', {
|
|
135
460
|
ctrl: false,
|
|
136
461
|
alt: false,
|
|
137
462
|
}).then(handlerNext);
|
|
138
463
|
};
|
|
139
464
|
return new Promise((resolve) => {
|
|
140
|
-
|
|
141
|
-
click("n", {
|
|
465
|
+
click('n', {
|
|
142
466
|
ctrl: false,
|
|
143
467
|
alt: false,
|
|
144
468
|
}).then(handlerNext);
|
|
145
|
-
|
|
146
|
-
click("b", {
|
|
469
|
+
click('b', {
|
|
147
470
|
ctrl: false,
|
|
148
471
|
alt: false,
|
|
149
472
|
}).then(() => {
|
|
150
473
|
win = true;
|
|
151
|
-
process.stdout.write(
|
|
474
|
+
process.stdout.write('\x1b[?25h');
|
|
152
475
|
resolve(arr[index]);
|
|
153
476
|
});
|
|
154
477
|
});
|
|
155
478
|
}
|
|
156
|
-
/**
|
|
157
|
-
* 注册一个全局任务,每次按键都会被调用
|
|
158
|
-
* @param task 回调函数
|
|
159
|
-
*/
|
|
160
479
|
static use(task) {
|
|
161
480
|
tasks.push(task);
|
|
162
481
|
}
|
|
163
482
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
const rawKeyName = key?.name || "";
|
|
483
|
+
process.stdin.on('keypress', (str, key) => {
|
|
484
|
+
const rawKeyName = key?.name || '';
|
|
167
485
|
const ctrl = Boolean(key?.ctrl);
|
|
168
486
|
const alt = Boolean(key?.alt);
|
|
169
487
|
handler(rawKeyName, {
|
|
@@ -172,98 +490,147 @@ process.stdin.on("keypress", (str, key) => {
|
|
|
172
490
|
}, str);
|
|
173
491
|
});
|
|
174
492
|
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
},
|
|
189
|
-
build: {
|
|
190
|
-
rollupPlugins: [],
|
|
191
|
-
cache: "auto",
|
|
192
|
-
bundle: true,
|
|
193
|
-
onEnd: () => { },
|
|
194
|
-
onStart: () => { },
|
|
195
|
-
onWarn: () => { }
|
|
493
|
+
const logFile = path.join(os.homedir(), '.cache/mbler/latest.log');
|
|
494
|
+
function _clean(promise) {
|
|
495
|
+
return () => {
|
|
496
|
+
Logger.run = Logger.run.filter((item) => {
|
|
497
|
+
return item !== promise;
|
|
498
|
+
});
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
async function FileExsit$1(file) {
|
|
502
|
+
try {
|
|
503
|
+
const f = await fs$1.stat(file);
|
|
504
|
+
if (f)
|
|
505
|
+
return true;
|
|
196
506
|
}
|
|
197
|
-
|
|
507
|
+
catch {
|
|
508
|
+
return false;
|
|
509
|
+
}
|
|
510
|
+
return false;
|
|
511
|
+
}
|
|
512
|
+
function writeLog(logContent) {
|
|
513
|
+
async function write() {
|
|
514
|
+
try {
|
|
515
|
+
const dir = path.dirname(logFile);
|
|
516
|
+
if (!(await FileExsit$1(dir))) {
|
|
517
|
+
// ensure the directory exists, root-to-leaf
|
|
518
|
+
await fs$1.mkdir(dir, { recursive: true }).catch(() => void 0);
|
|
519
|
+
}
|
|
520
|
+
// if file does not exist, create it (touch)
|
|
521
|
+
if (!(await FileExsit$1(logFile))) {
|
|
522
|
+
await fs$1.writeFile(logFile, '');
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
catch (err) {
|
|
526
|
+
// if we can't prepare the log file, output to stderr but don't crash
|
|
527
|
+
console.error('[logger] unable to prepare log file:', err);
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
try {
|
|
531
|
+
await fs$1.appendFile(logFile, '\n' + logContent);
|
|
532
|
+
}
|
|
533
|
+
catch (err) {
|
|
534
|
+
console.error('[logger] failed to append to log file:', err);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
const asy = write();
|
|
538
|
+
Logger.run.push(asy.then(_clean(asy)));
|
|
539
|
+
}
|
|
540
|
+
class Logger {
|
|
541
|
+
static LogFile = logFile;
|
|
542
|
+
static run = [];
|
|
543
|
+
static _b(tag, msg, t) {
|
|
544
|
+
const date = new Date();
|
|
545
|
+
const logContent = [
|
|
546
|
+
`${date.toLocaleDateString()} ${date.toLocaleTimeString()}`,
|
|
547
|
+
`[${t} ${tag}]`,
|
|
548
|
+
msg,
|
|
549
|
+
].join(' ');
|
|
550
|
+
writeLog(logContent);
|
|
551
|
+
}
|
|
552
|
+
static w(tag, msg) {
|
|
553
|
+
Logger._b(tag, msg, 'WARN');
|
|
554
|
+
}
|
|
555
|
+
static e(tag, msg) {
|
|
556
|
+
Logger._b(tag, msg, 'ERROR');
|
|
557
|
+
}
|
|
558
|
+
static i(tag, msg) {
|
|
559
|
+
Logger._b(tag, msg, 'INFO');
|
|
560
|
+
}
|
|
561
|
+
static d(tag, msg) {
|
|
562
|
+
Logger._b(tag, msg, 'DEBUG');
|
|
563
|
+
}
|
|
564
|
+
}
|
|
198
565
|
|
|
199
566
|
const BuildConfig = {
|
|
200
|
-
ConfigFile:
|
|
567
|
+
ConfigFile: 'mbler.config.js',
|
|
201
568
|
salt: {
|
|
202
|
-
header:
|
|
203
|
-
sapi:
|
|
204
|
-
module:
|
|
569
|
+
header: 'd61e721d-a2c9-4535-8054-0183bce24767',
|
|
570
|
+
sapi: '33e2c698-908f-45ab-8a9f-66018f8486ed',
|
|
571
|
+
module: 'cbbacfa4-8b1e-4a9c-9cbd-7a0d2e5f0b3c',
|
|
205
572
|
},
|
|
206
|
-
behavior:
|
|
207
|
-
resources:
|
|
573
|
+
behavior: 'behavior',
|
|
574
|
+
resources: 'resources',
|
|
208
575
|
includes: {
|
|
209
576
|
public: {
|
|
210
|
-
|
|
211
|
-
|
|
577
|
+
'pack_icon.png': 'file',
|
|
578
|
+
'manifest.json': 'file',
|
|
212
579
|
},
|
|
213
580
|
resources: {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
animation_controllers:
|
|
224
|
-
animations:
|
|
225
|
-
attachables:
|
|
226
|
-
biomes:
|
|
227
|
-
cameras:
|
|
228
|
-
entity:
|
|
229
|
-
fogs:
|
|
230
|
-
font:
|
|
231
|
-
items:
|
|
232
|
-
library:
|
|
233
|
-
materials:
|
|
234
|
-
models:
|
|
235
|
-
particles:
|
|
236
|
-
render_controllers:
|
|
237
|
-
sounds:
|
|
238
|
-
texts:
|
|
239
|
-
textures:
|
|
581
|
+
'biomes_client.json': 'file',
|
|
582
|
+
'blocks.json': 'file',
|
|
583
|
+
'bug_pack_icon.png': 'file',
|
|
584
|
+
'contents.json': 'file',
|
|
585
|
+
'loading_messages.json': 'file',
|
|
586
|
+
'manifest_publish.json': 'file',
|
|
587
|
+
'signatures.json': 'file',
|
|
588
|
+
'sounds.json': 'file',
|
|
589
|
+
'splashes.json': 'file',
|
|
590
|
+
animation_controllers: 'directory',
|
|
591
|
+
animations: 'directory',
|
|
592
|
+
attachables: 'directory',
|
|
593
|
+
biomes: 'directory',
|
|
594
|
+
cameras: 'directory',
|
|
595
|
+
entity: 'directory',
|
|
596
|
+
fogs: 'directory',
|
|
597
|
+
font: 'directory',
|
|
598
|
+
items: 'directory',
|
|
599
|
+
library: 'directory',
|
|
600
|
+
materials: 'directory',
|
|
601
|
+
models: 'directory',
|
|
602
|
+
particles: 'directory',
|
|
603
|
+
render_controllers: 'directory',
|
|
604
|
+
sounds: 'directory',
|
|
605
|
+
texts: 'directory',
|
|
606
|
+
textures: 'directory',
|
|
240
607
|
},
|
|
241
608
|
behavior: {
|
|
242
|
-
aim_assist:
|
|
243
|
-
animation_controllers:
|
|
244
|
-
animations:
|
|
245
|
-
behavior_trees:
|
|
246
|
-
biomes:
|
|
247
|
-
blocks:
|
|
248
|
-
cameras:
|
|
249
|
-
dimensions:
|
|
250
|
-
entities:
|
|
251
|
-
feature_rules:
|
|
252
|
-
features:
|
|
253
|
-
functions:
|
|
254
|
-
item_catalog:
|
|
255
|
-
items:
|
|
256
|
-
loot_tables:
|
|
257
|
-
recipes:
|
|
258
|
-
scripts:
|
|
259
|
-
spawn_rules:
|
|
260
|
-
structures:
|
|
261
|
-
texts:
|
|
262
|
-
trading:
|
|
263
|
-
worldgen:
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
609
|
+
aim_assist: 'directory',
|
|
610
|
+
animation_controllers: 'directory',
|
|
611
|
+
animations: 'directory',
|
|
612
|
+
behavior_trees: 'directory',
|
|
613
|
+
biomes: 'directory',
|
|
614
|
+
blocks: 'directory',
|
|
615
|
+
cameras: 'directory',
|
|
616
|
+
dimensions: 'directory',
|
|
617
|
+
entities: 'directory',
|
|
618
|
+
feature_rules: 'directory',
|
|
619
|
+
features: 'directory',
|
|
620
|
+
functions: 'directory',
|
|
621
|
+
item_catalog: 'directory',
|
|
622
|
+
items: 'directory',
|
|
623
|
+
loot_tables: 'directory',
|
|
624
|
+
recipes: 'directory',
|
|
625
|
+
scripts: 'skip', // special handling
|
|
626
|
+
spawn_rules: 'directory',
|
|
627
|
+
structures: 'directory',
|
|
628
|
+
texts: 'directory',
|
|
629
|
+
trading: 'directory',
|
|
630
|
+
worldgen: 'directory',
|
|
631
|
+
'contents.json': 'file',
|
|
632
|
+
'manifest_publish.json': 'file',
|
|
633
|
+
'signatures.json': 'file',
|
|
267
634
|
},
|
|
268
635
|
},
|
|
269
636
|
};
|
|
@@ -290,14 +657,32 @@ async function ReadProjectMblerConfig(project) {
|
|
|
290
657
|
throw new Error(`[read config]: read config from '${project}' error: Unexpected '${key}'`);
|
|
291
658
|
}
|
|
292
659
|
}
|
|
293
|
-
|
|
660
|
+
const config = {
|
|
661
|
+
...templateMblerConfig,
|
|
662
|
+
...file,
|
|
663
|
+
};
|
|
664
|
+
try {
|
|
665
|
+
const pkgRaw = await fs__namespace.readFile(path__namespace.join(project, 'package.json'), 'utf-8');
|
|
666
|
+
const pkg = JSON.parse(pkgRaw);
|
|
667
|
+
if (pkg.name)
|
|
668
|
+
config.name = pkg.name;
|
|
669
|
+
if (pkg.version)
|
|
670
|
+
config.version = pkg.version;
|
|
671
|
+
}
|
|
672
|
+
catch {
|
|
673
|
+
// fallback to mbler.config.js or template defaults
|
|
674
|
+
}
|
|
675
|
+
if (!config.name)
|
|
676
|
+
config.name = 'unknown';
|
|
677
|
+
if (!config.version)
|
|
678
|
+
config.version = '0.0.0';
|
|
679
|
+
return config;
|
|
294
680
|
}
|
|
295
681
|
/**
|
|
296
682
|
* Print a single-line message to stdout with a trailing newline.
|
|
297
683
|
* Exported here so other modules (for example `build`) do not need
|
|
298
684
|
* to import from `cli`, avoiding a circular dependency.
|
|
299
685
|
*/
|
|
300
|
-
// IO缓冲队列,避免多线程写入冲突
|
|
301
686
|
let outputQueue = [];
|
|
302
687
|
let isFlushing = false;
|
|
303
688
|
async function flushOutputQueue() {
|
|
@@ -316,11 +701,13 @@ async function flushOutputQueue() {
|
|
|
316
701
|
isFlushing = false;
|
|
317
702
|
}
|
|
318
703
|
}
|
|
319
|
-
process.on(
|
|
704
|
+
process.on('exit', flushOutputQueue);
|
|
320
705
|
function showText(text, needNextLine = true) {
|
|
321
|
-
outputQueue.push(text + (needNextLine ? '\n' :
|
|
706
|
+
outputQueue.push(text + (needNextLine ? '\n' : ''));
|
|
322
707
|
if (!isFlushing) {
|
|
323
|
-
Promise.resolve()
|
|
708
|
+
Promise.resolve()
|
|
709
|
+
.then(() => flushOutputQueue())
|
|
710
|
+
.catch(() => {
|
|
324
711
|
outputQueue = [];
|
|
325
712
|
isFlushing = false;
|
|
326
713
|
});
|
|
@@ -403,165 +790,54 @@ function compareVersion(a, b) {
|
|
|
403
790
|
};
|
|
404
791
|
}))();
|
|
405
792
|
|
|
406
|
-
const logFile = path.join(os.homedir(), ".cache/mbler/latest.log");
|
|
407
|
-
function _clean(promise) {
|
|
408
|
-
return () => {
|
|
409
|
-
Logger.run = Logger.run.filter((item) => {
|
|
410
|
-
return item !== promise;
|
|
411
|
-
});
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
function writeLog(logContent) {
|
|
415
|
-
async function write() {
|
|
416
|
-
try {
|
|
417
|
-
const dir = path.dirname(logFile);
|
|
418
|
-
if (!(await FileExsit(dir))) {
|
|
419
|
-
// ensure the directory exists, root-to-leaf
|
|
420
|
-
await fs.mkdir(dir, { recursive: true }).catch(() => void 0);
|
|
421
|
-
}
|
|
422
|
-
// if file does not exist, create it (touch)
|
|
423
|
-
if (!(await FileExsit(logFile))) {
|
|
424
|
-
await fs.writeFile(logFile, "");
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
catch (err) {
|
|
428
|
-
// if we can't prepare the log file, output to stderr but don't crash
|
|
429
|
-
console.error("[logger] unable to prepare log file:", err);
|
|
430
|
-
return;
|
|
431
|
-
}
|
|
432
|
-
try {
|
|
433
|
-
await fs.appendFile(logFile, "\n" + logContent);
|
|
434
|
-
}
|
|
435
|
-
catch (err) {
|
|
436
|
-
console.error("[logger] failed to append to log file:", err);
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
const asy = write();
|
|
440
|
-
Logger.run.push(asy.then(_clean(asy)));
|
|
441
|
-
}
|
|
442
|
-
class Logger {
|
|
443
|
-
// 写入日志池
|
|
444
|
-
static LogFile = logFile;
|
|
445
|
-
static run = [];
|
|
446
|
-
static _b(tag, msg, t) {
|
|
447
|
-
const date = new Date();
|
|
448
|
-
const logContent = [
|
|
449
|
-
`${date.toLocaleDateString()} ${date.toLocaleTimeString()}`,
|
|
450
|
-
`[${t} ${tag}]`,
|
|
451
|
-
msg,
|
|
452
|
-
].join(" ");
|
|
453
|
-
writeLog(logContent);
|
|
454
|
-
}
|
|
455
|
-
static w(tag, msg) {
|
|
456
|
-
Logger._b(tag, msg, "WARN");
|
|
457
|
-
}
|
|
458
|
-
static e(tag, msg) {
|
|
459
|
-
Logger._b(tag, msg, "ERROR");
|
|
460
|
-
}
|
|
461
|
-
static i(tag, msg) {
|
|
462
|
-
Logger._b(tag, msg, "INFO");
|
|
463
|
-
}
|
|
464
|
-
static d(tag, msg) {
|
|
465
|
-
Logger._b(tag, msg, "DEBUG");
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
|
|
469
793
|
class BuildCacheManager {
|
|
470
|
-
projectRoot;
|
|
471
794
|
isWatch;
|
|
472
|
-
cacheDir;
|
|
473
|
-
cacheFile;
|
|
474
795
|
mode;
|
|
475
|
-
|
|
476
|
-
constructor(projectRoot, mode, isWatch) {
|
|
477
|
-
this.projectRoot = projectRoot;
|
|
796
|
+
constructor(_projectRoot, mode, isWatch, _cachePath) {
|
|
478
797
|
this.isWatch = isWatch;
|
|
479
|
-
this.cacheDir = path.join(this.projectRoot, ".mbler", "cache");
|
|
480
|
-
this.cacheFile = path.join(this.cacheDir, "rollup.cache.bin");
|
|
481
798
|
this.mode = this.resolveMode(mode);
|
|
482
799
|
}
|
|
483
800
|
getMode() {
|
|
484
801
|
return this.mode;
|
|
485
802
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
return undefined;
|
|
489
|
-
if (this.mode === "memory")
|
|
490
|
-
return this.memoryCache;
|
|
491
|
-
if (this.memoryCache)
|
|
492
|
-
return this.memoryCache;
|
|
493
|
-
try {
|
|
494
|
-
const raw = await fs.readFile(this.cacheFile);
|
|
495
|
-
this.memoryCache = node_v8.deserialize(raw);
|
|
496
|
-
return this.memoryCache;
|
|
497
|
-
}
|
|
498
|
-
catch {
|
|
499
|
-
return undefined;
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
getWatchCacheOption() {
|
|
503
|
-
if (this.mode === "none")
|
|
504
|
-
return false;
|
|
505
|
-
return true;
|
|
506
|
-
}
|
|
507
|
-
async saveRollupCache(cache) {
|
|
508
|
-
if (!cache || this.mode === "none")
|
|
509
|
-
return;
|
|
510
|
-
this.memoryCache = cache;
|
|
511
|
-
if (this.mode !== "file")
|
|
512
|
-
return;
|
|
513
|
-
try {
|
|
514
|
-
await fs.mkdir(this.cacheDir, { recursive: true });
|
|
515
|
-
await fs.writeFile(this.cacheFile, node_v8.serialize(cache));
|
|
516
|
-
}
|
|
517
|
-
catch (error) {
|
|
518
|
-
Logger.w("BuildCache", `failed to write file cache: ${error}`);
|
|
519
|
-
}
|
|
803
|
+
shouldUseIncrementalBuild() {
|
|
804
|
+
return this.mode !== 'none';
|
|
520
805
|
}
|
|
521
806
|
resolveMode(mode) {
|
|
522
|
-
const value = mode ??
|
|
523
|
-
if (value ===
|
|
524
|
-
return
|
|
525
|
-
|
|
526
|
-
if (this.isWatch)
|
|
527
|
-
return "memory";
|
|
528
|
-
return "none";
|
|
529
|
-
}
|
|
530
|
-
if (value === "file" || value === "filesystem")
|
|
531
|
-
return "file";
|
|
532
|
-
// auto: watch mode uses memory, non-watch uses file
|
|
533
|
-
return this.isWatch ? "memory" : "file";
|
|
807
|
+
const value = mode ?? 'auto';
|
|
808
|
+
if (value === 'none')
|
|
809
|
+
return 'none';
|
|
810
|
+
return 'file';
|
|
534
811
|
}
|
|
535
812
|
}
|
|
536
813
|
|
|
537
|
-
|
|
814
|
+
/**
|
|
815
|
+
* @description To generate uuid
|
|
816
|
+
*/
|
|
538
817
|
const fromString = (input, salt = '') => {
|
|
539
818
|
const combinedInput = salt + input;
|
|
540
|
-
const hash = crypto
|
|
541
|
-
|
|
542
|
-
.update(combinedInput)
|
|
543
|
-
.digest('hex');
|
|
544
|
-
const base = hash
|
|
545
|
-
.slice(0, 32); // 取前 32 个 hex 字符(16 字节)
|
|
819
|
+
const hash = crypto.createHash('sha256').update(combinedInput).digest('hex');
|
|
820
|
+
const base = hash.slice(0, 32);
|
|
546
821
|
const ls = '89ab';
|
|
547
822
|
const r = (t) => ls[(combinedInput.length + t + salt.length) % ls.length];
|
|
548
|
-
//
|
|
823
|
+
// build to:xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
|
|
549
824
|
const uuid = `${base.substring(0, 8)}-${base.substring(8, 12)}-4${base.substring(12, 15)}-8${r(1)}${r(2)}${r(3)}-${base.substring(18, 30)}`;
|
|
550
825
|
return uuid;
|
|
551
826
|
};
|
|
552
827
|
({
|
|
553
|
-
uuid: crypto.randomUUID
|
|
828
|
+
uuid: crypto.randomUUID,
|
|
554
829
|
});
|
|
555
830
|
|
|
556
831
|
const config = {
|
|
557
|
-
tmpdir: path__namespace.join(os.tmpdir(),
|
|
832
|
+
tmpdir: path__namespace.join(os.tmpdir(), '.mbler')};
|
|
558
833
|
|
|
559
834
|
/**
|
|
560
835
|
* Compare two dotted version strings ("major.minor.patch").
|
|
561
836
|
* Returns negative if a < b, positive if a > b, zero if equal.
|
|
562
837
|
*/
|
|
563
|
-
const
|
|
564
|
-
const
|
|
838
|
+
const Sapi = function () {
|
|
839
|
+
const { json } = require('npm-registry-fetch');
|
|
840
|
+
const cacheFile = path__namespace.join(config.tmpdir, '_sapi_version.json');
|
|
565
841
|
// cacheData is an array of entries keyed by the embedded mc version string
|
|
566
842
|
let cacheData = null;
|
|
567
843
|
/**
|
|
@@ -570,7 +846,7 @@ const exp = (function () {
|
|
|
570
846
|
* recent formal/beta release we were able to parse.
|
|
571
847
|
*/
|
|
572
848
|
async function fetchData(pkgName) {
|
|
573
|
-
const data = (await
|
|
849
|
+
const data = (await json(`/${pkgName}`));
|
|
574
850
|
const pkgVersions = Object.keys(data.versions);
|
|
575
851
|
const reValue = {};
|
|
576
852
|
// helper to extract the embedded MC version ("yyyy") from a full
|
|
@@ -587,7 +863,11 @@ const exp = (function () {
|
|
|
587
863
|
const isStable = /(?:-stable)(?:$|[-.])/.test(v);
|
|
588
864
|
let entry = reValue[mcVersion];
|
|
589
865
|
if (!entry) {
|
|
590
|
-
entry = {
|
|
866
|
+
entry = {
|
|
867
|
+
formal: '',
|
|
868
|
+
beta: '',
|
|
869
|
+
_v: -1,
|
|
870
|
+
};
|
|
591
871
|
reValue[mcVersion] = entry;
|
|
592
872
|
}
|
|
593
873
|
if (isStable) {
|
|
@@ -610,8 +890,8 @@ const exp = (function () {
|
|
|
610
890
|
}
|
|
611
891
|
async function refresh() {
|
|
612
892
|
// grab the two packages we care about and merge the keys
|
|
613
|
-
const serverMap = await fetchData(
|
|
614
|
-
const uiMap = await fetchData(
|
|
893
|
+
const serverMap = await fetchData('@minecraft/server');
|
|
894
|
+
const uiMap = await fetchData('@minecraft/server-ui');
|
|
615
895
|
const versions = new Set([
|
|
616
896
|
...Object.keys(serverMap),
|
|
617
897
|
...Object.keys(uiMap),
|
|
@@ -621,24 +901,38 @@ const exp = (function () {
|
|
|
621
901
|
arr.push({
|
|
622
902
|
version: ver,
|
|
623
903
|
server: serverMap[ver]
|
|
624
|
-
? {
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
: {
|
|
904
|
+
? {
|
|
905
|
+
formal: serverMap[ver].formal,
|
|
906
|
+
beta: serverMap[ver].beta,
|
|
907
|
+
}
|
|
908
|
+
: {
|
|
909
|
+
formal: '',
|
|
910
|
+
beta: '',
|
|
911
|
+
},
|
|
912
|
+
'server-ui': uiMap[ver]
|
|
913
|
+
? {
|
|
914
|
+
formal: uiMap[ver].formal,
|
|
915
|
+
beta: uiMap[ver].beta,
|
|
916
|
+
}
|
|
917
|
+
: {
|
|
918
|
+
formal: '',
|
|
919
|
+
beta: '',
|
|
920
|
+
},
|
|
629
921
|
});
|
|
630
922
|
}
|
|
631
923
|
arr.sort((a, b) => compareVersion(a.version, b.version));
|
|
632
924
|
cacheData = arr;
|
|
633
925
|
await fs__namespace$1.promises
|
|
634
|
-
.mkdir(config.tmpdir, {
|
|
926
|
+
.mkdir(config.tmpdir, {
|
|
927
|
+
recursive: true,
|
|
928
|
+
})
|
|
635
929
|
.catch(() => void 0);
|
|
636
|
-
await fs__namespace$1.promises.writeFile(cacheFile, JSON.stringify(arr, null, 2),
|
|
930
|
+
await fs__namespace$1.promises.writeFile(cacheFile, JSON.stringify(arr, null, 2), 'utf-8');
|
|
637
931
|
}
|
|
638
|
-
async function generateVersion(module, mcVersion, isBeta) {
|
|
932
|
+
async function generateVersion(module, mcVersion, isBeta, withFull = false) {
|
|
639
933
|
if (!cacheData) {
|
|
640
934
|
try {
|
|
641
|
-
const txt = await fs__namespace$1.promises.readFile(cacheFile,
|
|
935
|
+
const txt = await fs__namespace$1.promises.readFile(cacheFile, 'utf-8');
|
|
642
936
|
cacheData = JSON.parse(txt);
|
|
643
937
|
}
|
|
644
938
|
catch {
|
|
@@ -646,7 +940,7 @@ const exp = (function () {
|
|
|
646
940
|
}
|
|
647
941
|
}
|
|
648
942
|
if (!cacheData) {
|
|
649
|
-
throw new Error(
|
|
943
|
+
throw new Error('unable to load sapi cache data');
|
|
650
944
|
}
|
|
651
945
|
// try exact match first
|
|
652
946
|
let entry = cacheData.find((e) => e.version === mcVersion);
|
|
@@ -667,26 +961,50 @@ const exp = (function () {
|
|
|
667
961
|
}
|
|
668
962
|
entry = candidate;
|
|
669
963
|
}
|
|
670
|
-
const moduleKey = module ===
|
|
964
|
+
const moduleKey = module === '@minecraft/server' ? 'server' : 'server-ui';
|
|
671
965
|
const entryModule = entry[moduleKey];
|
|
672
966
|
let result = isBeta ? entryModule.beta : entryModule.formal;
|
|
673
967
|
if (!result) {
|
|
674
968
|
// fall back to whatever is available
|
|
675
969
|
result = entryModule.formal || entryModule.beta;
|
|
676
970
|
}
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
971
|
+
if (withFull)
|
|
972
|
+
return result || '';
|
|
973
|
+
else {
|
|
974
|
+
const tmp = result.split('-').slice(0, 2);
|
|
975
|
+
tmp[1] = tmp[1].split('.')[0];
|
|
976
|
+
result = tmp.join('-');
|
|
977
|
+
return result || 'error';
|
|
978
|
+
}
|
|
681
979
|
}
|
|
682
980
|
return {
|
|
683
981
|
refresh,
|
|
684
982
|
generateVersion,
|
|
685
983
|
};
|
|
686
|
-
}
|
|
984
|
+
};
|
|
985
|
+
let sapiEmul = null;
|
|
986
|
+
var Sapi$1 = new Proxy({}, {
|
|
987
|
+
get(_, p) {
|
|
988
|
+
if (!sapiEmul)
|
|
989
|
+
sapiEmul = Sapi();
|
|
990
|
+
return sapiEmul[p];
|
|
991
|
+
},
|
|
992
|
+
set(_, p, n) {
|
|
993
|
+
if (!sapiEmul)
|
|
994
|
+
sapiEmul = Sapi();
|
|
995
|
+
sapiEmul[p] = n;
|
|
996
|
+
return true;
|
|
997
|
+
},
|
|
998
|
+
});
|
|
999
|
+
function evalVersion(result) {
|
|
1000
|
+
const tmp = result.split('-').slice(0, 2);
|
|
1001
|
+
tmp[1] = tmp[1].split('.')[0];
|
|
1002
|
+
result = tmp.join('-');
|
|
1003
|
+
return result;
|
|
1004
|
+
}
|
|
687
1005
|
|
|
688
1006
|
async function generateManifest(config, type) {
|
|
689
|
-
const hashRaw = `${config.name}-${type}-${config.script?.lang ||
|
|
1007
|
+
const hashRaw = `${config.name}-${type}-${config.script?.lang || 'js'}--mbler-hash-raw--:build-manifest`;
|
|
690
1008
|
const manifest = {
|
|
691
1009
|
format_version: 2,
|
|
692
1010
|
header: {
|
|
@@ -694,10 +1012,10 @@ async function generateManifest(config, type) {
|
|
|
694
1012
|
description: config.description,
|
|
695
1013
|
uuid: fromString(hashRaw, BuildConfig.salt.header),
|
|
696
1014
|
version: stringToNumberArray(config.version),
|
|
697
|
-
min_engine_version: stringToNumberArray(typeof config.mcVersion ===
|
|
1015
|
+
min_engine_version: stringToNumberArray(typeof config.mcVersion === 'string'
|
|
698
1016
|
? config.mcVersion
|
|
699
1017
|
: (() => {
|
|
700
|
-
throw new Error(
|
|
1018
|
+
throw new Error('mcVersion in mblerconfig should be a string');
|
|
701
1019
|
})()),
|
|
702
1020
|
},
|
|
703
1021
|
modules: [
|
|
@@ -709,80 +1027,106 @@ async function generateManifest(config, type) {
|
|
|
709
1027
|
},
|
|
710
1028
|
],
|
|
711
1029
|
};
|
|
712
|
-
if (type ===
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
1030
|
+
if (type === 'data' && config.script) {
|
|
1031
|
+
const isBundle = config.build?.bundle !== false;
|
|
1032
|
+
const outputDir = config.build?.outputDir || 'scripts';
|
|
1033
|
+
let entry;
|
|
1034
|
+
if (isBundle) {
|
|
1035
|
+
let filename = config.script.main || 'index.js';
|
|
1036
|
+
if (config.build?.outputFilename) {
|
|
1037
|
+
filename = config.build.outputFilename;
|
|
1038
|
+
}
|
|
1039
|
+
const extName = path.extname(filename);
|
|
1040
|
+
if (extName !== '.js') {
|
|
1041
|
+
filename = filename.slice(0, -extName.length) + '.js';
|
|
1042
|
+
}
|
|
1043
|
+
if (config.script.lang == 'mcx') {
|
|
1044
|
+
entry = `${outputDir}/index.js`;
|
|
1045
|
+
}
|
|
1046
|
+
else {
|
|
1047
|
+
entry = `${outputDir}/${filename}`;
|
|
1048
|
+
}
|
|
716
1049
|
}
|
|
717
1050
|
else {
|
|
718
|
-
entry =
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
1051
|
+
entry = `${outputDir}/${config.script.main || 'index.js'}`;
|
|
1052
|
+
const extName = path.extname(entry);
|
|
1053
|
+
if (extName !== '.js') {
|
|
1054
|
+
entry = entry.slice(0, -extName.length) + '.js';
|
|
1055
|
+
}
|
|
723
1056
|
}
|
|
724
1057
|
manifest.modules.push({
|
|
725
|
-
type:
|
|
1058
|
+
type: 'script',
|
|
726
1059
|
entry: entry,
|
|
727
|
-
language:
|
|
1060
|
+
language: 'javascript',
|
|
728
1061
|
uuid: fromString(hashRaw, BuildConfig.salt.sapi),
|
|
729
1062
|
description: `sapi generate by mbler, weclome to download and star at https://github.com/RuanhoR/mbler`,
|
|
730
1063
|
version: stringToNumberArray(config.version),
|
|
731
1064
|
});
|
|
732
|
-
manifest.capabilities = [
|
|
1065
|
+
manifest.capabilities = ['script_eval'];
|
|
733
1066
|
manifest.dependencies = [
|
|
734
1067
|
{
|
|
735
|
-
module_name:
|
|
736
|
-
version: (await
|
|
1068
|
+
module_name: '@minecraft/server',
|
|
1069
|
+
version: evalVersion(await Sapi$1.generateVersion('@minecraft/server', config.mcVersion, config.script?.UseBeta || false, false)), // only major.minor.patch, remove -beta or -rc
|
|
737
1070
|
},
|
|
738
1071
|
];
|
|
739
1072
|
if (config.script.ui) {
|
|
740
1073
|
manifest.dependencies.push({
|
|
741
|
-
module_name:
|
|
742
|
-
version: (await
|
|
1074
|
+
module_name: '@minecraft/server-ui',
|
|
1075
|
+
version: evalVersion(await Sapi$1.generateVersion('@minecraft/server-ui', config.mcVersion, config.script?.UseBeta || false, false)), // only major.minor.patch, remove -beta or -rc
|
|
743
1076
|
});
|
|
744
1077
|
}
|
|
745
1078
|
}
|
|
746
1079
|
return manifest;
|
|
747
1080
|
}
|
|
748
1081
|
|
|
749
|
-
function
|
|
750
|
-
const
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
const zip = new AdmZip();
|
|
756
|
-
for (const folder of dir) {
|
|
757
|
-
await zip.addLocalFolderPromise(folder[0], {
|
|
758
|
-
zipPath: folder[1]
|
|
759
|
-
});
|
|
1082
|
+
function Release() {
|
|
1083
|
+
const AdmZip = require('adm-zip');
|
|
1084
|
+
function createFullZip(dir) {
|
|
1085
|
+
const zip = new AdmZip();
|
|
1086
|
+
zip.addLocalFolder(dir);
|
|
1087
|
+
return zip;
|
|
760
1088
|
}
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
if (build.module == "all") {
|
|
770
|
-
zip = await createZipWithMoreFolder([
|
|
771
|
-
[build.outdirs?.behavior, "behavior"],
|
|
772
|
-
[build.outdirs?.resources, "resources"]
|
|
773
|
-
]);
|
|
774
|
-
}
|
|
775
|
-
else if (build.module == "behavior") {
|
|
776
|
-
zip = createFullZip(build.outdirs?.behavior);
|
|
777
|
-
}
|
|
778
|
-
else {
|
|
779
|
-
zip = createFullZip(build.outdirs?.resources);
|
|
1089
|
+
async function createZipWithMoreFolder(dir) {
|
|
1090
|
+
const zip = new AdmZip();
|
|
1091
|
+
for (const folder of dir) {
|
|
1092
|
+
await zip.addLocalFolderPromise(folder[0], {
|
|
1093
|
+
zipPath: folder[1],
|
|
1094
|
+
});
|
|
1095
|
+
}
|
|
1096
|
+
return zip;
|
|
780
1097
|
}
|
|
781
|
-
|
|
1098
|
+
return async function generateRelease(build) {
|
|
1099
|
+
if (!build.outdirs)
|
|
1100
|
+
throw new Error('invalid Build');
|
|
1101
|
+
if (node_process.env.BUILD_MODULE !== 'release')
|
|
1102
|
+
return;
|
|
1103
|
+
let zip;
|
|
1104
|
+
if (build.module == 'all') {
|
|
1105
|
+
zip = await createZipWithMoreFolder([
|
|
1106
|
+
[build.outdirs?.behavior, 'behavior'],
|
|
1107
|
+
[build.outdirs?.resources, 'resources'],
|
|
1108
|
+
]);
|
|
1109
|
+
}
|
|
1110
|
+
else if (build.module == 'behavior') {
|
|
1111
|
+
zip = createFullZip(build.outdirs?.behavior);
|
|
1112
|
+
}
|
|
1113
|
+
else {
|
|
1114
|
+
zip = createFullZip(build.outdirs?.resources);
|
|
1115
|
+
}
|
|
1116
|
+
await zip.writeZipPromise(build.outdirs?.dist);
|
|
1117
|
+
};
|
|
782
1118
|
}
|
|
1119
|
+
let releaseEmul = null;
|
|
1120
|
+
const generateRelease = (...argv) => {
|
|
1121
|
+
if (!releaseEmul)
|
|
1122
|
+
releaseEmul = Release();
|
|
1123
|
+
return releaseEmul(...argv);
|
|
1124
|
+
};
|
|
783
1125
|
|
|
784
1126
|
// cjs support
|
|
785
|
-
const chalk$1 = _chalk instanceof Function
|
|
1127
|
+
const chalk$1 = _chalk instanceof Function
|
|
1128
|
+
? _chalk
|
|
1129
|
+
: _chalk.default;
|
|
786
1130
|
class Postgress {
|
|
787
1131
|
max;
|
|
788
1132
|
constructor(max) {
|
|
@@ -800,7 +1144,7 @@ class Postgress {
|
|
|
800
1144
|
const progressText = `\n\u001B[1A\r[${progressBar}] ${percentText} (${current}/${this.max})`;
|
|
801
1145
|
showText(progressText, false);
|
|
802
1146
|
if (current == this.max) {
|
|
803
|
-
showText(
|
|
1147
|
+
showText('', true);
|
|
804
1148
|
}
|
|
805
1149
|
}
|
|
806
1150
|
}
|
|
@@ -809,7 +1153,7 @@ class Postgress {
|
|
|
809
1153
|
* 运行 MCX TypeScript 编译器
|
|
810
1154
|
* 为 .mcx 文件提供 TypeScript 类型检查支持
|
|
811
1155
|
*/
|
|
812
|
-
function runTSC(tscpath = require.resolve(
|
|
1156
|
+
function runTSC(tscpath = require.resolve('typescript/lib/tsc')) {
|
|
813
1157
|
runTsc_js.runTsc(tscpath, {
|
|
814
1158
|
extraSupportedExtensions: ['.mcx'],
|
|
815
1159
|
extraExtensionsToRemove: ['.mcx'],
|
|
@@ -818,8 +1162,10 @@ function runTSC(tscpath = require.resolve("typescript/lib/tsc")) {
|
|
|
818
1162
|
});
|
|
819
1163
|
}
|
|
820
1164
|
|
|
821
|
-
// cjs support
|
|
822
|
-
const chalk = _chalk instanceof Function
|
|
1165
|
+
// cjs support (Why is chalk's type so weak? )
|
|
1166
|
+
const chalk = _chalk instanceof Function
|
|
1167
|
+
? _chalk
|
|
1168
|
+
: _chalk.default;
|
|
823
1169
|
class Build {
|
|
824
1170
|
baseBuildDir;
|
|
825
1171
|
resolve;
|
|
@@ -835,12 +1181,13 @@ class Build {
|
|
|
835
1181
|
this.isWatch = isWatch;
|
|
836
1182
|
try {
|
|
837
1183
|
const tsModule = ts;
|
|
838
|
-
this.mcxLanguagePluginCreator =
|
|
1184
|
+
this.mcxLanguagePluginCreator =
|
|
1185
|
+
mcxServer.createMCXLanguagePlugin;
|
|
839
1186
|
this.mcxTs = tsModule;
|
|
840
1187
|
}
|
|
841
1188
|
catch (error) {
|
|
842
1189
|
this.mcxTs = ts;
|
|
843
|
-
Logger.w(
|
|
1190
|
+
Logger.w('Build', `Failed to initialize MCX language plugin: ${error}`);
|
|
844
1191
|
}
|
|
845
1192
|
}
|
|
846
1193
|
/**
|
|
@@ -855,7 +1202,7 @@ class Build {
|
|
|
855
1202
|
onEnd(() => {
|
|
856
1203
|
if (this.watchers) {
|
|
857
1204
|
this.watchers.chokidar.close();
|
|
858
|
-
this.watchers.rollup
|
|
1205
|
+
this.watchers.rollup?.close();
|
|
859
1206
|
}
|
|
860
1207
|
});
|
|
861
1208
|
await this._watch();
|
|
@@ -908,7 +1255,7 @@ class Build {
|
|
|
908
1255
|
closeWatchers() {
|
|
909
1256
|
if (this.watchers) {
|
|
910
1257
|
this.watchers.chokidar.close();
|
|
911
|
-
this.watchers.rollup
|
|
1258
|
+
this.watchers.rollup?.close();
|
|
912
1259
|
this.watchers = null;
|
|
913
1260
|
}
|
|
914
1261
|
}
|
|
@@ -968,7 +1315,7 @@ class Build {
|
|
|
968
1315
|
this.currentConfig = await ReadProjectMblerConfig(this.baseBuildDir);
|
|
969
1316
|
if (this.currentConfig.build)
|
|
970
1317
|
this.buildConfig = this.currentConfig.build;
|
|
971
|
-
this.cacheManager = new BuildCacheManager(this.baseBuildDir, this.buildConfig?.cache, this.isWatch);
|
|
1318
|
+
this.cacheManager = new BuildCacheManager(this.baseBuildDir, this.buildConfig?.cache, this.isWatch, this.buildConfig?.cachePath);
|
|
972
1319
|
if (this.buildConfig?.onStart)
|
|
973
1320
|
await this.buildConfig.onStart(this.currentConfig);
|
|
974
1321
|
this.loadData();
|
|
@@ -978,38 +1325,48 @@ class Build {
|
|
|
978
1325
|
await this.handlerManifest();
|
|
979
1326
|
if (!this.isWatch)
|
|
980
1327
|
progress.update(30);
|
|
981
|
-
const
|
|
982
|
-
if (
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1328
|
+
const isBundle = this.currentConfig.build?.bundle !== false;
|
|
1329
|
+
if (this.currentConfig.script) {
|
|
1330
|
+
if (isBundle) {
|
|
1331
|
+
const rBuild = (await this.createRollup());
|
|
1332
|
+
if (!this.rollupPlugin || !this.outdirs) {
|
|
1333
|
+
throw new Error(`[build addon]: can't resolve rollup instance`);
|
|
1334
|
+
}
|
|
1335
|
+
if (!this.isWatch)
|
|
1336
|
+
progress.update(50);
|
|
1337
|
+
// write script
|
|
1338
|
+
let output = this.currentConfig.script?.main;
|
|
1339
|
+
if (!output)
|
|
1340
|
+
output = 'index.js';
|
|
1341
|
+
if (path.extname(output) !== 'js')
|
|
1342
|
+
output =
|
|
1343
|
+
output.slice(0, output.length - path.extname(output).length) + '.js';
|
|
1344
|
+
if (this.buildConfig?.outputFilename)
|
|
1345
|
+
output = this.buildConfig.outputFilename;
|
|
1346
|
+
const outputDir = this.buildConfig?.outputDir || 'scripts';
|
|
1347
|
+
await rBuild.write({
|
|
1348
|
+
file: join(path.join(this.outdirs.behavior, outputDir), output),
|
|
1001
1349
|
format: 'esm',
|
|
1002
1350
|
sourcemap: false,
|
|
1003
|
-
chunkFileNames: '[name].js',
|
|
1004
1351
|
});
|
|
1005
|
-
|
|
1352
|
+
}
|
|
1353
|
+
else {
|
|
1354
|
+
// bundle: false – skip rollup, copy source scripts directly
|
|
1355
|
+
const srcScriptDir = path.join(this.srcDirs.behavior, 'scripts');
|
|
1356
|
+
const outputDir = this.buildConfig?.outputDir || 'scripts';
|
|
1357
|
+
const outPath = path.join(this.outdirs.behavior, outputDir);
|
|
1358
|
+
if (await FileExsit(srcScriptDir)) {
|
|
1359
|
+
await fs__namespace.cp(srcScriptDir, outPath, { recursive: true, force: true });
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1006
1363
|
if (!this.isWatch)
|
|
1007
1364
|
progress.update(70);
|
|
1008
1365
|
if (!this.outdirs || !this.module)
|
|
1009
1366
|
throw new Error(`[build addon]: can't resolve outdirs`);
|
|
1010
1367
|
await generateRelease({
|
|
1011
1368
|
outdirs: this.outdirs,
|
|
1012
|
-
module: this.module
|
|
1369
|
+
module: this.module,
|
|
1013
1370
|
});
|
|
1014
1371
|
if (!this.isWatch)
|
|
1015
1372
|
progress.update(80);
|
|
@@ -1035,13 +1392,7 @@ class Build {
|
|
|
1035
1392
|
if (!(await FileExsit(main))) {
|
|
1036
1393
|
throw new Error(`[build addon]: main script ${main} is not exist: can't resolve entry`);
|
|
1037
1394
|
}
|
|
1038
|
-
const plugin = [
|
|
1039
|
-
jsonPlugin(),
|
|
1040
|
-
resolvePlugin({
|
|
1041
|
-
extensions: ['.ts', '.js', '.json'],
|
|
1042
|
-
}),
|
|
1043
|
-
commonjs()
|
|
1044
|
-
];
|
|
1395
|
+
const plugin = [];
|
|
1045
1396
|
const moduleDir = path.join(this.baseBuildDir, 'node_modules');
|
|
1046
1397
|
if (!(await FileExsit(moduleDir))) {
|
|
1047
1398
|
throw new Error(`[build addon]: node_modules is not exist in project root: can't resolve node_modules for rollup: ${moduleDir}`);
|
|
@@ -1059,23 +1410,6 @@ class Build {
|
|
|
1059
1410
|
if (this.buildConfig?.rollupPlugins) {
|
|
1060
1411
|
plugin.push(...this.buildConfig.rollupPlugins);
|
|
1061
1412
|
}
|
|
1062
|
-
if (this.currentConfig.script.lang == "ts") {
|
|
1063
|
-
const tsconfigPath = path.join(this.baseBuildDir, 'tsconfig.json');
|
|
1064
|
-
if (!(await FileExsit(tsconfigPath))) {
|
|
1065
|
-
throw new Error(`[build addon]: ts-lang: tsconfig.json is not exist in project root: can't resolve tsconfig for rollup: ${tsconfigPath}`);
|
|
1066
|
-
}
|
|
1067
|
-
plugin.push(typescript({
|
|
1068
|
-
sourceMap: false,
|
|
1069
|
-
tsconfig: tsconfigPath,
|
|
1070
|
-
exclude: [
|
|
1071
|
-
this.outdirs.behavior,
|
|
1072
|
-
this.outdirs.resources
|
|
1073
|
-
],
|
|
1074
|
-
include: [
|
|
1075
|
-
this.srcDirs.behavior
|
|
1076
|
-
]
|
|
1077
|
-
}));
|
|
1078
|
-
}
|
|
1079
1413
|
if (this.currentConfig.script?.lang == 'mcx') {
|
|
1080
1414
|
try {
|
|
1081
1415
|
const tsconfigPath = path.join(this.baseBuildDir, 'tsconfig.json');
|
|
@@ -1087,38 +1421,50 @@ class Build {
|
|
|
1087
1421
|
tsconfigPath: tsconfigPath,
|
|
1088
1422
|
sourcemap: false,
|
|
1089
1423
|
ts: this.mcxTs,
|
|
1090
|
-
mcxLanguagePlugin: this.mcxLanguagePluginCreator
|
|
1091
1424
|
};
|
|
1092
1425
|
if (this.mcxLanguagePluginCreator) {
|
|
1093
1426
|
pluginConfig.mcxLanguagePlugin = this.mcxLanguagePluginCreator;
|
|
1094
1427
|
}
|
|
1095
|
-
plugin.push(mcxDef__namespace.
|
|
1428
|
+
plugin.push(mcxDef__namespace.rolldownPlugin(pluginConfig, this.outdirs));
|
|
1096
1429
|
}
|
|
1097
1430
|
catch (err) {
|
|
1098
|
-
throw new Error(`[build addon]: mcx plugin is required but '@mbler/mcx-core' could not be loaded: ${err}
|
|
1431
|
+
throw new Error(`[build addon]: mcx plugin is required but '@mbler/mcx-core' could not be loaded: ${err}`, { cause: err });
|
|
1099
1432
|
}
|
|
1100
1433
|
}
|
|
1101
1434
|
// save plugin array for watcher re-use
|
|
1102
1435
|
this.rollupPlugin = plugin;
|
|
1103
1436
|
const rollupOption = {
|
|
1104
1437
|
input: main,
|
|
1105
|
-
external: [
|
|
1438
|
+
external: [
|
|
1439
|
+
'@minecraft/server',
|
|
1440
|
+
'@minecraft/server-ui',
|
|
1441
|
+
...(this.buildConfig?.rollupExternal ?? []),
|
|
1442
|
+
],
|
|
1106
1443
|
plugins: plugin,
|
|
1107
|
-
|
|
1444
|
+
experimental: {
|
|
1445
|
+
...(this.cacheManager?.shouldUseIncrementalBuild()
|
|
1446
|
+
? { incrementalBuild: true }
|
|
1447
|
+
: {}),
|
|
1448
|
+
},
|
|
1108
1449
|
};
|
|
1109
|
-
if (this.buildConfig?.onWarn)
|
|
1110
|
-
|
|
1111
|
-
|
|
1450
|
+
if (this.buildConfig?.onWarn) {
|
|
1451
|
+
const onWarn = (warning, _defaultHandler) => {
|
|
1452
|
+
const msg = typeof warning === 'string'
|
|
1453
|
+
? warning
|
|
1454
|
+
: warning.message || 'Unknown warning';
|
|
1455
|
+
this.buildConfig?.onWarn?.(this.currentConfig, new Error(msg));
|
|
1112
1456
|
};
|
|
1457
|
+
rollupOption.onwarn = onWarn;
|
|
1458
|
+
}
|
|
1113
1459
|
if (this.buildConfig?.onEnd) {
|
|
1114
1460
|
plugin.push({
|
|
1115
1461
|
name: 'build-end-plugin',
|
|
1116
1462
|
buildEnd: () => {
|
|
1117
1463
|
return this.buildConfig?.onEnd?.(this.currentConfig);
|
|
1118
|
-
}
|
|
1464
|
+
},
|
|
1119
1465
|
});
|
|
1120
1466
|
}
|
|
1121
|
-
return await
|
|
1467
|
+
return await rolldown.rolldown(rollupOption);
|
|
1122
1468
|
}
|
|
1123
1469
|
/**
|
|
1124
1470
|
* Internal helper invoked by {@link watch}.
|
|
@@ -1129,7 +1475,7 @@ class Build {
|
|
|
1129
1475
|
if (!this.init) {
|
|
1130
1476
|
await this.build();
|
|
1131
1477
|
}
|
|
1132
|
-
this.createWatcher();
|
|
1478
|
+
await this.createWatcher();
|
|
1133
1479
|
// watchers field is populated by createWatcher
|
|
1134
1480
|
}
|
|
1135
1481
|
isParent(parent, dir) {
|
|
@@ -1152,7 +1498,7 @@ class Build {
|
|
|
1152
1498
|
}
|
|
1153
1499
|
return false;
|
|
1154
1500
|
}
|
|
1155
|
-
createRollupWatcher() {
|
|
1501
|
+
async createRollupWatcher() {
|
|
1156
1502
|
if (!this.srcDirs ||
|
|
1157
1503
|
!this.outdirs ||
|
|
1158
1504
|
!this.currentConfig ||
|
|
@@ -1160,24 +1506,31 @@ class Build {
|
|
|
1160
1506
|
throw new Error(`[build addon]: can't first can this method`);
|
|
1161
1507
|
let output = this.currentConfig.script?.main;
|
|
1162
1508
|
if (!output)
|
|
1163
|
-
output =
|
|
1164
|
-
if (path.extname(output) !==
|
|
1165
|
-
output =
|
|
1166
|
-
|
|
1509
|
+
output = 'index.js';
|
|
1510
|
+
if (path.extname(output) !== 'js')
|
|
1511
|
+
output =
|
|
1512
|
+
output.slice(0, output.length - path.extname(output).length) + '.js';
|
|
1513
|
+
if (this.buildConfig?.outputFilename)
|
|
1514
|
+
output = this.buildConfig.outputFilename;
|
|
1515
|
+
const outputDir = this.buildConfig?.outputDir || 'scripts';
|
|
1516
|
+
const rollupWatcher = rolldown.watch({
|
|
1167
1517
|
input: path.join(this.srcDirs.behavior, 'scripts', this.currentConfig?.script?.main || ''),
|
|
1168
|
-
external: [
|
|
1518
|
+
external: [
|
|
1519
|
+
'@minecraft/server',
|
|
1520
|
+
'@minecraft/server-ui',
|
|
1521
|
+
...(this.buildConfig?.rollupExternal ?? []),
|
|
1522
|
+
],
|
|
1169
1523
|
plugins: this.rollupPlugin,
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
}
|
|
1175
|
-
|
|
1524
|
+
experimental: {
|
|
1525
|
+
...(this.cacheManager?.shouldUseIncrementalBuild()
|
|
1526
|
+
? { incrementalBuild: true }
|
|
1527
|
+
: {}),
|
|
1528
|
+
},
|
|
1529
|
+
output: {
|
|
1530
|
+
file: join(path.join(this.outdirs.behavior, outputDir), output),
|
|
1176
1531
|
format: 'esm',
|
|
1177
|
-
chunkFileNames: '[name].js',
|
|
1178
1532
|
sourcemap: false,
|
|
1179
1533
|
},
|
|
1180
|
-
cache: this.cacheManager?.getWatchCacheOption() ?? true,
|
|
1181
1534
|
watch: {
|
|
1182
1535
|
clearScreen: false,
|
|
1183
1536
|
include: path.join(this.srcDirs.behavior, 'scripts/**/*'),
|
|
@@ -1203,28 +1556,32 @@ class Build {
|
|
|
1203
1556
|
else if (event.code === 'END') {
|
|
1204
1557
|
Logger.i('Watcher', `rebuild success`);
|
|
1205
1558
|
}
|
|
1206
|
-
else if (event.code === 'BUNDLE_END')
|
|
1207
|
-
await this.cacheManager?.saveRollupCache(event.result?.cache);
|
|
1208
|
-
}
|
|
1559
|
+
else if (event.code === 'BUNDLE_END') ;
|
|
1209
1560
|
});
|
|
1210
1561
|
return rollupWatcher;
|
|
1211
1562
|
}
|
|
1212
1563
|
async onChange(filePath) {
|
|
1564
|
+
const isBundle = this.currentConfig?.build?.bundle !== false;
|
|
1213
1565
|
if (!this.srcDirs ||
|
|
1214
1566
|
!this.outdirs ||
|
|
1215
1567
|
!this.currentConfig ||
|
|
1216
|
-
!this.rollupPlugin ||
|
|
1568
|
+
(isBundle && !this.rollupPlugin) ||
|
|
1217
1569
|
!this.watchers)
|
|
1218
1570
|
throw new Error(`[build addon]: can't first can this method`);
|
|
1219
|
-
const isConfigChange = path.relative(path.join(this.baseBuildDir,
|
|
1220
|
-
const
|
|
1571
|
+
const isConfigChange = path.relative(path.join(this.baseBuildDir, BuildConfig.ConfigFile), filePath) === '';
|
|
1572
|
+
const isPkgChange = path.relative(path.join(this.baseBuildDir, 'package.json'), filePath) ===
|
|
1573
|
+
'';
|
|
1574
|
+
const isScriptsChange = !isBundle &&
|
|
1575
|
+
this.isParent(path.join(this.srcDirs.behavior, 'scripts'), filePath);
|
|
1576
|
+
const isBehaviorChange = this.isParent(this.srcDirs.behavior, filePath) &&
|
|
1577
|
+
!this.isParent(path.join(this.srcDirs.behavior, 'scripts'), filePath);
|
|
1221
1578
|
const isResourcesChange = this.isParent(this.srcDirs.resources, filePath);
|
|
1222
|
-
if (isConfigChange) {
|
|
1579
|
+
if (isConfigChange || isPkgChange) {
|
|
1223
1580
|
const oldConfig = this.currentConfig;
|
|
1224
|
-
Logger.i('Watcher', 'detected
|
|
1581
|
+
Logger.i('Watcher', 'detected config change, reload config');
|
|
1225
1582
|
this.currentConfig = await ReadProjectMblerConfig(this.baseBuildDir);
|
|
1226
1583
|
this.buildConfig = this.currentConfig.build || null;
|
|
1227
|
-
this.cacheManager = new BuildCacheManager(this.baseBuildDir, this.buildConfig?.cache, this.isWatch);
|
|
1584
|
+
this.cacheManager = new BuildCacheManager(this.baseBuildDir, this.buildConfig?.cache, this.isWatch, this.buildConfig?.cachePath);
|
|
1228
1585
|
this.loadData();
|
|
1229
1586
|
if (this.isChange(oldConfig, this.currentConfig, [
|
|
1230
1587
|
'name',
|
|
@@ -1234,12 +1591,31 @@ class Build {
|
|
|
1234
1591
|
])) {
|
|
1235
1592
|
await this.handlerManifest();
|
|
1236
1593
|
}
|
|
1237
|
-
if (this.isChange(oldConfig, this.currentConfig, ['script', 'outdir'])) {
|
|
1238
|
-
this.
|
|
1239
|
-
|
|
1240
|
-
|
|
1594
|
+
if (this.isChange(oldConfig, this.currentConfig, ['script', 'outdir', 'build'])) {
|
|
1595
|
+
const newIsBundle = this.currentConfig.build?.bundle !== false;
|
|
1596
|
+
if (newIsBundle && this.watchers.rollup) {
|
|
1597
|
+
this.watchers.rollup.close();
|
|
1598
|
+
await this.createRollup();
|
|
1599
|
+
this.watchers.rollup = await this.createRollupWatcher();
|
|
1600
|
+
}
|
|
1601
|
+
else if (newIsBundle) {
|
|
1602
|
+
await this.createRollup();
|
|
1603
|
+
this.watchers.rollup = await this.createRollupWatcher();
|
|
1604
|
+
}
|
|
1605
|
+
else {
|
|
1606
|
+
if (this.watchers.rollup) {
|
|
1607
|
+
this.watchers.rollup.close();
|
|
1608
|
+
}
|
|
1609
|
+
this.watchers.rollup = null;
|
|
1610
|
+
}
|
|
1241
1611
|
}
|
|
1242
1612
|
}
|
|
1613
|
+
// if bundle: false and a script file changed, copy it directly
|
|
1614
|
+
if (isScriptsChange) {
|
|
1615
|
+
const outputDir = this.buildConfig?.outputDir || 'scripts';
|
|
1616
|
+
const relativePath = path.relative(path.join(this.srcDirs.behavior, 'scripts'), filePath);
|
|
1617
|
+
await fs__namespace.cp(filePath, path.join(this.outdirs.behavior, outputDir, relativePath), { recursive: true, force: true });
|
|
1618
|
+
}
|
|
1243
1619
|
// if behavior or resources change, we can just copy the changed file instead of copy all files again.
|
|
1244
1620
|
if (isBehaviorChange || isResourcesChange) {
|
|
1245
1621
|
const handlerBP = async () => {
|
|
@@ -1269,8 +1645,9 @@ class Build {
|
|
|
1269
1645
|
}
|
|
1270
1646
|
showText(`[${chalk.green('mbler')}] ${chalk.bgYellow(`file changed: ${filePath}`)}`);
|
|
1271
1647
|
}
|
|
1272
|
-
createWatcher() {
|
|
1273
|
-
|
|
1648
|
+
async createWatcher() {
|
|
1649
|
+
const isBundle = this.currentConfig?.build?.bundle !== false;
|
|
1650
|
+
if (!this.srcDirs || !this.outdirs || (isBundle && !this.rollupPlugin))
|
|
1274
1651
|
throw new Error(`[build addon]: can't first can this method`);
|
|
1275
1652
|
const chokidar$1 = chokidar.watch(this.baseBuildDir, {
|
|
1276
1653
|
ignored: [
|
|
@@ -1286,11 +1663,19 @@ class Build {
|
|
|
1286
1663
|
await this.onChange(filePath);
|
|
1287
1664
|
};
|
|
1288
1665
|
chokidar$1.on('change', onChange);
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1666
|
+
if (isBundle && this.currentConfig?.script) {
|
|
1667
|
+
const rollupWatcher = await this.createRollupWatcher();
|
|
1668
|
+
this.watchers = {
|
|
1669
|
+
chokidar: chokidar$1,
|
|
1670
|
+
rollup: rollupWatcher,
|
|
1671
|
+
};
|
|
1672
|
+
}
|
|
1673
|
+
else {
|
|
1674
|
+
this.watchers = {
|
|
1675
|
+
chokidar: chokidar$1,
|
|
1676
|
+
rollup: null,
|
|
1677
|
+
};
|
|
1678
|
+
}
|
|
1294
1679
|
}
|
|
1295
1680
|
async handlerManifest() {
|
|
1296
1681
|
if (!this.currentConfig || !this.outdirs || !this.srcDirs || !this.module)
|
|
@@ -1325,7 +1710,7 @@ class Build {
|
|
|
1325
1710
|
const json = JSON.parse(content);
|
|
1326
1711
|
otherManifestOption.behavior = json;
|
|
1327
1712
|
}
|
|
1328
|
-
catch (
|
|
1713
|
+
catch (_err) {
|
|
1329
1714
|
Logger.w('Build', 'invalid manifest.json in behavior');
|
|
1330
1715
|
}
|
|
1331
1716
|
}
|
|
@@ -1339,7 +1724,7 @@ class Build {
|
|
|
1339
1724
|
const json = JSON.parse(content);
|
|
1340
1725
|
otherManifestOption.resources = json;
|
|
1341
1726
|
}
|
|
1342
|
-
catch (
|
|
1727
|
+
catch (_err) {
|
|
1343
1728
|
Logger.w('Build', 'invalid manifest.json in resources');
|
|
1344
1729
|
}
|
|
1345
1730
|
}
|
|
@@ -1467,6 +1852,7 @@ function watch(cliParam, work) {
|
|
|
1467
1852
|
|
|
1468
1853
|
exports.Build = Build;
|
|
1469
1854
|
exports.McxTsc = runTSC;
|
|
1855
|
+
exports.Sapi = Sapi$1;
|
|
1470
1856
|
exports.build = build;
|
|
1471
1857
|
exports.watch = watch;
|
|
1472
1858
|
//# sourceMappingURL=build.js.map
|