asajs 4.0.0-indev-1 → 4.0.0-indev-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.
Files changed (43) hide show
  1. package/config.d.ts +26 -0
  2. package/dist/js/compilers/Configuration.js +20 -1
  3. package/dist/js/compilers/Memory.js +1 -3
  4. package/dist/js/compilers/bindings/Checker.js +9 -0
  5. package/dist/js/compilers/bindings/Function.js +71 -0
  6. package/dist/js/compilers/bindings/Funtion.js +30 -6
  7. package/dist/js/compilers/bindings/Lexer.js +49 -6
  8. package/dist/js/compilers/bindings/Parser.js +152 -12
  9. package/dist/js/compilers/ui/buildcache.js +53 -0
  10. package/dist/js/compilers/ui/builddata.js +4 -0
  11. package/dist/js/compilers/ui/builder.js +30 -9
  12. package/dist/js/compilers/ui/installer.js +15 -1
  13. package/dist/js/compilers/ui/linker.js +43 -1
  14. package/dist/js/compilers/ui/manifest.js +25 -1
  15. package/dist/js/compilers/ui/prevdata.js +8 -0
  16. package/dist/js/components/AnimationKeyframe.js +1 -1
  17. package/dist/js/components/UI.js +25 -13
  18. package/dist/js/components/Utils.js +100 -23
  19. package/dist/js/config..js +1 -0
  20. package/dist/js/config.js +1 -0
  21. package/dist/js/index.js +4 -0
  22. package/dist/js/types/config.js +1 -0
  23. package/dist/types/compilers/Configuration.d.ts +5 -1
  24. package/dist/types/compilers/bindings/Checker.d.ts +3 -0
  25. package/dist/types/compilers/bindings/Function.d.ts +7 -0
  26. package/dist/types/compilers/bindings/Funtion.d.ts +1 -1
  27. package/dist/types/compilers/bindings/Parser.d.ts +12 -3
  28. package/dist/types/compilers/ui/buildcache.d.ts +8 -0
  29. package/dist/types/compilers/ui/builddata.d.ts +1 -0
  30. package/dist/types/compilers/ui/installer.d.ts +1 -1
  31. package/dist/types/compilers/ui/linker.d.ts +4 -0
  32. package/dist/types/compilers/ui/manifest.d.ts +1 -1
  33. package/dist/types/compilers/ui/prevdata.d.ts +3 -0
  34. package/dist/types/components/AnimationKeyframe.d.ts +4 -4
  35. package/dist/types/components/UI.d.ts +9 -2
  36. package/dist/types/components/Utils.d.ts +17 -16
  37. package/dist/types/config..d.ts +2 -0
  38. package/dist/types/config.d.ts +13 -0
  39. package/dist/types/index.d.ts +4 -0
  40. package/dist/types/types/config.d.ts +13 -0
  41. package/dist/types/types/enums/index.d.ts +0 -1
  42. package/package.json +1 -1
  43. package/resources/asajs.config.cjs +14 -0
package/config.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { Variable } from "./src/types/properties/value.ts"
2
+
3
+ export interface Config {
4
+ compiler?: {
5
+ enabled?: boolean
6
+ linked?: boolean
7
+ }
8
+ packinfo?: {
9
+ name?: string
10
+ description?: string
11
+ version?: [number, number, number]
12
+
13
+ metadata?: {
14
+ authors?: string[]
15
+ license?: string
16
+ url?: string
17
+ }
18
+
19
+ subpacks?: {
20
+ folder_name?: string
21
+ name?: string
22
+ memory_performance_tier?: number
23
+ }[]
24
+ }
25
+ global_variables?: Record<Variable, string>
26
+ }
@@ -1 +1,20 @@
1
- export const isBuildMode = process.argv.includes("--build");
1
+ import fs from "fs";
2
+ import path from "path";
3
+ if (!fs.existsSync("asajs.config.cjs")) {
4
+ fs.copyFileSync("node_modules/asajs/resources/asajs.config.cjs", "asajs.config.cjs");
5
+ }
6
+ if (!fs.existsSync(".gitignore")) {
7
+ fs.writeFileSync(".gitignore", `node_modules`, "utf-8");
8
+ }
9
+ export const config = require(path.resolve(process.cwd(), "asajs.config.cjs")).config;
10
+ export let isBuildMode = config.compiler?.enabled ?? false;
11
+ export let isLinkMode = config.compiler?.linked ?? false;
12
+ export let unLinked = !(config.compiler?.linked ?? true);
13
+ for (const arg of process.argv) {
14
+ if (arg === "--build")
15
+ isBuildMode = true;
16
+ if (arg === "--link")
17
+ isLinkMode = true;
18
+ else if (arg === "--unlink")
19
+ unLinked = true;
20
+ }
@@ -22,9 +22,7 @@ export class Memory extends Class {
22
22
  const data = new Map();
23
23
  Memory.files.entries().forEach(([path, { elements, namespace }]) => {
24
24
  const record = {};
25
- elements.forEach(element => {
26
- record[element.name] = element;
27
- });
25
+ elements.forEach(element => (record[element.name] = element));
28
26
  data.set(path, {
29
27
  namespace,
30
28
  ...record,
@@ -7,6 +7,15 @@ export function isWordChar(char) {
7
7
  export function isNumberChar(char) {
8
8
  return /\d/.test(char);
9
9
  }
10
+ export function isHexChar(char) {
11
+ return /[0-9a-fA-F]/.test(char);
12
+ }
13
+ export function isBinaryChar(char) {
14
+ return /[01]/.test(char);
15
+ }
16
+ export function isOctalChar(char) {
17
+ return /[0-7]/.test(char);
18
+ }
10
19
  export function isCompileBinding(input) {
11
20
  return input.startsWith("[") && input.endsWith("]");
12
21
  }
@@ -0,0 +1,71 @@
1
+ import { RandomBindingString } from "../../components/Utils.js";
2
+ import { Parser } from "./Parser.js";
3
+ export const FunctionMap = new Map();
4
+ function callFn(name, ...args) {
5
+ return FunctionMap.get(name)(...args);
6
+ }
7
+ // Default Functions
8
+ FunctionMap.set("abs", number => {
9
+ const randomBinding = RandomBindingString(16);
10
+ return {
11
+ genBindings: [{ source: `((-1 + (${number} > 0) * 2) * ${number})`, target: randomBinding }],
12
+ value: randomBinding,
13
+ };
14
+ });
15
+ FunctionMap.set("new", expression => {
16
+ const randomBinding = RandomBindingString(16);
17
+ return {
18
+ genBindings: [{ source: expression, target: randomBinding }],
19
+ value: randomBinding,
20
+ };
21
+ });
22
+ FunctionMap.set("sqrt", number => {
23
+ const rtn = RandomBindingString(16), $1 = RandomBindingString(16), $2 = RandomBindingString(16);
24
+ const { genBindings: absValue, value: absRtn } = callFn("abs", number);
25
+ return {
26
+ genBindings: [
27
+ {
28
+ source: `${number} * 100 / 2`,
29
+ target: $1,
30
+ },
31
+ ...absValue,
32
+ {
33
+ source: `${absRtn} > 1`,
34
+ target: $2,
35
+ },
36
+ {
37
+ source: `(${number} < 0) * -1 + (${number} > -1) * (${$2} * ((${rtn} + ${number} / ${rtn}) / 2) + (not ${$2}) * ${rtn})`,
38
+ target: rtn,
39
+ },
40
+ ],
41
+ value: rtn,
42
+ };
43
+ });
44
+ FunctionMap.set("translatable", key => {
45
+ return {
46
+ value: `'%' + ${key}`,
47
+ };
48
+ });
49
+ FunctionMap.set("bin", input => {
50
+ const { ret, bindings } = Parser.intToBin(input);
51
+ bindings.push({
52
+ source: `'§z' + ${Array.from({ length: 30 }, (_, i) => `${ret}${30 - i - 1}`).join(" + ")}`,
53
+ target: ret,
54
+ });
55
+ return { genBindings: bindings, value: ret };
56
+ });
57
+ FunctionMap.set("bind", (value, bait) => {
58
+ const ret = RandomBindingString(16);
59
+ if (!bait) {
60
+ throw new Error("Bait is required");
61
+ }
62
+ return {
63
+ genBindings: [{ source: `((${bait} - ${bait}) + ${value})`, target: ret }],
64
+ value: ret,
65
+ };
66
+ });
67
+ FunctionMap.set("int", input => {
68
+ return {
69
+ value: input,
70
+ };
71
+ });
@@ -1,24 +1,25 @@
1
1
  import { RandomBindingString } from "../../components/Utils.js";
2
- export const FuntionMap = new Map();
2
+ import { Parser } from "./Parser.js";
3
+ export const FunctionMap = new Map();
3
4
  function callFn(name, ...args) {
4
- return FuntionMap.get(name)(...args);
5
+ return FunctionMap.get(name)(...args);
5
6
  }
6
7
  // Default Functions
7
- FuntionMap.set("abs", number => {
8
+ FunctionMap.set("abs", number => {
8
9
  const randomBinding = RandomBindingString(16);
9
10
  return {
10
11
  genBindings: [{ source: `((-1 + (${number} > 0) * 2) * ${number})`, target: randomBinding }],
11
12
  value: randomBinding,
12
13
  };
13
14
  });
14
- FuntionMap.set("new", expression => {
15
+ FunctionMap.set("new", expression => {
15
16
  const randomBinding = RandomBindingString(16);
16
17
  return {
17
18
  genBindings: [{ source: expression, target: randomBinding }],
18
19
  value: randomBinding,
19
20
  };
20
21
  });
21
- FuntionMap.set("sqrt", number => {
22
+ FunctionMap.set("sqrt", number => {
22
23
  const rtn = RandomBindingString(16), $1 = RandomBindingString(16), $2 = RandomBindingString(16);
23
24
  const { genBindings: absValue, value: absRtn } = callFn("abs", number);
24
25
  return {
@@ -40,8 +41,31 @@ FuntionMap.set("sqrt", number => {
40
41
  value: rtn,
41
42
  };
42
43
  });
43
- FuntionMap.set("translatable", key => {
44
+ FunctionMap.set("translatable", key => {
44
45
  return {
45
46
  value: `'%' + ${key}`,
46
47
  };
47
48
  });
49
+ FunctionMap.set("bin", input => {
50
+ const { ret, bindings } = Parser.intToBin(input);
51
+ bindings.push({
52
+ source: `'§z' + ${Array.from({ length: 30 }, (_, i) => `${ret}${30 - i - 1}`).join(" + ")}`,
53
+ target: ret,
54
+ });
55
+ return { genBindings: bindings, value: ret };
56
+ });
57
+ FunctionMap.set("bind", (value, bait) => {
58
+ const ret = RandomBindingString(16);
59
+ if (!bait) {
60
+ throw new Error("Bait is required");
61
+ }
62
+ return {
63
+ genBindings: [{ source: `((${bait} - ${bait}) + ${value})`, target: ret }],
64
+ value: ret,
65
+ };
66
+ });
67
+ FunctionMap.set("int", input => {
68
+ return {
69
+ value: input,
70
+ };
71
+ });
@@ -39,6 +39,7 @@ export function Lexer(input, start = 0, end) {
39
39
  case "*":
40
40
  case "/":
41
41
  case "%":
42
+ case "^":
42
43
  tokens.push(makeToken(input, TokenKind.OPERATOR, index));
43
44
  break;
44
45
  case "(":
@@ -53,18 +54,24 @@ export function Lexer(input, start = 0, end) {
53
54
  case "=":
54
55
  if (input[index + 1] === input[index])
55
56
  tokens.push(makeToken(input, TokenKind.OPERATOR, index++, 2));
56
- else {
57
- console.error(`\x1b[31merror: ${input + "\n" + " ".repeat(index + 7) + "^"}\nInvalid character.\x1b[0m`);
58
- throw new Error();
59
- }
57
+ else
58
+ tokens.push(makeToken(input, TokenKind.OPERATOR, index));
60
59
  break;
61
60
  case "!":
62
61
  case ">":
63
62
  case "<":
64
63
  if (input[index + 1] === "=")
65
64
  tokens.push(makeToken(input, TokenKind.OPERATOR, index++, 2));
66
- else
67
- tokens.push(makeToken(input, TokenKind.OPERATOR, index));
65
+ else {
66
+ if (input[index] === input[index + 1]) {
67
+ if (input[index] !== "!")
68
+ tokens.push(makeToken(input, TokenKind.OPERATOR, index++, 2));
69
+ else
70
+ tokens.push(makeToken(input, TokenKind.OPERATOR, index));
71
+ }
72
+ else
73
+ tokens.push(makeToken(input, TokenKind.OPERATOR, index));
74
+ }
68
75
  break;
69
76
  // string
70
77
  case "'": {
@@ -168,6 +175,42 @@ export function Lexer(input, start = 0, end) {
168
175
  default: {
169
176
  let start = index;
170
177
  if (Checker.isNumberChar(token)) {
178
+ if (token === "0") {
179
+ const numType = input[index + 1];
180
+ if (numType === "x") {
181
+ index += 2;
182
+ while (Checker.isHexChar(input[index + 1]))
183
+ index++;
184
+ if (start + 2 === index) {
185
+ console.error(`\x1b[31merror: ${input + "\n" + " ".repeat(index + 6) + "^"}\nInvalid character.\x1b[0m`);
186
+ throw new Error();
187
+ }
188
+ tokens.push(makeToken(input, TokenKind.NUMBER, start, index - start + 1));
189
+ break;
190
+ }
191
+ else if (numType === "b") {
192
+ index += 2;
193
+ while (Checker.isBinaryChar(input[index + 1]))
194
+ index++;
195
+ tokens.push(makeToken(input, TokenKind.NUMBER, start, index - start + 1));
196
+ if (start + 2 === index) {
197
+ console.error(`\x1b[31merror: ${input + "\n" + " ".repeat(index + 6) + "^"}\nInvalid character.\x1b[0m`);
198
+ throw new Error();
199
+ }
200
+ break;
201
+ }
202
+ else if (numType === "o") {
203
+ index += 2;
204
+ while (Checker.isOctalChar(input[index + 1]))
205
+ index++;
206
+ tokens.push(makeToken(input, TokenKind.NUMBER, start, index - start + 1));
207
+ if (start + 2 === index) {
208
+ console.error(`\x1b[31merror: ${input + "\n" + " ".repeat(index + 6) + "^"}\nInvalid character.\x1b[0m`);
209
+ throw new Error();
210
+ }
211
+ break;
212
+ }
213
+ }
171
214
  while (Checker.isNumberChar(input[index + 1]))
172
215
  index++;
173
216
  if (input[index + 1] === "e") {
@@ -1,21 +1,55 @@
1
1
  import { TokenKind, TSTokenKind } from "./types.js";
2
2
  import { BindingType } from "../../types/enums/BindingType.js";
3
- import { FuntionMap } from "./Funtion.js";
3
+ import { FunctionMap } from "./Function.js";
4
4
  import { Lexer } from "./Lexer.js";
5
+ import { RandomBindingString } from "../../components/Utils.js";
5
6
  export class Parser {
6
7
  input;
8
+ cache;
7
9
  position = 0;
8
- tokens;
9
10
  genBindings = [];
10
11
  output;
11
- constructor(input) {
12
+ tokens;
13
+ constructor(input, cache = new Map(), tokens) {
12
14
  this.input = input;
13
- this.tokens = Lexer(this.input);
15
+ this.cache = cache;
16
+ if (tokens) {
17
+ this.tokens = tokens;
18
+ tokens = undefined;
19
+ }
20
+ else
21
+ this.tokens = Lexer(input);
14
22
  this.output = this.parseExpression();
15
23
  if (this.at()) {
16
24
  this.expect(TokenKind.EOF, "Unexpected token!");
17
25
  }
18
26
  }
27
+ static intToBin(input) {
28
+ const bindings = [];
29
+ const rtn = RandomBindingString(16);
30
+ for (let i = 0; i < 30; i++) {
31
+ bindings.push({
32
+ source: `(${input} / ${2 ** i} - (${input} / ${2 ** (i + 1)}) * 2)`,
33
+ target: `${rtn}${i}`,
34
+ });
35
+ }
36
+ return {
37
+ ret: rtn,
38
+ bindings,
39
+ };
40
+ }
41
+ intToBin(input) {
42
+ const inStr = `expr:${input}`;
43
+ if (this.cache.has(inStr)) {
44
+ return this.cache.get(inStr);
45
+ }
46
+ else {
47
+ const { ret, bindings } = Parser.intToBin(input);
48
+ this.cache.set(inStr, ret);
49
+ this.genBindings.push(...bindings);
50
+ return ret;
51
+ }
52
+ }
19
53
  at() {
20
54
  return this.tokens[this.position];
21
55
  }
@@ -81,19 +115,106 @@ export class Parser {
81
115
  return left;
82
116
  }
83
117
  parseMultiplicativeExpression() {
84
- let left = this.parsePrimaryExpression(), current;
118
+ let left = this.parseBitwiseLogicExpression(), current;
85
119
  while ((current = this.at()) &&
86
120
  this.at()?.kind === TokenKind.OPERATOR &&
87
121
  ["*", "/", "%"].includes(current.value)) {
88
122
  const operator = this.eat();
89
123
  const right = this.parsePrimaryExpression();
90
- if (current.value === "%")
91
- left = `(${left} - (${left} / ${right} * ${right}))`;
124
+ if (current.value === "%") {
125
+ const cacheStr = `expr:${left}${operator.value}${right}`;
126
+ if (this.cache.has(cacheStr)) {
127
+ return (left = this.cache.get(cacheStr));
128
+ }
129
+ const ret = RandomBindingString(16);
130
+ this.genBindings.push({
131
+ source: `(${left} - (${left} / ${right} * ${right}))`,
132
+ target: ret,
133
+ });
134
+ this.cache.set(cacheStr, ret);
135
+ left = ret;
136
+ }
92
137
  else
93
138
  left = `(${left} ${operator.value} ${right})`;
94
139
  }
95
140
  return left;
96
141
  }
142
+ parseBitwiseLogicExpression() {
143
+ let left = this.parseBitwiseShiftExpression(), current;
144
+ while ((current = this.at()) &&
145
+ this.at()?.kind === TokenKind.OPERATOR &&
146
+ ["&", "|", "^"].includes(current.value)) {
147
+ const operator = this.eat();
148
+ const right = this.parsePrimaryExpression();
149
+ const cacheStr = `expr:${left}${operator.value}${right}`;
150
+ if (this.cache.has(cacheStr)) {
151
+ return (left = this.cache.get(cacheStr));
152
+ }
153
+ const ret = RandomBindingString(16);
154
+ this.cache.set(cacheStr, ret);
155
+ const leftBin = this.intToBin(left);
156
+ const rightBin = this.intToBin(right);
157
+ if (operator.value === "&") {
158
+ this.genBindings.push(...Array.from({ length: 30 }, (_, i) => {
159
+ return {
160
+ source: `(${leftBin}${i} * ${rightBin}${i})`,
161
+ target: `${ret}${i}`,
162
+ };
163
+ }));
164
+ }
165
+ else if (operator.value === "|") {
166
+ this.genBindings.push(...Array.from({ length: 30 }, (_, i) => {
167
+ return {
168
+ source: `(${leftBin}${i} + ${rightBin}${i} - (${leftBin}${i} * ${rightBin}${i}))`,
169
+ target: `${ret}${i}`,
170
+ };
171
+ }));
172
+ }
173
+ else {
174
+ this.genBindings.push(...Array.from({ length: 30 }, (_, i) => {
175
+ return {
176
+ source: `(${leftBin}${i} + ${rightBin}${i} - 2 * (${leftBin}${i} * ${rightBin}${i}))`,
177
+ target: `${ret}${i}`,
178
+ };
179
+ }));
180
+ }
181
+ this.genBindings.push({
182
+ source: `(${Array.from({ length: 30 }, (_, i) => `(${ret}${i} * ${2 ** i})`).join(" + ")})`,
183
+ target: ret,
184
+ });
185
+ left = ret;
186
+ }
187
+ return left;
188
+ }
189
+ parseBitwiseShiftExpression() {
190
+ let left = this.parsePrimaryExpression(), current;
191
+ while ((current = this.at()) &&
192
+ this.at()?.kind === TokenKind.OPERATOR &&
193
+ [">>", "<<"].includes(current.value)) {
194
+ const operator = this.eat();
195
+ const right = this.parsePrimaryExpression();
196
+ const cacheStr = `expr:${left}${operator.value}${right}`;
197
+ if (this.cache.has(cacheStr)) {
198
+ return (left = this.cache.get(cacheStr));
199
+ }
200
+ const ret = RandomBindingString(16);
201
+ this.cache.set(cacheStr, ret);
202
+ const leftBind = this.intToBin(left);
203
+ const op = operator.value === "<<" ? "-" : "+";
204
+ this.genBindings.push(...Array.from({ length: 30 }, (_, i) => {
205
+ return {
206
+ source: `((0 * ${left}) + ('${leftBind}' + (${i} ${op} ${right})))`,
207
+ target: `${ret}${i}`,
208
+ };
209
+ }));
210
+ this.genBindings.push({
211
+ source: `(${Array.from({ length: 30 }, (_, i) => `(${ret}${i} * ${2 ** i})`).join(" + ")})`,
212
+ target: ret,
213
+ });
214
+ left = ret;
215
+ }
216
+ return left;
217
+ }
97
218
  parsePrimaryExpression() {
98
219
  const left = this.at();
99
220
  switch (left?.kind) {
@@ -107,8 +228,18 @@ export class Parser {
107
228
  return `(${value})`;
108
229
  }
109
230
  case TokenKind.NUMBER: {
110
- const [num, exp] = this.eat().value.split("e");
111
- return "" + (exp ? +num * 10 ** +exp : num);
231
+ const numberToken = this.eat();
232
+ switch (numberToken.value[1]) {
233
+ case "x":
234
+ return "" + parseInt(numberToken.value.slice(2), 16);
235
+ case "o":
236
+ return "" + parseInt(numberToken.value.slice(2), 8);
237
+ case "b":
238
+ return "" + parseInt(numberToken.value.slice(2), 2);
239
+ default:
240
+ const [num, exp] = numberToken.value.split("e");
241
+ return "" + (exp ? +num * 10 ** +exp : num);
242
+ }
112
243
  }
113
244
  case TokenKind.VARIABLE:
114
245
  case TokenKind.STRING:
@@ -184,7 +315,15 @@ export class Parser {
184
315
  }
185
316
  }
186
317
  this.eat();
187
- return this.funtionCall(callerToken.value, ...args);
318
+ const inputStr = `func:${callerToken.value}(${args.join(", ")})`;
319
+ if (this.cache.has(inputStr)) {
320
+ return this.cache.get(inputStr);
321
+ }
322
+ else {
323
+ const ret = this.functionCall(callerToken.value, ...args);
324
+ this.cache.set(inputStr, ret);
325
+ return ret;
326
+ }
188
327
  }
189
328
  else if (left?.kind === TokenKind.OPERATOR) {
190
329
  this.warn(`Implicit string literal '${callerToken.value}'. Use quoted string ('${callerToken.value}') for clarity!`, callerToken);
@@ -198,8 +337,8 @@ export class Parser {
198
337
  return callerToken.value;
199
338
  }
200
339
  }
201
- funtionCall(name, ...params) {
202
- const func = FuntionMap.get(name.toLowerCase());
340
+ functionCall(name, ...params) {
341
+ const func = FunctionMap.get(name.toLowerCase());
203
342
  if (!func) {
204
343
  return this.expect(TokenKind.WORD, "Function not found!");
205
344
  }
@@ -226,6 +365,7 @@ export class Parser {
226
365
  out() {
227
366
  return {
228
367
  out: `(${this.output})`,
368
+ cache: this.cache,
229
369
  gen: this.genBindings.map(({ source, target }) => ({
230
370
  binding_type: BindingType.VIEW,
231
371
  source_property_name: `(${source})`,
@@ -0,0 +1,53 @@
1
+ import fs from "fs/promises";
2
+ export class BuildCache {
3
+ static queue = Promise.resolve();
4
+ static async enqueue(task) {
5
+ let result;
6
+ this.queue = this.queue.then(async () => {
7
+ result = await task();
8
+ });
9
+ return this.queue.then(() => result);
10
+ }
11
+ static async get(key) {
12
+ return this.enqueue(async () => {
13
+ try {
14
+ return await fs.readFile("build/cache.json", "utf-8").then(data => JSON.parse(data)[key] ?? null);
15
+ }
16
+ catch (error) {
17
+ return null;
18
+ }
19
+ });
20
+ }
21
+ static async getWithDefault(key, defaultValue) {
22
+ const outVal = typeof defaultValue === "function" ? defaultValue() : defaultValue;
23
+ return this.get(key).then(value => value ?? outVal);
24
+ }
25
+ static async getWithSetDefault(key, defaultValue) {
26
+ const outVal = typeof defaultValue === "function" ? defaultValue() : defaultValue;
27
+ return this.enqueue(async () => {
28
+ let data = {};
29
+ try {
30
+ data = JSON.parse(await fs.readFile("build/cache.json", "utf-8"));
31
+ }
32
+ catch { }
33
+ if (key in data)
34
+ return data[key];
35
+ data[key] = outVal;
36
+ await fs.writeFile("build/cache.json", JSON.stringify(data), "utf-8");
37
+ return outVal;
38
+ });
39
+ }
40
+ static async set(key, value) {
41
+ return this.enqueue(async () => {
42
+ try {
43
+ return fs.writeFile("build/cache.json", JSON.stringify({
44
+ ...(await fs.readFile("build/cache.json", "utf-8").then(data => JSON.parse(data))),
45
+ [key]: value,
46
+ }), "utf-8");
47
+ }
48
+ catch (error) {
49
+ return fs.writeFile("build/cache.json", JSON.stringify({ [key]: value }), "utf-8");
50
+ }
51
+ });
52
+ }
53
+ }
@@ -0,0 +1,4 @@
1
+ try {
2
+ }
3
+ catch (error) { }
4
+ export {};
@@ -1,22 +1,37 @@
1
- import { isBuildMode } from "../Configuration.js";
1
+ import { config, isBuildMode, isLinkMode, unLinked } from "../Configuration.js";
2
2
  import { Memory } from "../Memory.js";
3
- import { createBuildFolder } from "./linker.js";
3
+ import { createBuildFolder, linkToGame, unlink } from "./linker.js";
4
+ import { genManifest } from "./manifest.js";
4
5
  import fs from "fs/promises";
6
+ import { BuildCache } from "./buildcache.js";
5
7
  async function buildUI() {
6
8
  const build = Memory.build();
7
- let i = 0;
8
- build.set("ui/ui_defs.json", {
9
+ build.set("ui/_ui_defs.json", {
9
10
  ui_defs: Array.from(build.keys()),
10
11
  });
11
- await Promise.all(build.entries().map(async ([file, value]) => {
12
- const outFile = `build/build/${file}`;
12
+ if (config.global_variables)
13
+ build.set("ui/_global_variables.json", config.global_variables);
14
+ const out = await Promise.all(build.entries().map(async ([file, value]) => {
15
+ const outFile = `build/${file}`;
13
16
  await fs
14
17
  .stat(outFile.split(/\\|\//g).slice(0, -1).join("/"))
15
18
  .catch(async () => await fs.mkdir(outFile.split(/\\|\//g).slice(0, -1).join("/"), { recursive: true }));
16
- await fs.writeFile(outFile, JSON.stringify(value), "utf-8");
17
- i++;
19
+ await fs.writeFile(outFile, JSON.stringify(Object.fromEntries(Object.entries(value).map(([key, value]) => {
20
+ const extend = value.extend;
21
+ return [extend ? key + String(extend) : key, value];
22
+ }))), "utf-8");
23
+ build.delete(file);
24
+ return file;
18
25
  }));
19
- return i - 1;
26
+ await Promise.all([
27
+ fs.writeFile("build/manifest.json", await genManifest(), "utf-8"),
28
+ fs.writeFile("build/.gitignore", [...out, "manifest.json"].join("\n"), "utf-8"),
29
+ BuildCache.set("build-files", [...out, "manifest.json"]),
30
+ fs
31
+ .stat("build/pack_icon.png")
32
+ .catch(() => fs.copyFile("node_modules/asajs/resources/pack_icon.png", "build/pack_icon.png")),
33
+ ]);
34
+ return out.length;
20
35
  }
21
36
  if (isBuildMode) {
22
37
  let first = true;
@@ -24,7 +39,13 @@ if (isBuildMode) {
24
39
  if (first) {
25
40
  await createBuildFolder();
26
41
  await buildUI();
42
+ if (isLinkMode)
43
+ await linkToGame();
27
44
  }
28
45
  first = false;
29
46
  });
30
47
  }
48
+ else if (isLinkMode)
49
+ linkToGame();
50
+ else if (unLinked)
51
+ unlink();
@@ -1 +1,15 @@
1
- export {};
1
+ import os from "os";
2
+ import path from "path";
3
+ export function getGamedataPath() {
4
+ switch (os.platform()) {
5
+ case "win32": {
6
+ if (/Windows (10|11)/.test(os.version())) {
7
+ return path.join(process.env.APPDATA, "Minecraft Bedrock\\Users\\Shared\\games\\com.mojang");
8
+ }
9
+ }
10
+ default: {
11
+ console.error(`Your platform is not supported the install feature yet! \nYour OS version: ${os.version()}`);
12
+ process.exit(1);
13
+ }
14
+ }
15
+ }