@holoscript/core 2.0.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-KWYIVRIH.js → chunk-2XXE34KS.js} +2 -2
- package/dist/chunk-2XXE34KS.js.map +1 -0
- package/dist/{chunk-EU6CZMGJ.js → chunk-AFFVFO4D.js} +511 -118
- package/dist/chunk-AFFVFO4D.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +10 -0
- package/dist/{chunk-4CV4JOE5.js.map → chunk-DGUM43GV.js.map} +1 -1
- package/dist/{chunk-VYIDLUCV.js → chunk-DOY73HDH.js} +4 -4
- package/dist/{chunk-VYIDLUCV.js.map → chunk-DOY73HDH.js.map} +1 -1
- package/dist/chunk-JEQ2X3Z6.cjs +12 -0
- package/dist/{chunk-CZLDE2OZ.cjs.map → chunk-JEQ2X3Z6.cjs.map} +1 -1
- package/dist/{chunk-3N67RLQP.cjs → chunk-L6VLNVKP.cjs} +511 -118
- package/dist/chunk-L6VLNVKP.cjs.map +1 -0
- package/dist/{chunk-VMZN4EVR.cjs → chunk-MFNO57XL.cjs} +2 -2
- package/dist/chunk-MFNO57XL.cjs.map +1 -0
- package/dist/{chunk-WFI4T3XB.cjs → chunk-R75MREOS.cjs} +6 -6
- package/dist/{chunk-WFI4T3XB.cjs.map → chunk-R75MREOS.cjs.map} +1 -1
- package/dist/{chunk-4OHVW4XR.cjs → chunk-T57ZL7KR.cjs} +299 -45
- package/dist/chunk-T57ZL7KR.cjs.map +1 -0
- package/dist/{chunk-MCP6D4LT.js → chunk-U72GEJZT.js} +299 -45
- package/dist/chunk-U72GEJZT.js.map +1 -0
- package/dist/debugger.cjs +6 -6
- package/dist/debugger.d.cts +1 -1
- package/dist/debugger.d.ts +1 -1
- package/dist/debugger.js +4 -4
- package/dist/index.cjs +1896 -1099
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3145 -1534
- package/dist/index.d.ts +3145 -1534
- package/dist/index.js +1922 -1133
- package/dist/index.js.map +1 -1
- package/dist/parser.cjs +3 -3
- package/dist/parser.d.cts +34 -1
- package/dist/parser.d.ts +34 -1
- package/dist/parser.js +2 -2
- package/dist/runtime.cjs +3 -3
- package/dist/runtime.d.cts +47 -27
- package/dist/runtime.d.ts +47 -27
- package/dist/runtime.js +2 -2
- package/dist/type-checker.cjs +4 -4
- package/dist/type-checker.d.cts +3 -3
- package/dist/type-checker.d.ts +3 -3
- package/dist/type-checker.js +2 -2
- package/dist/{types-D6g4ACjP.d.cts → types-4h8cbtF_.d.cts} +80 -13
- package/dist/{types-D6g4ACjP.d.ts → types-4h8cbtF_.d.ts} +80 -13
- package/package.json +21 -20
- package/LICENSE +0 -21
- package/dist/chunk-3N67RLQP.cjs.map +0 -1
- package/dist/chunk-4CV4JOE5.js +0 -24
- package/dist/chunk-4OHVW4XR.cjs.map +0 -1
- package/dist/chunk-CZLDE2OZ.cjs +0 -28
- package/dist/chunk-EU6CZMGJ.js.map +0 -1
- package/dist/chunk-KWYIVRIH.js.map +0 -1
- package/dist/chunk-MCP6D4LT.js.map +0 -1
- package/dist/chunk-VMZN4EVR.cjs.map +0 -1
|
@@ -1,5 +1,111 @@
|
|
|
1
1
|
import { logger } from './chunk-SATNCODL.js';
|
|
2
2
|
|
|
3
|
+
// src/ReactiveState.ts
|
|
4
|
+
var ReactiveState = class {
|
|
5
|
+
constructor(initialState = {}) {
|
|
6
|
+
this.subscribers = /* @__PURE__ */ new Set();
|
|
7
|
+
this.state = { ...initialState };
|
|
8
|
+
this.proxy = this.createReactiveProxy(this.state);
|
|
9
|
+
}
|
|
10
|
+
createReactiveProxy(target) {
|
|
11
|
+
const self = this;
|
|
12
|
+
return new Proxy(target, {
|
|
13
|
+
get(obj, key) {
|
|
14
|
+
const val = obj[key];
|
|
15
|
+
if (val && typeof val === "object" && !Array.isArray(val)) {
|
|
16
|
+
return self.createReactiveProxy(val);
|
|
17
|
+
}
|
|
18
|
+
return val;
|
|
19
|
+
},
|
|
20
|
+
set(obj, key, value) {
|
|
21
|
+
const oldVal = obj[key];
|
|
22
|
+
obj[key] = value;
|
|
23
|
+
if (oldVal !== value) {
|
|
24
|
+
self.notify();
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
get(key) {
|
|
31
|
+
return this.proxy[key];
|
|
32
|
+
}
|
|
33
|
+
set(key, value) {
|
|
34
|
+
this.proxy[key] = value;
|
|
35
|
+
}
|
|
36
|
+
update(updates) {
|
|
37
|
+
Object.assign(this.proxy, updates);
|
|
38
|
+
}
|
|
39
|
+
subscribe(callback) {
|
|
40
|
+
this.subscribers.add(callback);
|
|
41
|
+
return () => this.subscribers.delete(callback);
|
|
42
|
+
}
|
|
43
|
+
getSnapshot() {
|
|
44
|
+
return { ...this.state };
|
|
45
|
+
}
|
|
46
|
+
notify() {
|
|
47
|
+
this.subscribers.forEach((cb) => cb(this.getSnapshot()));
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
var ExpressionEvaluator = class {
|
|
51
|
+
constructor(context = {}) {
|
|
52
|
+
this.context = context;
|
|
53
|
+
}
|
|
54
|
+
evaluate(expression) {
|
|
55
|
+
if (typeof expression !== "string") return expression;
|
|
56
|
+
const dangerousPatterns = [
|
|
57
|
+
/\beval\s*\(/,
|
|
58
|
+
/\brequire\s*\(/,
|
|
59
|
+
/\bimport\s*\(/,
|
|
60
|
+
/\bprocess\s*\./,
|
|
61
|
+
/\bglobal\s*\./,
|
|
62
|
+
/\b__dirname\b/,
|
|
63
|
+
/\b__filename\b/,
|
|
64
|
+
/\bfs\s*\./,
|
|
65
|
+
/\bchild_process\s*\./,
|
|
66
|
+
/\bfs\.writeFileSync/,
|
|
67
|
+
/\bfs\.readFileSync/
|
|
68
|
+
];
|
|
69
|
+
for (const pattern of dangerousPatterns) {
|
|
70
|
+
if (pattern.test(expression)) {
|
|
71
|
+
console.warn(`Security: Blocked suspicious expression: ${expression}`);
|
|
72
|
+
return void 0;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (expression.includes("${")) {
|
|
76
|
+
const trimmed = expression.trim();
|
|
77
|
+
const match = trimmed.match(/^\$\{([^}]+)\}$/);
|
|
78
|
+
if (match) {
|
|
79
|
+
return this.evaluate(match[1]);
|
|
80
|
+
}
|
|
81
|
+
return this.interpolate(expression);
|
|
82
|
+
}
|
|
83
|
+
const keys = Object.keys(this.context);
|
|
84
|
+
const values = Object.values(this.context);
|
|
85
|
+
try {
|
|
86
|
+
const fn = new Function(...keys, `return (${expression})`);
|
|
87
|
+
return fn(...values);
|
|
88
|
+
} catch (e) {
|
|
89
|
+
return expression;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
interpolate(str) {
|
|
93
|
+
return str.replace(/\$\{([^}]+)\}/g, (_, expr) => {
|
|
94
|
+
const val = this.evaluate(expr);
|
|
95
|
+
return val !== void 0 ? String(val) : "";
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
updateContext(updates) {
|
|
99
|
+
Object.assign(this.context, updates);
|
|
100
|
+
}
|
|
101
|
+
setContext(context) {
|
|
102
|
+
this.context = { ...context };
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
function createState(initial = {}) {
|
|
106
|
+
return new ReactiveState(initial);
|
|
107
|
+
}
|
|
108
|
+
|
|
3
109
|
// src/HoloScriptRuntime.ts
|
|
4
110
|
var RUNTIME_SECURITY_LIMITS = {
|
|
5
111
|
maxExecutionDepth: 50,
|
|
@@ -9,7 +115,7 @@ var RUNTIME_SECURITY_LIMITS = {
|
|
|
9
115
|
maxCallStackDepth: 100
|
|
10
116
|
};
|
|
11
117
|
var HoloScriptRuntime = class {
|
|
12
|
-
constructor(_importLoader) {
|
|
118
|
+
constructor(_importLoader, customFunctions) {
|
|
13
119
|
this.particleSystems = /* @__PURE__ */ new Map();
|
|
14
120
|
this.executionHistory = [];
|
|
15
121
|
this.startTime = 0;
|
|
@@ -20,13 +126,18 @@ var HoloScriptRuntime = class {
|
|
|
20
126
|
this.uiElements = /* @__PURE__ */ new Map();
|
|
21
127
|
this.context = this.createEmptyContext();
|
|
22
128
|
this.currentScope = { variables: this.context.variables };
|
|
23
|
-
this.builtinFunctions = this.initBuiltins();
|
|
129
|
+
this.builtinFunctions = this.initBuiltins(customFunctions);
|
|
24
130
|
}
|
|
25
131
|
/**
|
|
26
132
|
* Initialize built-in functions
|
|
27
133
|
*/
|
|
28
|
-
initBuiltins() {
|
|
134
|
+
initBuiltins(customFunctions) {
|
|
29
135
|
const builtins = /* @__PURE__ */ new Map();
|
|
136
|
+
if (customFunctions) {
|
|
137
|
+
for (const [name, func] of Object.entries(customFunctions)) {
|
|
138
|
+
builtins.set(name, func);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
30
141
|
builtins.set("show", (args) => {
|
|
31
142
|
const target = String(args[0]);
|
|
32
143
|
const element = this.uiElements.get(target);
|
|
@@ -45,7 +156,7 @@ var HoloScriptRuntime = class {
|
|
|
45
156
|
logger.info("hide", { target });
|
|
46
157
|
return { hidden: target };
|
|
47
158
|
});
|
|
48
|
-
builtins.set("
|
|
159
|
+
builtins.set("pulsate", (args) => {
|
|
49
160
|
const target = String(args[0]);
|
|
50
161
|
const options = args[1] || {};
|
|
51
162
|
const duration = Number(options.duration) || 1e3;
|
|
@@ -139,6 +250,15 @@ var HoloScriptRuntime = class {
|
|
|
139
250
|
if (Array.isArray(arr)) return arr[index];
|
|
140
251
|
return void 0;
|
|
141
252
|
});
|
|
253
|
+
builtins.set("showSettings", () => {
|
|
254
|
+
this.emit("show-settings");
|
|
255
|
+
return true;
|
|
256
|
+
});
|
|
257
|
+
builtins.set("openChat", (args) => {
|
|
258
|
+
const config = args[0] || {};
|
|
259
|
+
this.emit("show-chat", config);
|
|
260
|
+
return true;
|
|
261
|
+
});
|
|
142
262
|
builtins.set("log", (args) => {
|
|
143
263
|
logger.info("HoloScript log", { args });
|
|
144
264
|
return args[0];
|
|
@@ -152,6 +272,17 @@ var HoloScriptRuntime = class {
|
|
|
152
272
|
builtins.set("isArray", (args) => Array.isArray(args[0]));
|
|
153
273
|
builtins.set("isNumber", (args) => typeof args[0] === "number" && !isNaN(args[0]));
|
|
154
274
|
builtins.set("isString", (args) => typeof args[0] === "string");
|
|
275
|
+
builtins.set("shop", (args) => this.handleShop(args));
|
|
276
|
+
builtins.set("inventory", (args) => this.handleInventory(args));
|
|
277
|
+
builtins.set("purchase", (args) => this.handlePurchase(args));
|
|
278
|
+
builtins.set("presence", (args) => this.handlePresence(args));
|
|
279
|
+
builtins.set("invite", (args) => this.handleInvite(args));
|
|
280
|
+
builtins.set("share", (args) => this.handleShare(args));
|
|
281
|
+
builtins.set("physics", (args) => this.handlePhysics(args));
|
|
282
|
+
builtins.set("gravity", (args) => this.handleGravity(args));
|
|
283
|
+
builtins.set("collide", (args) => this.handleCollide(args));
|
|
284
|
+
builtins.set("animate", (args) => this.handleAnimate(args));
|
|
285
|
+
builtins.set("calculate_arc", (args) => this.handleCalculateArc(args));
|
|
155
286
|
return builtins;
|
|
156
287
|
}
|
|
157
288
|
/**
|
|
@@ -179,7 +310,6 @@ var HoloScriptRuntime = class {
|
|
|
179
310
|
case "stream":
|
|
180
311
|
result = await this.executeStream(node);
|
|
181
312
|
break;
|
|
182
|
-
case "execute":
|
|
183
313
|
case "call":
|
|
184
314
|
result = await this.executeCall(node);
|
|
185
315
|
break;
|
|
@@ -208,6 +338,36 @@ var HoloScriptRuntime = class {
|
|
|
208
338
|
case "expression-statement":
|
|
209
339
|
result = await this.executeCall(node);
|
|
210
340
|
break;
|
|
341
|
+
case "scale":
|
|
342
|
+
result = await this.executeScale(node);
|
|
343
|
+
break;
|
|
344
|
+
case "focus":
|
|
345
|
+
result = await this.executeFocus(node);
|
|
346
|
+
break;
|
|
347
|
+
case "environment":
|
|
348
|
+
result = await this.executeEnvironment(node);
|
|
349
|
+
break;
|
|
350
|
+
case "composition":
|
|
351
|
+
result = await this.executeComposition(node);
|
|
352
|
+
break;
|
|
353
|
+
case "template":
|
|
354
|
+
result = await this.executeTemplate(node);
|
|
355
|
+
break;
|
|
356
|
+
case "server":
|
|
357
|
+
result = await this.executeServerNode(node);
|
|
358
|
+
break;
|
|
359
|
+
case "database":
|
|
360
|
+
result = await this.executeDatabaseNode(node);
|
|
361
|
+
break;
|
|
362
|
+
case "fetch":
|
|
363
|
+
result = await this.executeFetchNode(node);
|
|
364
|
+
break;
|
|
365
|
+
case "execute":
|
|
366
|
+
result = await this.executeTarget(node);
|
|
367
|
+
break;
|
|
368
|
+
case "state-declaration":
|
|
369
|
+
result = await this.executeStateDeclaration(node);
|
|
370
|
+
break;
|
|
211
371
|
default:
|
|
212
372
|
result = {
|
|
213
373
|
success: false,
|
|
@@ -231,6 +391,22 @@ var HoloScriptRuntime = class {
|
|
|
231
391
|
return errorResult;
|
|
232
392
|
}
|
|
233
393
|
}
|
|
394
|
+
/**
|
|
395
|
+
* Execute multiple nodes or a single node (unified entry point)
|
|
396
|
+
*/
|
|
397
|
+
async execute(nodes) {
|
|
398
|
+
if (Array.isArray(nodes)) {
|
|
399
|
+
const results = await this.executeProgram(nodes);
|
|
400
|
+
const success = results.every((r) => r.success);
|
|
401
|
+
return {
|
|
402
|
+
success,
|
|
403
|
+
output: success ? `Program executed (${results.length} nodes)` : "Program failed",
|
|
404
|
+
error: results.find((r) => !r.success)?.error
|
|
405
|
+
};
|
|
406
|
+
} else {
|
|
407
|
+
return this.executeNode(nodes);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
234
410
|
/**
|
|
235
411
|
* Execute multiple nodes in sequence
|
|
236
412
|
*/
|
|
@@ -401,119 +577,45 @@ var HoloScriptRuntime = class {
|
|
|
401
577
|
*/
|
|
402
578
|
evaluateExpression(expr) {
|
|
403
579
|
if (!expr || typeof expr !== "string") return expr;
|
|
404
|
-
|
|
405
|
-
const
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
}
|
|
410
|
-
if (expr.startsWith('"') && expr.endsWith('"') || expr.startsWith("'") && expr.endsWith("'")) {
|
|
411
|
-
return expr.slice(1, -1);
|
|
412
|
-
}
|
|
413
|
-
if (/^-?\d+(\.\d+)?$/.test(expr)) {
|
|
414
|
-
return parseFloat(expr);
|
|
415
|
-
}
|
|
416
|
-
if (expr === "true") return true;
|
|
417
|
-
if (expr === "false") return false;
|
|
418
|
-
if (expr === "null") return null;
|
|
419
|
-
if (expr === "undefined") return void 0;
|
|
420
|
-
if (expr.startsWith("[") && expr.endsWith("]")) {
|
|
421
|
-
const inner = expr.slice(1, -1);
|
|
422
|
-
if (!inner.trim()) return [];
|
|
423
|
-
const elements = this.splitByComma(inner);
|
|
424
|
-
return elements.map((e) => this.evaluateExpression(e.trim()));
|
|
425
|
-
}
|
|
426
|
-
if (expr.startsWith("{") && expr.endsWith("}")) {
|
|
427
|
-
const inner = expr.slice(1, -1);
|
|
428
|
-
if (!inner.trim()) return {};
|
|
429
|
-
const pairs = this.splitByComma(inner);
|
|
430
|
-
const obj = {};
|
|
431
|
-
for (const pair of pairs) {
|
|
432
|
-
const colonIndex = pair.indexOf(":");
|
|
433
|
-
if (colonIndex > 0) {
|
|
434
|
-
const key = pair.slice(0, colonIndex).trim();
|
|
435
|
-
const value = pair.slice(colonIndex + 1).trim();
|
|
436
|
-
obj[key] = this.evaluateExpression(value);
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
return obj;
|
|
440
|
-
}
|
|
441
|
-
const funcMatch = expr.match(/^(\w+)\s*\((.*)?\)$/);
|
|
442
|
-
if (funcMatch) {
|
|
443
|
-
const [, funcName, argsStr] = funcMatch;
|
|
444
|
-
const args = argsStr ? this.splitByComma(argsStr).map((a) => this.evaluateExpression(a.trim())) : [];
|
|
445
|
-
const builtin = this.builtinFunctions.get(funcName);
|
|
446
|
-
if (builtin) {
|
|
447
|
-
return builtin(args);
|
|
448
|
-
}
|
|
449
|
-
if (this.context.functions.has(funcName)) {
|
|
450
|
-
return { __holoCall: funcName, args };
|
|
451
|
-
}
|
|
452
|
-
return void 0;
|
|
453
|
-
}
|
|
454
|
-
const binaryOps = [
|
|
455
|
-
{ pattern: /(.+)\s*\+\s*(.+)/, op: (a, b) => typeof a === "string" || typeof b === "string" ? String(a) + String(b) : Number(a) + Number(b) },
|
|
456
|
-
{ pattern: /(.+)\s*-\s*(.+)/, op: (a, b) => Number(a) - Number(b) },
|
|
457
|
-
{ pattern: /(.+)\s*\*\s*(.+)/, op: (a, b) => Number(a) * Number(b) },
|
|
458
|
-
{ pattern: /(.+)\s*\/\s*(.+)/, op: (a, b) => Number(b) !== 0 ? Number(a) / Number(b) : 0 },
|
|
459
|
-
{ pattern: /(.+)\s*%\s*(.+)/, op: (a, b) => Number(a) % Number(b) }
|
|
460
|
-
];
|
|
461
|
-
for (const { pattern, op } of binaryOps) {
|
|
462
|
-
const match = expr.match(pattern);
|
|
463
|
-
if (match) {
|
|
464
|
-
const left = this.evaluateExpression(match[1]);
|
|
465
|
-
const right = this.evaluateExpression(match[2]);
|
|
466
|
-
return op(left, right);
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
return this.getVariable(expr);
|
|
470
|
-
}
|
|
471
|
-
/**
|
|
472
|
-
* Split string by comma, respecting nesting
|
|
473
|
-
*/
|
|
474
|
-
splitByComma(str) {
|
|
475
|
-
const parts = [];
|
|
476
|
-
let current = "";
|
|
477
|
-
let depth = 0;
|
|
478
|
-
let inString = false;
|
|
479
|
-
let stringChar = "";
|
|
480
|
-
for (let i = 0; i < str.length; i++) {
|
|
481
|
-
const char = str[i];
|
|
482
|
-
if (!inString && (char === '"' || char === "'")) {
|
|
483
|
-
inString = true;
|
|
484
|
-
stringChar = char;
|
|
485
|
-
} else if (inString && char === stringChar && str[i - 1] !== "\\") {
|
|
486
|
-
inString = false;
|
|
487
|
-
}
|
|
488
|
-
if (!inString) {
|
|
489
|
-
if (char === "(" || char === "[" || char === "{") depth++;
|
|
490
|
-
if (char === ")" || char === "]" || char === "}") depth--;
|
|
491
|
-
if (char === "," && depth === 0) {
|
|
492
|
-
parts.push(current.trim());
|
|
493
|
-
current = "";
|
|
494
|
-
continue;
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
current += char;
|
|
498
|
-
}
|
|
499
|
-
if (current.trim()) {
|
|
500
|
-
parts.push(current.trim());
|
|
501
|
-
}
|
|
502
|
-
return parts;
|
|
580
|
+
const evaluator = new ExpressionEvaluator(this.context.state.getSnapshot());
|
|
581
|
+
const varContext = {};
|
|
582
|
+
this.context.variables.forEach((v, k) => varContext[k] = v);
|
|
583
|
+
evaluator.updateContext(varContext);
|
|
584
|
+
return evaluator.evaluate(expr);
|
|
503
585
|
}
|
|
504
586
|
// ============================================================================
|
|
505
587
|
// Node Executors
|
|
506
588
|
// ============================================================================
|
|
507
589
|
async executeOrb(node) {
|
|
590
|
+
const scale = this.context.currentScale || 1;
|
|
591
|
+
const adjustedPos = node.position ? {
|
|
592
|
+
x: node.position.x * scale,
|
|
593
|
+
y: node.position.y * scale,
|
|
594
|
+
z: node.position.z * scale
|
|
595
|
+
} : { x: 0, y: 0, z: 0 };
|
|
508
596
|
if (node.position) {
|
|
509
|
-
this.context.spatialMemory.set(node.name,
|
|
597
|
+
this.context.spatialMemory.set(node.name, adjustedPos);
|
|
598
|
+
}
|
|
599
|
+
const hologram = node.hologram ? {
|
|
600
|
+
...node.hologram,
|
|
601
|
+
size: (node.hologram.size || 1) * scale
|
|
602
|
+
} : void 0;
|
|
603
|
+
const evaluatedProperties = {};
|
|
604
|
+
for (const [key, val] of Object.entries(node.properties)) {
|
|
605
|
+
if (typeof val === "string") {
|
|
606
|
+
evaluatedProperties[key] = this.evaluateExpression(val);
|
|
607
|
+
} else {
|
|
608
|
+
evaluatedProperties[key] = val;
|
|
609
|
+
}
|
|
510
610
|
}
|
|
511
611
|
const orbData = {
|
|
512
612
|
__type: "orb",
|
|
513
613
|
name: node.name,
|
|
514
|
-
properties:
|
|
515
|
-
|
|
516
|
-
|
|
614
|
+
properties: evaluatedProperties,
|
|
615
|
+
traits: node.directives?.filter((d) => d.type === "trait").map((d) => d.name) || [],
|
|
616
|
+
directives: node.directives || [],
|
|
617
|
+
position: adjustedPos,
|
|
618
|
+
hologram,
|
|
517
619
|
created: Date.now(),
|
|
518
620
|
// Methods bound to this orb
|
|
519
621
|
show: () => this.builtinFunctions.get("show")([node.name]),
|
|
@@ -521,16 +623,19 @@ var HoloScriptRuntime = class {
|
|
|
521
623
|
pulse: (opts) => this.builtinFunctions.get("pulse")([node.name, opts])
|
|
522
624
|
};
|
|
523
625
|
this.context.variables.set(node.name, orbData);
|
|
524
|
-
if (
|
|
525
|
-
this.context.hologramState.set(node.name,
|
|
626
|
+
if (hologram) {
|
|
627
|
+
this.context.hologramState.set(node.name, hologram);
|
|
628
|
+
}
|
|
629
|
+
if (node.directives) {
|
|
630
|
+
this.applyDirectives(node);
|
|
526
631
|
}
|
|
527
|
-
this.createParticleEffect(`${node.name}_creation`,
|
|
528
|
-
logger.info("Orb created", { name: node.name, properties: Object.keys(node.properties) });
|
|
632
|
+
this.createParticleEffect(`${node.name}_creation`, adjustedPos, "#00ffff", 20);
|
|
633
|
+
logger.info("Orb created", { name: node.name, properties: Object.keys(node.properties), scale });
|
|
529
634
|
return {
|
|
530
635
|
success: true,
|
|
531
636
|
output: orbData,
|
|
532
|
-
hologram
|
|
533
|
-
spatialPosition:
|
|
637
|
+
hologram,
|
|
638
|
+
spatialPosition: adjustedPos
|
|
534
639
|
};
|
|
535
640
|
}
|
|
536
641
|
async executeFunction(node) {
|
|
@@ -1048,7 +1153,7 @@ var HoloScriptRuntime = class {
|
|
|
1048
1153
|
case "count":
|
|
1049
1154
|
return Array.isArray(data) ? data.length : 1;
|
|
1050
1155
|
case "unique":
|
|
1051
|
-
return Array.isArray(data) ?
|
|
1156
|
+
return Array.isArray(data) ? Array.from(new Set(data)) : data;
|
|
1052
1157
|
case "flatten":
|
|
1053
1158
|
return Array.isArray(data) ? data.flat() : data;
|
|
1054
1159
|
case "reverse":
|
|
@@ -1079,6 +1184,13 @@ var HoloScriptRuntime = class {
|
|
|
1079
1184
|
handlers.push(handler);
|
|
1080
1185
|
this.eventHandlers.set(event, handlers);
|
|
1081
1186
|
}
|
|
1187
|
+
/**
|
|
1188
|
+
* Register host function
|
|
1189
|
+
*/
|
|
1190
|
+
registerFunction(name, handler) {
|
|
1191
|
+
this.builtinFunctions.set(name, handler);
|
|
1192
|
+
logger.info(`Host function registered: ${name}`);
|
|
1193
|
+
}
|
|
1082
1194
|
/**
|
|
1083
1195
|
* Remove event handler
|
|
1084
1196
|
*/
|
|
@@ -1141,6 +1253,158 @@ var HoloScriptRuntime = class {
|
|
|
1141
1253
|
anim.startTime = now;
|
|
1142
1254
|
}
|
|
1143
1255
|
}
|
|
1256
|
+
this.updateSystemVariables();
|
|
1257
|
+
}
|
|
1258
|
+
/**
|
|
1259
|
+
* Update real-life and system variables ($time, $user, etc.)
|
|
1260
|
+
*/
|
|
1261
|
+
updateSystemVariables() {
|
|
1262
|
+
const now = /* @__PURE__ */ new Date();
|
|
1263
|
+
this.setVariable("$time", now.toLocaleTimeString());
|
|
1264
|
+
this.setVariable("$date", now.toLocaleDateString());
|
|
1265
|
+
this.setVariable("$timestamp", now.getTime());
|
|
1266
|
+
this.setVariable("$hour", now.getHours());
|
|
1267
|
+
this.setVariable("$minute", now.getMinutes());
|
|
1268
|
+
this.setVariable("$second", now.getSeconds());
|
|
1269
|
+
if (this.getVariable("$user") === void 0) {
|
|
1270
|
+
this.setVariable("$user", {
|
|
1271
|
+
id: "user_123",
|
|
1272
|
+
name: "Alpha Explorer",
|
|
1273
|
+
level: 42,
|
|
1274
|
+
rank: "Legendary",
|
|
1275
|
+
achievements: ["First World", "Spirit Guide"],
|
|
1276
|
+
preferences: { theme: "holographic", language: "en" }
|
|
1277
|
+
});
|
|
1278
|
+
}
|
|
1279
|
+
if (this.getVariable("$location") === void 0) {
|
|
1280
|
+
this.setVariable("$location", {
|
|
1281
|
+
city: "Neo Tokyo",
|
|
1282
|
+
region: "Holo-Sector 7",
|
|
1283
|
+
coordinates: { lat: 35.6895, lng: 139.6917 },
|
|
1284
|
+
altitude: 450
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1287
|
+
if (this.getVariable("$weather") === void 0) {
|
|
1288
|
+
this.setVariable("$weather", {
|
|
1289
|
+
condition: "Neon Mist",
|
|
1290
|
+
temperature: 24,
|
|
1291
|
+
humidity: 65,
|
|
1292
|
+
windSpeed: 12,
|
|
1293
|
+
unit: "C"
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1296
|
+
if (this.getVariable("$wallet") === void 0) {
|
|
1297
|
+
this.setVariable("$wallet", {
|
|
1298
|
+
address: "0xHolo...42ff",
|
|
1299
|
+
balance: 1337.5,
|
|
1300
|
+
currency: "HOLO",
|
|
1301
|
+
network: "MainNet"
|
|
1302
|
+
});
|
|
1303
|
+
}
|
|
1304
|
+
if (this.getVariable("$ai_config") === void 0) {
|
|
1305
|
+
const savedKeys = typeof localStorage !== "undefined" ? localStorage.getItem("brittney_api_keys") : null;
|
|
1306
|
+
let configuredCount = 0;
|
|
1307
|
+
if (savedKeys) {
|
|
1308
|
+
try {
|
|
1309
|
+
const keys = JSON.parse(savedKeys);
|
|
1310
|
+
configuredCount = Object.values(keys).filter((k) => !!k).length;
|
|
1311
|
+
} catch (e) {
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
this.setVariable("$ai_config", {
|
|
1315
|
+
status: configuredCount > 0 ? "configured" : "pending",
|
|
1316
|
+
providerCount: configuredCount,
|
|
1317
|
+
lastUpdated: Date.now()
|
|
1318
|
+
});
|
|
1319
|
+
}
|
|
1320
|
+
if (this.getVariable("$chat_status") === void 0) {
|
|
1321
|
+
this.setVariable("$chat_status", {
|
|
1322
|
+
active: true,
|
|
1323
|
+
typing: false,
|
|
1324
|
+
version: "1.0.0-brittney"
|
|
1325
|
+
});
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
// ==========================================================================
|
|
1329
|
+
// COMMERCE PRIMITIVES
|
|
1330
|
+
// ==========================================================================
|
|
1331
|
+
handleShop(args) {
|
|
1332
|
+
const config = args[0] || {};
|
|
1333
|
+
this.emit("shop", config);
|
|
1334
|
+
return { success: true, type: "shop", config };
|
|
1335
|
+
}
|
|
1336
|
+
handleInventory(args) {
|
|
1337
|
+
const item = args[0];
|
|
1338
|
+
const action = args[1] || "add";
|
|
1339
|
+
this.emit("inventory", { item, action });
|
|
1340
|
+
return { success: true, item, action };
|
|
1341
|
+
}
|
|
1342
|
+
handlePurchase(args) {
|
|
1343
|
+
const productId = args[0];
|
|
1344
|
+
this.emit("purchase", { productId });
|
|
1345
|
+
return { success: true, productId, status: "pending" };
|
|
1346
|
+
}
|
|
1347
|
+
// ==========================================================================
|
|
1348
|
+
// SOCIAL PRIMITIVES
|
|
1349
|
+
// ==========================================================================
|
|
1350
|
+
handlePresence(args) {
|
|
1351
|
+
const config = args[0] || {};
|
|
1352
|
+
this.emit("presence", config);
|
|
1353
|
+
return { success: true, active: true };
|
|
1354
|
+
}
|
|
1355
|
+
handleInvite(args) {
|
|
1356
|
+
const userId = args[0];
|
|
1357
|
+
this.emit("invite", { userId });
|
|
1358
|
+
return { success: true, userId };
|
|
1359
|
+
}
|
|
1360
|
+
handleShare(args) {
|
|
1361
|
+
const scriptId = args[0];
|
|
1362
|
+
const targetUserId = args[1];
|
|
1363
|
+
this.emit("share", { scriptId, targetUserId });
|
|
1364
|
+
return { success: true, scriptId };
|
|
1365
|
+
}
|
|
1366
|
+
// ==========================================================================
|
|
1367
|
+
// PHYSICS PRIMITIVES
|
|
1368
|
+
// ==========================================================================
|
|
1369
|
+
handlePhysics(args) {
|
|
1370
|
+
const config = args[0] || {};
|
|
1371
|
+
this.emit("physics", config);
|
|
1372
|
+
return { success: true, enabled: config.enabled !== false };
|
|
1373
|
+
}
|
|
1374
|
+
handleGravity(args) {
|
|
1375
|
+
const value = args[0] ?? 9.81;
|
|
1376
|
+
this.emit("gravity", { value });
|
|
1377
|
+
return { success: true, value };
|
|
1378
|
+
}
|
|
1379
|
+
handleCollide(args) {
|
|
1380
|
+
const target = args[0];
|
|
1381
|
+
const handler = args[1];
|
|
1382
|
+
this.emit("collide", { target, handler });
|
|
1383
|
+
return { success: true, target };
|
|
1384
|
+
}
|
|
1385
|
+
/**
|
|
1386
|
+
* Handle calculate_arc(start, end, speed)
|
|
1387
|
+
*/
|
|
1388
|
+
handleCalculateArc(args) {
|
|
1389
|
+
if (args.length < 3) return { x: 0, y: 0, z: 0 };
|
|
1390
|
+
const start = args[0];
|
|
1391
|
+
const end = args[1];
|
|
1392
|
+
const speed = args[2];
|
|
1393
|
+
const dx = end.x - start.x;
|
|
1394
|
+
const dz = end.z - start.z;
|
|
1395
|
+
const dy = end.y - start.y;
|
|
1396
|
+
const dist = Math.sqrt(dx * dx + dz * dz);
|
|
1397
|
+
if (dist < 0.1) return { x: 0, y: speed, z: 0 };
|
|
1398
|
+
const t = dist / speed;
|
|
1399
|
+
const vx = dx / t;
|
|
1400
|
+
const vz = dz / t;
|
|
1401
|
+
const vy = dy / t + 0.5 * 9.81 * t;
|
|
1402
|
+
return { x: vx, y: vy, z: vz };
|
|
1403
|
+
}
|
|
1404
|
+
handleAnimate(args) {
|
|
1405
|
+
const options = args[0] || {};
|
|
1406
|
+
this.emit("animate", options);
|
|
1407
|
+
return { success: true, options };
|
|
1144
1408
|
}
|
|
1145
1409
|
applyEasing(t, easing) {
|
|
1146
1410
|
switch (easing) {
|
|
@@ -1277,9 +1541,135 @@ var HoloScriptRuntime = class {
|
|
|
1277
1541
|
connections: [],
|
|
1278
1542
|
spatialMemory: /* @__PURE__ */ new Map(),
|
|
1279
1543
|
hologramState: /* @__PURE__ */ new Map(),
|
|
1280
|
-
executionStack: []
|
|
1544
|
+
executionStack: [],
|
|
1545
|
+
currentScale: 1,
|
|
1546
|
+
scaleMagnitude: "standard",
|
|
1547
|
+
focusHistory: [],
|
|
1548
|
+
environment: {},
|
|
1549
|
+
templates: /* @__PURE__ */ new Map(),
|
|
1550
|
+
state: createState({})
|
|
1551
|
+
};
|
|
1552
|
+
}
|
|
1553
|
+
async executeScale(node) {
|
|
1554
|
+
const parentScale = this.context.currentScale;
|
|
1555
|
+
this.context.currentScale *= node.multiplier;
|
|
1556
|
+
this.context.scaleMagnitude = node.magnitude;
|
|
1557
|
+
logger.info("Scale context entering", { magnitude: node.magnitude, multiplier: this.context.currentScale });
|
|
1558
|
+
this.emit("scale:change", { multiplier: this.context.currentScale, magnitude: node.magnitude });
|
|
1559
|
+
const results = await this.executeProgram(node.body, this.context.executionStack.length);
|
|
1560
|
+
this.context.currentScale = parentScale;
|
|
1561
|
+
this.emit("scale:change", { multiplier: this.context.currentScale });
|
|
1562
|
+
return {
|
|
1563
|
+
success: results.every((r) => r.success),
|
|
1564
|
+
output: `Executed scale block: ${node.magnitude}`
|
|
1281
1565
|
};
|
|
1282
1566
|
}
|
|
1567
|
+
async executeFocus(node) {
|
|
1568
|
+
this.context.focusHistory.push(node.target);
|
|
1569
|
+
const results = await this.executeProgram(node.body, this.context.executionStack.length);
|
|
1570
|
+
return {
|
|
1571
|
+
success: results.every((r) => r.success),
|
|
1572
|
+
output: `Focused on ${node.target}`
|
|
1573
|
+
};
|
|
1574
|
+
}
|
|
1575
|
+
async executeEnvironment(node) {
|
|
1576
|
+
this.context.environment = { ...this.context.environment, ...node.settings };
|
|
1577
|
+
return { success: true, output: "Environment updated" };
|
|
1578
|
+
}
|
|
1579
|
+
async executeComposition(node) {
|
|
1580
|
+
return {
|
|
1581
|
+
success: (await this.executeProgram(node.children, this.context.executionStack.length)).every((r) => r.success),
|
|
1582
|
+
output: `Composition ${node.name} executed`
|
|
1583
|
+
};
|
|
1584
|
+
}
|
|
1585
|
+
async executeTemplate(node) {
|
|
1586
|
+
this.context.templates.set(node.name, node);
|
|
1587
|
+
return { success: true, output: `Template ${node.name} registered` };
|
|
1588
|
+
}
|
|
1589
|
+
async executeServerNode(node) {
|
|
1590
|
+
if (this.context.mode === "public") {
|
|
1591
|
+
return { success: false, error: "SecurityViolation: Server creation blocked in public mode.", executionTime: 0 };
|
|
1592
|
+
}
|
|
1593
|
+
logger.info(`Starting server on port ${node.port}`);
|
|
1594
|
+
return {
|
|
1595
|
+
success: true,
|
|
1596
|
+
output: `Server listening on port ${node.port}`,
|
|
1597
|
+
hologram: node.hologram,
|
|
1598
|
+
executionTime: 0
|
|
1599
|
+
};
|
|
1600
|
+
}
|
|
1601
|
+
async executeDatabaseNode(node) {
|
|
1602
|
+
if (this.context.mode === "public") {
|
|
1603
|
+
return { success: false, error: "SecurityViolation: DB access blocked in public mode.", executionTime: 0 };
|
|
1604
|
+
}
|
|
1605
|
+
logger.info(`Executing Query: ${node.query}`);
|
|
1606
|
+
return {
|
|
1607
|
+
success: true,
|
|
1608
|
+
output: `Query executed: ${node.query}`,
|
|
1609
|
+
hologram: node.hologram,
|
|
1610
|
+
executionTime: 0
|
|
1611
|
+
};
|
|
1612
|
+
}
|
|
1613
|
+
async executeFetchNode(node) {
|
|
1614
|
+
if (this.context.mode === "public") {
|
|
1615
|
+
return { success: false, error: "SecurityViolation: External fetch blocked in public mode.", executionTime: 0 };
|
|
1616
|
+
}
|
|
1617
|
+
logger.info(`Fetching: ${node.url}`);
|
|
1618
|
+
return {
|
|
1619
|
+
success: true,
|
|
1620
|
+
output: `Fetched data from ${node.url}`,
|
|
1621
|
+
hologram: node.hologram,
|
|
1622
|
+
executionTime: 0
|
|
1623
|
+
};
|
|
1624
|
+
}
|
|
1625
|
+
async executeTarget(node) {
|
|
1626
|
+
const target = this.context.functions.get(node.target);
|
|
1627
|
+
if (!target) {
|
|
1628
|
+
return {
|
|
1629
|
+
success: false,
|
|
1630
|
+
error: `Function ${node.target} not found`,
|
|
1631
|
+
executionTime: 0
|
|
1632
|
+
};
|
|
1633
|
+
}
|
|
1634
|
+
const result = await this.executeFunction(target);
|
|
1635
|
+
this.createExecutionEffect(node.target, target.position || { x: 0, y: 0, z: 0 });
|
|
1636
|
+
return {
|
|
1637
|
+
success: true,
|
|
1638
|
+
output: `Executed ${node.target}`,
|
|
1639
|
+
hologram: {
|
|
1640
|
+
shape: "sphere",
|
|
1641
|
+
color: "#ff4500",
|
|
1642
|
+
size: 1.2,
|
|
1643
|
+
glow: true,
|
|
1644
|
+
interactive: false
|
|
1645
|
+
},
|
|
1646
|
+
executionTime: result.executionTime
|
|
1647
|
+
};
|
|
1648
|
+
}
|
|
1649
|
+
async executeStateDeclaration(node) {
|
|
1650
|
+
const stateDirective = node.directives?.find((d) => d.type === "state");
|
|
1651
|
+
if (stateDirective) {
|
|
1652
|
+
this.context.state.update(stateDirective.body);
|
|
1653
|
+
}
|
|
1654
|
+
return { success: true, output: "State updated" };
|
|
1655
|
+
}
|
|
1656
|
+
applyDirectives(node) {
|
|
1657
|
+
if (!node.directives) return;
|
|
1658
|
+
for (const d of node.directives) {
|
|
1659
|
+
if (d.type === "trait") {
|
|
1660
|
+
logger.info(`Applying trait ${d.name} to ${node.type}`);
|
|
1661
|
+
if (d.name === "chat") {
|
|
1662
|
+
this.emit("show-chat", d.config);
|
|
1663
|
+
}
|
|
1664
|
+
} else if (d.type === "state") {
|
|
1665
|
+
this.context.state.update(d.body);
|
|
1666
|
+
} else if (d.type === "lifecycle") {
|
|
1667
|
+
if (d.hook === "on_mount") {
|
|
1668
|
+
this.evaluateExpression(d.body);
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1283
1673
|
getExecutionHistory() {
|
|
1284
1674
|
return [...this.executionHistory];
|
|
1285
1675
|
}
|
|
@@ -1289,8 +1679,11 @@ var HoloScriptRuntime = class {
|
|
|
1289
1679
|
getCallStack() {
|
|
1290
1680
|
return [...this.callStack];
|
|
1291
1681
|
}
|
|
1682
|
+
getState() {
|
|
1683
|
+
return this.context.state.getSnapshot();
|
|
1684
|
+
}
|
|
1292
1685
|
};
|
|
1293
1686
|
|
|
1294
1687
|
export { HoloScriptRuntime };
|
|
1295
|
-
//# sourceMappingURL=chunk-
|
|
1296
|
-
//# sourceMappingURL=chunk-
|
|
1688
|
+
//# sourceMappingURL=chunk-AFFVFO4D.js.map
|
|
1689
|
+
//# sourceMappingURL=chunk-AFFVFO4D.js.map
|