hzengine-core 0.1.2-dev → 0.1.3
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/dist/async/index.js +150 -162
- package/dist/audio/index.js +249 -260
- package/dist/config/index.js +57 -57
- package/dist/debug/index.js +9 -8
- package/dist/index.js +108 -103
- package/dist/plugins/basic_command/img.js +247 -249
- package/dist/plugins/basic_command/menu.js +140 -140
- package/dist/plugins/transform/animation.js +430 -440
- package/dist/plugins/transform/hz_anime.js +196 -211
- package/dist/plugins/transform/index.js +94 -93
- package/dist/script/index.js +537 -537
- package/dist/storage/index.js +447 -440
- package/dist/system/index.js +131 -144
- package/dist/ui/index.js +525 -535
- package/package.json +1 -1
- package/src/platform/index.ts +14 -12
- package/src/plugins/transform/animation.ts +1 -1
- package/src/script/index.ts +13 -0
- package/src/storage/index.ts +47 -47
- package/tsconfig.json +1 -1
- package/types/platform/index.d.ts +137 -134
- package/types/script/index.d.ts +129 -123
- package/types/script/strtools.d.ts +31 -31
package/dist/storage/index.js
CHANGED
|
@@ -1,442 +1,449 @@
|
|
|
1
|
-
// import * as this._core.platform from "@zos/fs";
|
|
2
|
-
import Path from "../utils/path.js";
|
|
3
|
-
// import { isFileSync } from "./fs.js";
|
|
4
|
-
export class Storage {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
this.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
this.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
this.
|
|
30
|
-
this.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (!this.
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
get
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
saveGlobalData() {
|
|
117
|
-
if (!this.projectRoot) {
|
|
118
|
-
throw "projectDir is null, please loadProject first";
|
|
119
|
-
}
|
|
120
|
-
if (this._saveGlobalDataTimerId)
|
|
121
|
-
return;
|
|
122
|
-
this._saveGlobalDataTimerId = setTimeout(() => {
|
|
123
|
-
this._saveGlobalDataTimerId = null;
|
|
124
|
-
if (!this.projectRoot) {
|
|
125
|
-
throw "projectDir is null, please loadProject first";
|
|
126
|
-
}
|
|
127
|
-
this._core.emit("beforeSaveGlobalData");
|
|
128
|
-
let res = this._core.platform.writeFileSync({
|
|
129
|
-
path: Path.join(this.saveRoot, "globalData.json"),
|
|
130
|
-
data: JSON.stringify(this._globalData),
|
|
131
|
-
}); // TODO
|
|
132
|
-
if (res < 0)
|
|
133
|
-
throw `[HZEngine] save globalData to globalData.json failed, code = ${res}`;
|
|
134
|
-
this._core.debug.log(`save globalData to globalData.json`);
|
|
135
|
-
this._core.emit("afterSaveGlobalData");
|
|
136
|
-
}, 0);
|
|
137
|
-
}
|
|
138
|
-
loadArchiveData(archiveFile) {
|
|
139
|
-
this._core.emit("beforeLoadArchive");
|
|
140
|
-
if (archiveFile) {
|
|
141
|
-
if (!this.saveRoot)
|
|
142
|
-
throw `saveRoot is null, please loadProject first`;
|
|
143
|
-
if (!this._core.platform.statSync({
|
|
144
|
-
path: Path.join(this.saveRoot, archiveFile),
|
|
145
|
-
})) {
|
|
146
|
-
throw `Archive [${archiveFile}] not exist`;
|
|
147
|
-
}
|
|
148
|
-
let archiveData = JSON.parse(this._core.platform.readFileSync({
|
|
149
|
-
path: Path.join(this.saveRoot, archiveFile),
|
|
150
|
-
options: {
|
|
151
|
-
encoding: "utf8",
|
|
152
|
-
},
|
|
153
|
-
}));
|
|
154
|
-
if (archiveData == null)
|
|
155
|
-
throw `[HZEngine] ArchiveData is null`;
|
|
156
|
-
this._archiveData = archiveData;
|
|
157
|
-
this._core.debug.log(`load archiveData from ${archiveFile}`);
|
|
158
|
-
this._core.emit("afterLoadArchive");
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
this._core.debug.log(`load archiveData from empty template`);
|
|
162
|
-
this._archiveData = {};
|
|
163
|
-
this._core.emit("initArchiveData");
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
this._core.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
this._core.
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
this._saveArchiveDataTimerId
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
//
|
|
225
|
-
//
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
this.
|
|
276
|
-
this.
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
//
|
|
284
|
-
//
|
|
285
|
-
//
|
|
286
|
-
//
|
|
287
|
-
//
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
*
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
//
|
|
296
|
-
//
|
|
297
|
-
|
|
298
|
-
let
|
|
299
|
-
let
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
//
|
|
309
|
-
//
|
|
310
|
-
// let
|
|
311
|
-
//
|
|
312
|
-
//
|
|
313
|
-
// let
|
|
314
|
-
let contentStr =
|
|
315
|
-
let
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
1
|
+
// import * as this._core.platform from "@zos/fs";
|
|
2
|
+
import Path from "../utils/path.js";
|
|
3
|
+
// import { isFileSync } from "./fs.js";
|
|
4
|
+
export class Storage {
|
|
5
|
+
_core;
|
|
6
|
+
constructor(_core) {
|
|
7
|
+
this._core = _core;
|
|
8
|
+
}
|
|
9
|
+
projectRoot = null;
|
|
10
|
+
cacheRoot = null;
|
|
11
|
+
saveRoot = null;
|
|
12
|
+
preloadedData = null;
|
|
13
|
+
packageData = null;
|
|
14
|
+
loadProject(options) {
|
|
15
|
+
this._core.emit("beforeLoadProject");
|
|
16
|
+
if (!this._core.platform.readdirSync({ path: options.projectPath })) {
|
|
17
|
+
throw "Dir not exist";
|
|
18
|
+
}
|
|
19
|
+
this.projectRoot = options.projectPath;
|
|
20
|
+
this.cacheRoot = options.cachePath;
|
|
21
|
+
this.saveRoot = options.savePath;
|
|
22
|
+
this.loadPackageData();
|
|
23
|
+
this.preload();
|
|
24
|
+
this._core.emit("afterLoadProject");
|
|
25
|
+
}
|
|
26
|
+
loadPackageData() {
|
|
27
|
+
if (!this.projectRoot)
|
|
28
|
+
throw "projectDir is null";
|
|
29
|
+
this._core.debug.log(`loadPackageData ${this.projectRoot} ${Path.join(this.projectRoot, "hz_package.json")}`);
|
|
30
|
+
if (!this._core.platform.statSync({
|
|
31
|
+
path: Path.join(this.projectRoot, "hz_package.json"),
|
|
32
|
+
})) {
|
|
33
|
+
throw "HZEngine Package File (hz_package.json) not exist";
|
|
34
|
+
}
|
|
35
|
+
this.packageData = JSON.parse(this._core.platform.readFileSync({
|
|
36
|
+
path: Path.join(this.projectRoot, "hz_package.json"),
|
|
37
|
+
options: { encoding: "utf8" },
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
// Storage Data
|
|
41
|
+
/**
|
|
42
|
+
* 全局数据
|
|
43
|
+
* 其中的数据不会跟随存档保存,而是直接存储在全局数据文件中
|
|
44
|
+
* 如:设置、CG解锁情况等
|
|
45
|
+
*/
|
|
46
|
+
_globalData = null;
|
|
47
|
+
get globalData() {
|
|
48
|
+
if (!this._globalData) {
|
|
49
|
+
this.loadGlobalData();
|
|
50
|
+
}
|
|
51
|
+
if (this._globalData == null)
|
|
52
|
+
throw `[HZEngine] GlobalData is null`;
|
|
53
|
+
return this._globalData;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* alias globalData
|
|
57
|
+
*/
|
|
58
|
+
get gd() {
|
|
59
|
+
return this.globalData;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* 存档数据
|
|
63
|
+
* 其中的数据会跟随存档保存
|
|
64
|
+
* 如:脚本执行位置即调用栈,攻略度等
|
|
65
|
+
*/
|
|
66
|
+
_archiveData = null;
|
|
67
|
+
get archiveData() {
|
|
68
|
+
if (!this._archiveData) {
|
|
69
|
+
this.loadArchiveData();
|
|
70
|
+
}
|
|
71
|
+
if (this._archiveData == null)
|
|
72
|
+
throw `[HZEngine] ArchiveData is null`;
|
|
73
|
+
return this._archiveData;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* alias archiveData
|
|
77
|
+
*/
|
|
78
|
+
get sd() {
|
|
79
|
+
return this.archiveData;
|
|
80
|
+
}
|
|
81
|
+
loadGlobalData() {
|
|
82
|
+
if (!this.saveRoot) {
|
|
83
|
+
throw "saveDir is null, please loadProject first";
|
|
84
|
+
}
|
|
85
|
+
this._core.emit("beforeLoadGlobalData");
|
|
86
|
+
if (this._core.platform.statSync({
|
|
87
|
+
path: Path.join(this.saveRoot, "globalData.json"),
|
|
88
|
+
})) {
|
|
89
|
+
this._globalData = JSON.parse(this._core.platform.readFileSync({
|
|
90
|
+
path: Path.join(this.saveRoot, "globalData.json"),
|
|
91
|
+
options: {
|
|
92
|
+
encoding: "utf8",
|
|
93
|
+
},
|
|
94
|
+
}));
|
|
95
|
+
if (this._globalData == null) {
|
|
96
|
+
this._globalData = {}; // TODO initial GlobalData value
|
|
97
|
+
this._core.emit("initGlobalData");
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
this._core.debug.log(`globalData.json not exist, create it.`);
|
|
102
|
+
this._globalData = {}; // Initial GlobalData value
|
|
103
|
+
this._core.emit("initGlobalData");
|
|
104
|
+
this._core.platform.writeFileSync({
|
|
105
|
+
path: Path.join(this.saveRoot, "globalData.json"),
|
|
106
|
+
data: JSON.stringify(this._globalData),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
this._core.emit("afterLoadGlobalData");
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* 保存全局数据
|
|
113
|
+
* 可以多次調用,實際上會異步儲存,也就是在一個宏任務中即使調用多次,也只會在宏任務結束後儲存一次
|
|
114
|
+
*/
|
|
115
|
+
_saveGlobalDataTimerId = null;
|
|
116
|
+
saveGlobalData() {
|
|
117
|
+
if (!this.projectRoot) {
|
|
118
|
+
throw "projectDir is null, please loadProject first";
|
|
119
|
+
}
|
|
120
|
+
if (this._saveGlobalDataTimerId)
|
|
121
|
+
return;
|
|
122
|
+
this._saveGlobalDataTimerId = setTimeout(() => {
|
|
123
|
+
this._saveGlobalDataTimerId = null;
|
|
124
|
+
if (!this.projectRoot) {
|
|
125
|
+
throw "projectDir is null, please loadProject first";
|
|
126
|
+
}
|
|
127
|
+
this._core.emit("beforeSaveGlobalData");
|
|
128
|
+
let res = this._core.platform.writeFileSync({
|
|
129
|
+
path: Path.join(this.saveRoot, "globalData.json"),
|
|
130
|
+
data: JSON.stringify(this._globalData),
|
|
131
|
+
}); // TODO
|
|
132
|
+
if (res < 0)
|
|
133
|
+
throw `[HZEngine] save globalData to globalData.json failed, code = ${res}`;
|
|
134
|
+
this._core.debug.log(`save globalData to globalData.json`);
|
|
135
|
+
this._core.emit("afterSaveGlobalData");
|
|
136
|
+
}, 0);
|
|
137
|
+
}
|
|
138
|
+
loadArchiveData(archiveFile) {
|
|
139
|
+
this._core.emit("beforeLoadArchive");
|
|
140
|
+
if (archiveFile) {
|
|
141
|
+
if (!this.saveRoot)
|
|
142
|
+
throw `saveRoot is null, please loadProject first`;
|
|
143
|
+
if (!this._core.platform.statSync({
|
|
144
|
+
path: Path.join(this.saveRoot, archiveFile),
|
|
145
|
+
})) {
|
|
146
|
+
throw `Archive [${archiveFile}] not exist`;
|
|
147
|
+
}
|
|
148
|
+
let archiveData = JSON.parse(this._core.platform.readFileSync({
|
|
149
|
+
path: Path.join(this.saveRoot, archiveFile),
|
|
150
|
+
options: {
|
|
151
|
+
encoding: "utf8",
|
|
152
|
+
},
|
|
153
|
+
}));
|
|
154
|
+
if (archiveData == null)
|
|
155
|
+
throw `[HZEngine] ArchiveData is null`;
|
|
156
|
+
this._archiveData = archiveData;
|
|
157
|
+
this._core.debug.log(`load archiveData from ${archiveFile}`);
|
|
158
|
+
this._core.emit("afterLoadArchive");
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
this._core.debug.log(`load archiveData from empty template`);
|
|
162
|
+
this._archiveData = {};
|
|
163
|
+
this._core.emit("initArchiveData");
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
_saveArchiveDataTimerId = null;
|
|
167
|
+
/**
|
|
168
|
+
* 保存存档数据
|
|
169
|
+
* 可以多次調用,實際上會異步儲存,也就是在一個宏任務中即使調用多次,也只會在宏任務結束後儲存一次
|
|
170
|
+
* @param archiveFile 存档文件目錄及名字
|
|
171
|
+
*/
|
|
172
|
+
saveArchiveData(archiveFile, immediate = false) {
|
|
173
|
+
if (!this.saveRoot)
|
|
174
|
+
throw `saveRoot is null, please loadProject first`;
|
|
175
|
+
this._core.emit("beforeSaveArchive");
|
|
176
|
+
this._core.debug.log("Will save archiveData to " + archiveFile);
|
|
177
|
+
let saveFunc = () => {
|
|
178
|
+
this._core.debug.log("Saving archiveData to " + archiveFile);
|
|
179
|
+
if (!this.saveRoot)
|
|
180
|
+
throw `projectDir is null, please loadProject first`;
|
|
181
|
+
let res = this._core.platform.writeFileSync({
|
|
182
|
+
path: Path.join(this.saveRoot, archiveFile),
|
|
183
|
+
data: JSON.stringify(this._archiveData),
|
|
184
|
+
}); //TODO
|
|
185
|
+
if (res < 0)
|
|
186
|
+
throw `[HZEngine] save archiveData to ${archiveFile} failed, code = ${res}`;
|
|
187
|
+
this._core.debug.log(`Save archiveData to ${archiveFile}`);
|
|
188
|
+
this._core.emit("afterSaveArchive");
|
|
189
|
+
};
|
|
190
|
+
if (immediate) {
|
|
191
|
+
saveFunc();
|
|
192
|
+
if (this._saveArchiveDataTimerId) {
|
|
193
|
+
clearTimeout(this._saveArchiveDataTimerId);
|
|
194
|
+
this._saveArchiveDataTimerId = null;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
else
|
|
198
|
+
this._saveArchiveDataTimerId = setTimeout(() => {
|
|
199
|
+
this._saveArchiveDataTimerId = null;
|
|
200
|
+
saveFunc();
|
|
201
|
+
}, 0);
|
|
202
|
+
}
|
|
203
|
+
getSaveableData(data, auto_correct, ...key_chain) {
|
|
204
|
+
let obj = data;
|
|
205
|
+
// if(obj == null) throw `[HZEngine] saveable data is null`
|
|
206
|
+
for (let key of key_chain) {
|
|
207
|
+
if (obj == null)
|
|
208
|
+
throw Error(`[HZEngine] saveable data is null`);
|
|
209
|
+
if (typeof obj !== "object")
|
|
210
|
+
throw Error(`[HZEngine] saveable data is not object`);
|
|
211
|
+
if (Array.isArray(obj))
|
|
212
|
+
throw Error(`[HZEngine] saveable data is array`);
|
|
213
|
+
if (!obj[key]) {
|
|
214
|
+
if (auto_correct) {
|
|
215
|
+
obj[key] = {};
|
|
216
|
+
}
|
|
217
|
+
else
|
|
218
|
+
throw Error(`[HZEngine] saveable data key ${key} not exist`);
|
|
219
|
+
}
|
|
220
|
+
obj = obj[key];
|
|
221
|
+
}
|
|
222
|
+
if (obj == null)
|
|
223
|
+
throw Error(`[HZEngine] saveable data result obj is null`);
|
|
224
|
+
// if (typeof obj !== "object")
|
|
225
|
+
// throw Error(`[HZEngine] saveable data result obj is not array or object`);
|
|
226
|
+
// if (Array.isArray(obj)) throw Error(`[HZEngine] saveable data result is an array, key_chain = ${key_chain.join(".")}, res = ${JSON.stringify(obj)}`);
|
|
227
|
+
return obj;
|
|
228
|
+
}
|
|
229
|
+
setSaveableData(data, auto_correct, value, ...key_chain) {
|
|
230
|
+
this._core.debug.log(`setSaveableData ${key_chain} => ${JSON.stringify(value)}`);
|
|
231
|
+
if (key_chain.length == 0)
|
|
232
|
+
throw `key_chain is empty`;
|
|
233
|
+
let parentObj = this.getSaveableData(data, auto_correct, ...key_chain.slice(0, -1));
|
|
234
|
+
if (parentObj == null)
|
|
235
|
+
throw `[HZEngine] saveable data is null`;
|
|
236
|
+
if (typeof parentObj !== "object")
|
|
237
|
+
throw `[HZEngine] saveable data is not object`;
|
|
238
|
+
if (Array.isArray(parentObj))
|
|
239
|
+
throw `[HZEngine] saveable data is array`;
|
|
240
|
+
parentObj[key_chain[key_chain.length - 1]] = value;
|
|
241
|
+
}
|
|
242
|
+
checkSaveableData(data, ...key_chain) {
|
|
243
|
+
return this.getSaveableData(data, false, ...key_chain);
|
|
244
|
+
}
|
|
245
|
+
// Preload
|
|
246
|
+
preload() {
|
|
247
|
+
if (!this.cacheRoot) {
|
|
248
|
+
throw "cacheRoot is null, please loadProject first";
|
|
249
|
+
}
|
|
250
|
+
// writeFileSync({path: "data://test.json", data: "awa", options: {encoding: "utf8"}});
|
|
251
|
+
if (this._core.platform.statSync({
|
|
252
|
+
path: Path.join(this.cacheRoot, "preloaded.json"),
|
|
253
|
+
})) {
|
|
254
|
+
// 已经预加载过了,退出
|
|
255
|
+
this.preloadedData = JSON.parse(this._core.platform.readFileSync({
|
|
256
|
+
path: Path.join(this.cacheRoot, "preloaded.json"),
|
|
257
|
+
options: {
|
|
258
|
+
encoding: "utf8",
|
|
259
|
+
},
|
|
260
|
+
}));
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
this.preloadedData = {
|
|
264
|
+
script: {
|
|
265
|
+
labelMap: {},
|
|
266
|
+
hzsInfoMap: {},
|
|
267
|
+
},
|
|
268
|
+
image: {
|
|
269
|
+
nameMap: {},
|
|
270
|
+
},
|
|
271
|
+
animation: {
|
|
272
|
+
profileMap: {},
|
|
273
|
+
},
|
|
274
|
+
};
|
|
275
|
+
this.preloadScript();
|
|
276
|
+
this.preloadImage();
|
|
277
|
+
this.preloadAnimation();
|
|
278
|
+
// console.log(JSON.stringify(this.preloadedData));
|
|
279
|
+
this._core.platform.writeFileSync({
|
|
280
|
+
path: Path.join(this.cacheRoot, "preloaded.json"),
|
|
281
|
+
data: JSON.stringify(this.preloadedData),
|
|
282
|
+
});
|
|
283
|
+
// console.log(
|
|
284
|
+
// `${Path.join(this.projectDir, "preloaded.json")} = ${readFileSync({
|
|
285
|
+
// path: Path.join(this.projectDir, "preloaded.json"),
|
|
286
|
+
// options:{encoding:"utf8"}
|
|
287
|
+
// })}`
|
|
288
|
+
// );
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* 预加载脚本
|
|
292
|
+
* 遍历出所有hzs文件和所有label,建立map
|
|
293
|
+
*/
|
|
294
|
+
preloadScript() {
|
|
295
|
+
// TODO
|
|
296
|
+
// 记录脚本label的位置
|
|
297
|
+
// 这里的index是以0开始计数的行数
|
|
298
|
+
let labelMap = this.preloadedData.script.labelMap;
|
|
299
|
+
let scriptDir = Path.join(this.projectRoot, "script");
|
|
300
|
+
let hzsInfoMap = this.preloadedData.script.hzsInfoMap;
|
|
301
|
+
if (!this._core.platform.readdirSync({ path: scriptDir }))
|
|
302
|
+
throw "项目文件夹中script文件夹不存在";
|
|
303
|
+
/**
|
|
304
|
+
* 1. 预加载所有的label并检查冲突
|
|
305
|
+
* 2. 记录所有脚本文件的行数
|
|
306
|
+
*/
|
|
307
|
+
const preloadHzs = (path) => {
|
|
308
|
+
// let fd = this._core.platform.openSync({ path });
|
|
309
|
+
// if (fd < 0) throw "Fd<0";
|
|
310
|
+
// let size = this._core.platform.statSync({ path })!.size;
|
|
311
|
+
// let arrbuf = new ArrayBuffer(size);
|
|
312
|
+
// this._core.platform.readSync({ fd, buffer: arrbuf });
|
|
313
|
+
// let buffer = Buffer.from(arrbuf);
|
|
314
|
+
// let contentStr = buffer.toString();
|
|
315
|
+
let contentStr = this._core.platform.readFileSync({
|
|
316
|
+
path,
|
|
317
|
+
options: { encoding: "utf8" },
|
|
318
|
+
});
|
|
319
|
+
let contentLines = contentStr.split("\n");
|
|
320
|
+
let totalLines = contentLines.length;
|
|
321
|
+
hzsInfoMap[path] = { totalLines };
|
|
322
|
+
for (let i = 0; i < totalLines; ++i) {
|
|
323
|
+
let line = contentLines[i].trim();
|
|
324
|
+
if (line.startsWith("*")) {
|
|
325
|
+
let len = line.length, p = 1, q;
|
|
326
|
+
while (p < len && line.charAt(p) === " ")
|
|
327
|
+
++p;
|
|
328
|
+
if (p === len)
|
|
329
|
+
throw `Lost Label Name at file(${path}) line(${i + 1})`;
|
|
330
|
+
q = p;
|
|
331
|
+
while (q < len && line.charAt(q) !== " ")
|
|
332
|
+
++q;
|
|
333
|
+
// [p, q)
|
|
334
|
+
let label = line.slice(p, q);
|
|
335
|
+
if (labelMap[label]) {
|
|
332
336
|
throw `Label name "${label}" conflict : \
|
|
333
337
|
at [${labelMap[label][0]}(line ${labelMap[label][1]})] \
|
|
334
|
-
[${path}(line ${i + 1})]`;
|
|
335
|
-
}
|
|
336
|
-
labelMap[label] = [path, i];
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
};
|
|
340
|
-
// 遍历所有hzs文件
|
|
341
|
-
const traverseScript = (path) => {
|
|
342
|
-
let dirs = this._core.platform.readdirSync({ path });
|
|
343
|
-
// console.log(dirs);
|
|
344
|
-
for (let dir of dirs) {
|
|
345
|
-
let subpath = Path.join(path, dir);
|
|
346
|
-
if (this._core.platform.isFileSync({ path: subpath })) {
|
|
347
|
-
// 是文件
|
|
348
|
-
if (dir.endsWith(".hzs")) {
|
|
349
|
-
preloadHzs(subpath);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
else {
|
|
353
|
-
// 是目录
|
|
354
|
-
traverseScript(subpath);
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
};
|
|
358
|
-
traverseScript(scriptDir);
|
|
359
|
-
}
|
|
360
|
-
/**
|
|
361
|
-
* 预加载资源
|
|
362
|
-
* 遍历所有png文件,计算对应的name key,建立map
|
|
363
|
-
*/
|
|
364
|
-
preloadImage() {
|
|
365
|
-
let nameMap = this.preloadedData.image.nameMap;
|
|
366
|
-
let imageDir = Path.join(this.projectRoot, "image");
|
|
367
|
-
if (!this._core.platform.readdirSync({ path: imageDir }))
|
|
368
|
-
throw "项目文件夹中image文件夹不存在";
|
|
369
|
-
/**
|
|
370
|
-
* 1. 预加载所有的image并检查冲突
|
|
371
|
-
* 2. 记录所有image的name key和路径
|
|
372
|
-
*/
|
|
373
|
-
function preloadImage(path) {
|
|
374
|
-
let raw_name = Path.parse(path).name;
|
|
375
|
-
let name_key = raw_name
|
|
376
|
-
.trim()
|
|
377
|
-
.replace("_", " ")
|
|
378
|
-
.replace(/ +/, " ")
|
|
379
|
-
.toLowerCase();
|
|
380
|
-
if (nameMap[name_key])
|
|
381
|
-
throw `Image name key conflict [${name_key}], at file [${path}] and [${nameMap[name_key]}]`;
|
|
382
|
-
nameMap[name_key] = [path];
|
|
383
|
-
}
|
|
384
|
-
// 遍历所有hzs文件
|
|
385
|
-
const traverseImage = (path) => {
|
|
386
|
-
let dirs = this._core.platform.readdirSync({ path });
|
|
387
|
-
// console.log(dirs);
|
|
388
|
-
for (let dir of dirs) {
|
|
389
|
-
let subpath = Path.join(path, dir);
|
|
390
|
-
if (this._core.platform.isFileSync({ path: subpath })) {
|
|
391
|
-
// 是文件
|
|
392
|
-
if (dir.endsWith(".png")) {
|
|
393
|
-
preloadImage(subpath);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
else {
|
|
397
|
-
// 是目录
|
|
398
|
-
traverseImage(subpath);
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
};
|
|
402
|
-
traverseImage(imageDir);
|
|
403
|
-
// console.log(
|
|
404
|
-
// `Preloaded image: ${JSON.stringify(this.preloadedData.image.nameMap)}`
|
|
405
|
-
// );
|
|
406
|
-
}
|
|
407
|
-
/**
|
|
408
|
-
* 預加載動畫profile
|
|
409
|
-
* 遍歷animation文件夾下的所有json文件,以文件名為key,json内容為value
|
|
410
|
-
*/
|
|
411
|
-
preloadAnimation() {
|
|
412
|
-
let profileMap = this.preloadedData.animation.profileMap;
|
|
413
|
-
let animationDir = Path.join(this.projectRoot, "animation");
|
|
414
|
-
if (!this._core.platform.readdirSync({ path: animationDir }))
|
|
415
|
-
throw "项目文件夹中animation文件夹不存在";
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
}
|
|
338
|
+
[${path}(line ${i + 1})]`;
|
|
339
|
+
}
|
|
340
|
+
labelMap[label] = [path, i];
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
// 遍历所有hzs文件
|
|
345
|
+
const traverseScript = (path) => {
|
|
346
|
+
let dirs = this._core.platform.readdirSync({ path });
|
|
347
|
+
// console.log(dirs);
|
|
348
|
+
for (let dir of dirs) {
|
|
349
|
+
let subpath = Path.join(path, dir);
|
|
350
|
+
if (this._core.platform.isFileSync({ path: subpath })) {
|
|
351
|
+
// 是文件
|
|
352
|
+
if (dir.endsWith(".hzs")) {
|
|
353
|
+
preloadHzs(subpath);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
// 是目录
|
|
358
|
+
traverseScript(subpath);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
traverseScript(scriptDir);
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* 预加载资源
|
|
366
|
+
* 遍历所有png文件,计算对应的name key,建立map
|
|
367
|
+
*/
|
|
368
|
+
preloadImage() {
|
|
369
|
+
let nameMap = this.preloadedData.image.nameMap;
|
|
370
|
+
let imageDir = Path.join(this.projectRoot, "image");
|
|
371
|
+
if (!this._core.platform.readdirSync({ path: imageDir }))
|
|
372
|
+
throw "项目文件夹中image文件夹不存在";
|
|
373
|
+
/**
|
|
374
|
+
* 1. 预加载所有的image并检查冲突
|
|
375
|
+
* 2. 记录所有image的name key和路径
|
|
376
|
+
*/
|
|
377
|
+
function preloadImage(path) {
|
|
378
|
+
let raw_name = Path.parse(path).name;
|
|
379
|
+
let name_key = raw_name
|
|
380
|
+
.trim()
|
|
381
|
+
.replace("_", " ")
|
|
382
|
+
.replace(/ +/, " ")
|
|
383
|
+
.toLowerCase();
|
|
384
|
+
if (nameMap[name_key])
|
|
385
|
+
throw `Image name key conflict [${name_key}], at file [${path}] and [${nameMap[name_key]}]`;
|
|
386
|
+
nameMap[name_key] = [path];
|
|
387
|
+
}
|
|
388
|
+
// 遍历所有hzs文件
|
|
389
|
+
const traverseImage = (path) => {
|
|
390
|
+
let dirs = this._core.platform.readdirSync({ path });
|
|
391
|
+
// console.log(dirs);
|
|
392
|
+
for (let dir of dirs) {
|
|
393
|
+
let subpath = Path.join(path, dir);
|
|
394
|
+
if (this._core.platform.isFileSync({ path: subpath })) {
|
|
395
|
+
// 是文件
|
|
396
|
+
if (dir.endsWith(".png")) {
|
|
397
|
+
preloadImage(subpath);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
// 是目录
|
|
402
|
+
traverseImage(subpath);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
};
|
|
406
|
+
traverseImage(imageDir);
|
|
407
|
+
// console.log(
|
|
408
|
+
// `Preloaded image: ${JSON.stringify(this.preloadedData.image.nameMap)}`
|
|
409
|
+
// );
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* 預加載動畫profile
|
|
413
|
+
* 遍歷animation文件夾下的所有json文件,以文件名為key,json内容為value
|
|
414
|
+
*/
|
|
415
|
+
preloadAnimation() {
|
|
416
|
+
let profileMap = this.preloadedData.animation.profileMap;
|
|
417
|
+
let animationDir = Path.join(this.projectRoot, "animation");
|
|
418
|
+
if (!this._core.platform.readdirSync({ path: animationDir })) {
|
|
419
|
+
// throw "项目文件夹中animation文件夹不存在";
|
|
420
|
+
console.log("Warning: 项目文件夹中animation文件夹不存在");
|
|
421
|
+
return; // allow project without animation folder
|
|
422
|
+
}
|
|
423
|
+
function preloadAnimation(path) {
|
|
424
|
+
let raw_name = Path.parse(path).name;
|
|
425
|
+
let name_key = raw_name.trim().replace(/ +/, "_");
|
|
426
|
+
if (profileMap[name_key])
|
|
427
|
+
throw `Animation profile name key conflict [${name_key}], at file [${path}] and [${profileMap[name_key]}]`;
|
|
428
|
+
profileMap[name_key] = [path];
|
|
429
|
+
}
|
|
430
|
+
const traverseAnimation = (path) => {
|
|
431
|
+
let dirs = this._core.platform.readdirSync({ path });
|
|
432
|
+
// console.log(dirs);
|
|
433
|
+
for (let dir of dirs) {
|
|
434
|
+
let subpath = Path.join(path, dir);
|
|
435
|
+
if (this._core.platform.isFileSync({ path: subpath })) {
|
|
436
|
+
// 是文件
|
|
437
|
+
if (dir.endsWith(".json")) {
|
|
438
|
+
preloadAnimation(subpath);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
// 是目录
|
|
443
|
+
traverseAnimation(subpath);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
traverseAnimation(animationDir);
|
|
448
|
+
}
|
|
449
|
+
}
|