asajs 4.0.0-indev-2 → 4.0.0-indev-4

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/README.md +56 -2
  2. package/config.d.ts +29 -0
  3. package/dist/js/compilers/Configuration.js +20 -1
  4. package/dist/js/compilers/Memory.js +1 -1
  5. package/dist/js/compilers/PreCompile.js +12 -1
  6. package/dist/js/compilers/bindings/Checker.js +9 -0
  7. package/dist/js/compilers/bindings/{Funtion.js → Function.js} +30 -6
  8. package/dist/js/compilers/bindings/Lexer.js +49 -6
  9. package/dist/js/compilers/bindings/Parser.js +152 -12
  10. package/dist/js/compilers/ui/builder.js +44 -14
  11. package/dist/js/compilers/ui/installer.js +139 -4
  12. package/dist/js/compilers/ui/linker.js +36 -9
  13. package/dist/js/compilers/ui/manifest.js +9 -5
  14. package/dist/js/components/AnimationKeyframe.js +1 -1
  15. package/dist/js/components/UI.js +4 -3
  16. package/dist/js/components/Utils.js +83 -20
  17. package/dist/js/index.js +3 -0
  18. package/dist/types/compilers/Configuration.d.ts +5 -1
  19. package/dist/types/compilers/PreCompile.d.ts +2 -0
  20. package/dist/types/compilers/bindings/Checker.d.ts +3 -0
  21. package/dist/types/compilers/bindings/{Funtion.d.ts → Function.d.ts} +1 -1
  22. package/dist/types/compilers/bindings/Parser.d.ts +12 -3
  23. package/dist/types/compilers/ui/installer.d.ts +11 -1
  24. package/dist/types/compilers/ui/linker.d.ts +2 -0
  25. package/dist/types/compilers/ui/manifest.d.ts +1 -0
  26. package/dist/types/components/AnimationKeyframe.d.ts +4 -4
  27. package/dist/types/components/UI.d.ts +1 -0
  28. package/dist/types/components/Utils.d.ts +16 -16
  29. package/dist/types/index.d.ts +3 -0
  30. package/dist/types/types/enums/index.d.ts +0 -1
  31. package/dist/types/types/vanilla/intellisense.d.ts +11194 -11194
  32. package/package.json +1 -1
  33. package/resources/asajs.config.cjs +17 -0
  34. package/dist/js/compilers/RunEnd.js +0 -7
  35. package/dist/js/compilers/ui/builddata.js +0 -4
  36. package/dist/js/compilers/ui/config.js +0 -1
  37. package/dist/js/compilers/ui/prevdata.js +0 -8
  38. package/dist/js/types/enums/SmartAnimationType.js +0 -3
  39. package/dist/types/compilers/RunEnd.d.ts +0 -1
  40. package/dist/types/compilers/ui/builddata.d.ts +0 -1
  41. package/dist/types/compilers/ui/config.d.ts +0 -1
  42. package/dist/types/compilers/ui/prevdata.d.ts +0 -3
  43. package/dist/types/types/enums/SmartAnimationType.d.ts +0 -2
package/README.md CHANGED
@@ -1,3 +1,57 @@
1
- AsaJS Logo made by [Kammasy](https://www.youtube.com/channel/UCrmjDWdM8-ZSeekzLeCnftg) a.k.a **[E.G.G](https://www.youtube.com/channel/UCrmjDWdM8-ZSeekzLeCnftg)**
1
+ <div align="center">
2
+ <img src="./resources/logo.png" />
2
3
 
3
- ![image](/resources/logo.png)
4
+ <h2 align="center">
5
+ <a href="https://asajs.asakiyuki.com/">AsaJS</a> - The <a href="https://www.minecraft.net/en-us">Minecraft: Bedrock Edition</a> JSON-UI Framework
6
+ </h2>
7
+
8
+ [![asajs version](https://img.shields.io/npm/v/asajs.svg?style=for-the-badge&labelColor=000000)](https://www.npmjs.com/package/asajs)
9
+ [![asajs license](https://img.shields.io/npm/l/asajs.svg?style=for-the-badge&labelColor=000000)](https://github.com/AsakiYuki/AsaJS/blob/main/README.md)
10
+ [![asajs downloads](https://img.shields.io/npm/dm/asajs.svg?style=for-the-badge&labelColor=000000)](https://www.npmjs.com/package/asajs)
11
+ </div>
12
+
13
+ **AsaJS** is a NodeJS library designed to empower developers to create **JSON-UI** packages for Minecraft: Bedrock Edition using **JavaScript** or **TypeScript**.
14
+
15
+ Say goodbye to the tedious and repetitive nature of manual JSON editing. AsaJS streamlines your workflow by bringing the programmatic flexibility to Minecraft UI development.
16
+
17
+ ## 🛠 Installation
18
+
19
+ To use AsaJS, ensure you have **[Node.js](https://nodejs.org/en)** installed on your system.
20
+
21
+ **Latest stable version:**
22
+
23
+ ```bash
24
+ npm install asajs
25
+ ```
26
+
27
+ **For our nightly builds:**
28
+
29
+ ```
30
+ npm install asajs@indev
31
+ ```
32
+
33
+ ## 📖 "Hello World!" Example
34
+
35
+ Creating a custom UI with AsaJS is straightforward. Here is how you can insert a custom label onto the Minecraft Start Screen:
36
+
37
+ ```javascript
38
+ import { Anchor, Label, Modify } from "asajs"
39
+
40
+ const label = Label({
41
+ text: "Hello World from my Custom UI!",
42
+ shadow: true,
43
+ anchor: Anchor.TOP_MIDDLE,
44
+ offset: [0, 10],
45
+ })
46
+
47
+ // This code injects the label into the top of the start screen
48
+ Modify("start", "start_screen_content").insertChild(label)
49
+ ```
50
+
51
+ ## 📚 Documentation
52
+
53
+ Detailed guides and API references are available at: 👉 https://asajs.asakiyuki.com/
54
+
55
+ ## 🤝 Contributing
56
+
57
+ Contributions are what make the open-source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
package/config.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ import { Variable } from "./src/types/properties/value.ts"
2
+
3
+ export interface Config {
4
+ compiler?: {
5
+ enabled?: boolean
6
+ autoImport?: boolean
7
+ importToPreview?: boolean
8
+ autoEnable?: boolean
9
+ gdkUserId?: string
10
+ }
11
+ packinfo?: {
12
+ name?: string
13
+ description?: string
14
+ version?: [number, number, number]
15
+
16
+ metadata?: {
17
+ authors?: string[]
18
+ license?: string
19
+ url?: string
20
+ }
21
+
22
+ subpacks?: {
23
+ folder_name?: string
24
+ name?: string
25
+ memory_performance_tier?: number
26
+ }[]
27
+ }
28
+ global_variables?: Record<Variable, string>
29
+ }
@@ -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?.autoImport ?? false;
12
+ export let unLinked = !(config.compiler?.autoImport ?? 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
+ }
@@ -20,7 +20,7 @@ export class Memory extends Class {
20
20
  }
21
21
  static build() {
22
22
  const data = new Map();
23
- Memory.files.entries().forEach(([path, { elements, namespace }]) => {
23
+ Array.from(Memory.files.entries()).forEach(([path, { elements, namespace }]) => {
24
24
  const record = {};
25
25
  elements.forEach(element => (record[element.name] = element));
26
26
  data.set(path, {
@@ -6,4 +6,15 @@ Map.prototype.toJSON = function () {
6
6
  Array.prototype.lastItem = function () {
7
7
  return this[this.length - 1];
8
8
  };
9
- export {};
9
+ const now = performance.now();
10
+ function TypeHighlight(type) {
11
+ switch (type) {
12
+ case "INFO":
13
+ return `\x1b[32mINFO\x1b[0m`;
14
+ default:
15
+ return type;
16
+ }
17
+ }
18
+ export function Log(type, message) {
19
+ console.log(`\x1b[90m[${(performance.now() - now).toFixed(2)}ms]\x1b[0m`, `[${TypeHighlight(type)}]`, message, "\x1b[0m");
20
+ }
@@ -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
  }
@@ -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})`,
@@ -1,34 +1,46 @@
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, linkToGame } from "./linker.js";
4
- import { genManifest } from "./manifest.js";
3
+ import { createBuildFolder, gamePath, getBuildFolderName, linkToGame, unlink } from "./linker.js";
4
+ import { genManifest, version } from "./manifest.js";
5
5
  import fs from "fs/promises";
6
+ import { BuildCache } from "./buildcache.js";
7
+ import { disableRSP, enableRSP } from "./installer.js";
8
+ import { Log } from "../PreCompile.js";
9
+ import path from "path";
6
10
  async function buildUI() {
7
11
  const build = Memory.build();
8
12
  build.set("ui/_ui_defs.json", {
9
13
  ui_defs: Array.from(build.keys()),
10
14
  });
11
- build.set("build.json", {
12
- files: Array.from(build.keys()),
13
- });
15
+ if (config.global_variables)
16
+ build.set("ui/_global_variables.json", config.global_variables);
14
17
  const out = await Promise.all(build.entries().map(async ([file, value]) => {
15
- const outFile = `build/build/${file}`;
18
+ const outFile = `build/${file}`;
16
19
  await fs
17
20
  .stat(outFile.split(/\\|\//g).slice(0, -1).join("/"))
18
21
  .catch(async () => await fs.mkdir(outFile.split(/\\|\//g).slice(0, -1).join("/"), { recursive: true }));
19
- await fs.writeFile(outFile, JSON.stringify(Object.fromEntries(Object.entries(value).map(([key, value]) => {
22
+ await fs
23
+ .writeFile(outFile, JSON.stringify(Object.fromEntries(Object.entries(value).map(([key, value]) => {
20
24
  const extend = value.extend;
21
25
  return [extend ? key + String(extend) : key, value];
22
- }))), "utf-8");
26
+ }))), "utf-8")
27
+ .then(() => Log("INFO", `${outFile} with ${Object.keys(value).length} elements created!`));
23
28
  build.delete(file);
24
29
  return file;
25
30
  }));
26
31
  await Promise.all([
27
- fs.writeFile("build/build/manifest.json", await genManifest(), "utf-8"),
28
- fs.writeFile("build/build/.gitignore", [...out, "manifest.json"].join("\n"), "utf-8"),
29
32
  fs
30
- .stat("build/build/pack_icon.png")
31
- .catch(() => fs.copyFile("node_modules/asajs/resources/pack_icon.png", "build/build/pack_icon.png")),
33
+ .writeFile("build/manifest.json", await genManifest(), "utf-8")
34
+ .then(() => Log("INFO", "build/manifest.json created!")),
35
+ fs
36
+ .writeFile("build/.gitignore", [...out, "manifest.json"].join("\n"), "utf-8")
37
+ .then(() => Log("INFO", "build/.gitignore created!")),
38
+ BuildCache.set("build-files", [...out, "manifest.json"]).then(() => Log("INFO", "build-files set!")),
39
+ BuildCache.set("version", version).then(() => Log("INFO", "version set!")),
40
+ fs
41
+ .stat("build/pack_icon.png")
42
+ .catch(() => fs.copyFile("node_modules/asajs/resources/pack_icon.png", "build/pack_icon.png"))
43
+ .then(() => Log("INFO", "build/pack_icon.png copied!")),
32
44
  ]);
33
45
  return out.length;
34
46
  }
@@ -38,8 +50,26 @@ if (isBuildMode) {
38
50
  if (first) {
39
51
  await createBuildFolder();
40
52
  await buildUI();
41
- await linkToGame();
53
+ if (isLinkMode)
54
+ await linkToGame();
55
+ if (config.compiler?.autoEnable)
56
+ await enableRSP();
57
+ else
58
+ await disableRSP();
59
+ Log("INFO", "Build completed!");
60
+ console.log("========================= PACK INFO =========================");
61
+ console.log("Name:", `\x1b[32m${config.packinfo?.name || "MyPack"}\x1b[0m`);
62
+ console.log("Description:", `\x1b[32m${config.packinfo?.description || "Create your Minecraft JSON-UI resource packs using JavaScript."}\x1b[0m`);
63
+ console.log("Version:", config.packinfo?.version || [4, 0, 0]);
64
+ console.log("UUID:", await BuildCache.get("uuid"));
65
+ if (gamePath)
66
+ console.log("Install Path:", `\x1b[32m"${path.join(gamePath, await getBuildFolderName())}"\x1b[0m`);
67
+ console.log("=============================================================");
42
68
  }
43
69
  first = false;
44
70
  });
45
71
  }
72
+ else if (isLinkMode)
73
+ linkToGame();
74
+ else if (unLinked)
75
+ unlink();