node-lab-mcp 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +156 -56
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -25646,18 +25646,20 @@ var AcademySink = class extends BenchNode {
|
|
|
25646
25646
|
}
|
|
25647
25647
|
};
|
|
25648
25648
|
var ACADEMY_IN = [
|
|
25649
|
-
{ type:
|
|
25650
|
-
{ type:
|
|
25651
|
-
{ type: 1 /* Number */, name: "DATA IN
|
|
25652
|
-
{ type: 1 /* Number */, name: "DATA IN
|
|
25653
|
-
{ type: 1 /* Number */, name: "DATA IN
|
|
25649
|
+
{ type: 1 /* Number */, name: "DATA IN X1" },
|
|
25650
|
+
{ type: 1 /* Number */, name: "DATA IN X2" },
|
|
25651
|
+
{ type: 1 /* Number */, name: "DATA IN X3" },
|
|
25652
|
+
{ type: 1 /* Number */, name: "DATA IN X4" },
|
|
25653
|
+
{ type: 1 /* Number */, name: "DATA IN X5" },
|
|
25654
|
+
{ type: 1 /* Number */, name: "DATA IN X6" }
|
|
25654
25655
|
];
|
|
25655
25656
|
var ACADEMY_OUT = [
|
|
25656
|
-
{ type:
|
|
25657
|
-
{ type:
|
|
25658
|
-
{ type: 1 /* Number */, name: "DATA OUT
|
|
25659
|
-
{ type: 1 /* Number */, name: "DATA OUT
|
|
25660
|
-
{ type: 1 /* Number */, name: "DATA OUT
|
|
25657
|
+
{ type: 1 /* Number */, name: "DATA OUT A1" },
|
|
25658
|
+
{ type: 1 /* Number */, name: "DATA OUT A2" },
|
|
25659
|
+
{ type: 1 /* Number */, name: "DATA OUT A3" },
|
|
25660
|
+
{ type: 1 /* Number */, name: "DATA OUT A4" },
|
|
25661
|
+
{ type: 1 /* Number */, name: "DATA OUT A5" },
|
|
25662
|
+
{ type: 1 /* Number */, name: "DATA OUT A6" }
|
|
25661
25663
|
];
|
|
25662
25664
|
var TwoInGate = class extends BenchNode {
|
|
25663
25665
|
a;
|
|
@@ -26013,10 +26015,10 @@ var Button = class extends BenchNode {
|
|
|
26013
26015
|
}
|
|
26014
26016
|
};
|
|
26015
26017
|
var Joystick = class extends BenchNode {
|
|
26016
|
-
constructor(id,
|
|
26018
|
+
constructor(id, axis) {
|
|
26017
26019
|
super(id);
|
|
26018
|
-
this.
|
|
26019
|
-
if (
|
|
26020
|
+
this.axis = axis;
|
|
26021
|
+
if (axis === "xy" || axis === "cross") {
|
|
26020
26022
|
this.addPort(1 /* Number */, false, "X+");
|
|
26021
26023
|
this.addPort(1 /* Number */, false, "X-");
|
|
26022
26024
|
this.addPort(1 /* Number */, false, "Y+");
|
|
@@ -26028,6 +26030,9 @@ var Joystick = class extends BenchNode {
|
|
|
26028
26030
|
}
|
|
26029
26031
|
x = 0;
|
|
26030
26032
|
y = 0;
|
|
26033
|
+
get twoAxis() {
|
|
26034
|
+
return this.axis === "xy" || this.axis === "cross";
|
|
26035
|
+
}
|
|
26031
26036
|
evaluate() {
|
|
26032
26037
|
const DZ = 0.08;
|
|
26033
26038
|
const dz = (t) => {
|
|
@@ -26036,11 +26041,14 @@ var Joystick = class extends BenchNode {
|
|
|
26036
26041
|
};
|
|
26037
26042
|
const pos = (t) => Math.round(Math.max(0, dz(t)) * 65535);
|
|
26038
26043
|
const neg = (t) => Math.round(Math.max(0, -dz(t)) * 65535);
|
|
26039
|
-
if (this.
|
|
26044
|
+
if (this.axis === "xy" || this.axis === "cross") {
|
|
26040
26045
|
this.outputs[0].value = pos(this.x);
|
|
26041
26046
|
this.outputs[1].value = neg(this.x);
|
|
26042
26047
|
this.outputs[2].value = pos(this.y);
|
|
26043
26048
|
this.outputs[3].value = neg(this.y);
|
|
26049
|
+
} else if (this.axis === "x") {
|
|
26050
|
+
this.outputs[0].value = pos(this.x);
|
|
26051
|
+
this.outputs[1].value = neg(this.x);
|
|
26044
26052
|
} else {
|
|
26045
26053
|
this.outputs[0].value = pos(this.y);
|
|
26046
26054
|
this.outputs[1].value = neg(this.y);
|
|
@@ -26155,6 +26163,13 @@ var LightDisplay = class extends BenchNode {
|
|
|
26155
26163
|
evaluate() {
|
|
26156
26164
|
}
|
|
26157
26165
|
};
|
|
26166
|
+
var Notes = class extends BenchNode {
|
|
26167
|
+
text = "# Notes\n\nDouble-click to edit. Supports **markdown** \u2014 headings, lists, `code`, [links](https://example.com).";
|
|
26168
|
+
width = 280;
|
|
26169
|
+
height = 200;
|
|
26170
|
+
evaluate() {
|
|
26171
|
+
}
|
|
26172
|
+
};
|
|
26158
26173
|
var Oscilloscope = class extends BenchNode {
|
|
26159
26174
|
input;
|
|
26160
26175
|
samples = [];
|
|
@@ -26551,11 +26566,49 @@ var VectorRotate = class extends BenchNode {
|
|
|
26551
26566
|
}
|
|
26552
26567
|
};
|
|
26553
26568
|
var SHIP_THRUST_ACCEL = 6;
|
|
26554
|
-
var SHIP_ANG_ACCEL =
|
|
26569
|
+
var SHIP_ANG_ACCEL = 0.625;
|
|
26555
26570
|
var SHIP_DRAG = 0;
|
|
26556
26571
|
var SHIP_DAMPER_MAX = 3;
|
|
26557
26572
|
var SHIP_ANG_DAMPER_MAX = 3;
|
|
26558
|
-
var
|
|
26573
|
+
var COMMON_ELEMENTS = [26, 14, 29, 22, 28];
|
|
26574
|
+
var RARE_ELEMENTS = [79, 78, 48, 82, 47, 92, 74];
|
|
26575
|
+
var MAGNETOSPHERE_M = 2500;
|
|
26576
|
+
var STATION_SAFE_M = 500;
|
|
26577
|
+
function pickComposition(pool) {
|
|
26578
|
+
const n = Math.random() < 0.5 ? 2 : 3;
|
|
26579
|
+
const picked = [];
|
|
26580
|
+
while (picked.length < n) {
|
|
26581
|
+
const e = pool[Math.floor(Math.random() * pool.length)];
|
|
26582
|
+
if (!picked.includes(e)) picked.push(e);
|
|
26583
|
+
}
|
|
26584
|
+
const weights = picked.map(() => 0.2 + Math.random());
|
|
26585
|
+
const sum = weights.reduce((a, b) => a + b, 0);
|
|
26586
|
+
const comp = {};
|
|
26587
|
+
picked.forEach((e, i) => comp[e] = Math.round(weights[i] / sum * 100) / 100);
|
|
26588
|
+
const total = Object.values(comp).reduce((a, b) => a + b, 0);
|
|
26589
|
+
const delta = Math.round((1 - total) * 100) / 100;
|
|
26590
|
+
if (delta !== 0) comp[picked[0]] = Math.round((comp[picked[0]] + delta) * 100) / 100;
|
|
26591
|
+
return comp;
|
|
26592
|
+
}
|
|
26593
|
+
function makeAsteroidField() {
|
|
26594
|
+
const out = [];
|
|
26595
|
+
const TOTAL = 400;
|
|
26596
|
+
for (let i = 0; i < TOTAL; i++) {
|
|
26597
|
+
const inner = i < 48;
|
|
26598
|
+
const rMin = inner ? 100 : STATION_SAFE_M;
|
|
26599
|
+
const rMax = inner ? STATION_SAFE_M : MAGNETOSPHERE_M - 100;
|
|
26600
|
+
const r = Math.cbrt(rMin ** 3 + Math.random() * (rMax ** 3 - rMin ** 3));
|
|
26601
|
+
const u = Math.random() * 2 - 1, phi = Math.random() * Math.PI * 2;
|
|
26602
|
+
const s = Math.sqrt(1 - u * u);
|
|
26603
|
+
const pos = vec(r * s * Math.cos(phi), r * u, r * s * Math.sin(phi), 0);
|
|
26604
|
+
const t = Math.random();
|
|
26605
|
+
const radius = 13 + t * 7;
|
|
26606
|
+
const mass = Math.round(30 + t * 70);
|
|
26607
|
+
const comp = pickComposition(inner ? COMMON_ELEMENTS : RARE_ELEMENTS);
|
|
26608
|
+
out.push({ id: `a${i}`, pos, vel: vec(), radius, mass, comp });
|
|
26609
|
+
}
|
|
26610
|
+
return out;
|
|
26611
|
+
}
|
|
26559
26612
|
var STATION_LOCK_RADIUS = 14;
|
|
26560
26613
|
var BEAM_SLEW = 5 * Math.PI / 180;
|
|
26561
26614
|
var BEAM_GIMBAL_LIMIT = 80 * Math.PI / 180;
|
|
@@ -26578,9 +26631,13 @@ var SHIP_STATE = {
|
|
|
26578
26631
|
orient: vec(0, 0, 0, 1),
|
|
26579
26632
|
dir: vec(0, 0, 1, 0),
|
|
26580
26633
|
asteroid: vec(),
|
|
26634
|
+
asteroidField: [],
|
|
26581
26635
|
station: vec(),
|
|
26582
26636
|
lockedTarget: null,
|
|
26583
|
-
beam: { aim: vec(0, 0, 1, 0), massRange: false, spectro: false }
|
|
26637
|
+
beam: { aim: vec(0, 0, 1, 0), massRange: false, spectro: false },
|
|
26638
|
+
respawnAt: 0,
|
|
26639
|
+
magnetosphere: MAGNETOSPHERE_M,
|
|
26640
|
+
stationSafe: STATION_SAFE_M
|
|
26584
26641
|
};
|
|
26585
26642
|
var ShipSim = class {
|
|
26586
26643
|
pos = vec(100, 0, 0, 0);
|
|
@@ -26591,10 +26648,11 @@ var ShipSim = class {
|
|
|
26591
26648
|
// quaternion
|
|
26592
26649
|
angVel = vec();
|
|
26593
26650
|
// body-frame angular velocity (rad/s) — persists, so the ship coasts its spin
|
|
26594
|
-
// ── world, station = origin (0,0,0). Ship starts at (100,0,0)
|
|
26595
|
-
//
|
|
26596
|
-
|
|
26597
|
-
|
|
26651
|
+
// ── world, station = origin (0,0,0). Ship starts at (100,0,0). 100 procedurally placed asteroids
|
|
26652
|
+
// (asteroidField) live around the station, inner shell (60–500 m) = common ores, outer shell
|
|
26653
|
+
// (500–2500 m) = rare. `asteroid` is the currently-active scan target (mutated by LOCK BEAM). ──
|
|
26654
|
+
asteroidField = makeAsteroidField();
|
|
26655
|
+
asteroid = this.asteroidField[0];
|
|
26598
26656
|
station = { pos: vec(0, 0, 0, 0) };
|
|
26599
26657
|
lockMode = 0;
|
|
26600
26658
|
// 1 CLEAR · 2 LASER(mass/rock) · 3 PROCESSING PLANT(station) · 4 SHOP · 5 MAILING GUN · 6 CUSTOM (0 = none)
|
|
@@ -26628,20 +26686,22 @@ var ShipSim = class {
|
|
|
26628
26686
|
const a = this.beam.aim;
|
|
26629
26687
|
const d = qrotate(this.orient, qnormalize({ x: a.x, y: a.y, z: a.z, w: 0 }));
|
|
26630
26688
|
let bestT = Infinity;
|
|
26631
|
-
let
|
|
26632
|
-
const
|
|
26633
|
-
|
|
26634
|
-
bestT
|
|
26635
|
-
|
|
26689
|
+
let bestAst = null;
|
|
26690
|
+
for (const ast of this.asteroidField) {
|
|
26691
|
+
const t = raySphereHit(this.pos, d, ast.pos, ast.radius);
|
|
26692
|
+
if (t !== null && t < bestT) {
|
|
26693
|
+
bestT = t;
|
|
26694
|
+
bestAst = ast;
|
|
26695
|
+
}
|
|
26636
26696
|
}
|
|
26637
26697
|
const ts = raySphereHit(this.pos, d, this.station.pos, STATION_LOCK_RADIUS);
|
|
26638
26698
|
if (ts !== null && ts < bestT) {
|
|
26639
|
-
|
|
26640
|
-
|
|
26641
|
-
}
|
|
26642
|
-
|
|
26643
|
-
this.lockedTarget = { pos: { ...
|
|
26644
|
-
this.lockKind =
|
|
26699
|
+
this.lockedTarget = { pos: { ...this.station.pos }, vel: vec() };
|
|
26700
|
+
this.lockKind = "station";
|
|
26701
|
+
} else if (bestAst) {
|
|
26702
|
+
this.asteroid = bestAst;
|
|
26703
|
+
this.lockedTarget = { pos: { ...bestAst.pos }, vel: vec() };
|
|
26704
|
+
this.lockKind = "asteroid";
|
|
26645
26705
|
} else {
|
|
26646
26706
|
this.lockedTarget = null;
|
|
26647
26707
|
this.lockKind = null;
|
|
@@ -26663,7 +26723,7 @@ var ShipSim = class {
|
|
|
26663
26723
|
this.lockKind = "station";
|
|
26664
26724
|
}
|
|
26665
26725
|
/**
|
|
26666
|
-
* LOCK MODE selects the target type. 6 CUSTOM tracks the CUSTOM
|
|
26726
|
+
* LOCK MODE selects the target type. 6 CUSTOM tracks the CUSTOM TGT vector live; the others apply on
|
|
26667
26727
|
* *change* (1 CLEAR wipes, 2 LASER → asteroid/rock, 3–5 → station), so a manual LOCK BEAM/STATION press can
|
|
26668
26728
|
* override in between. 0 = no command (unwired) → leaves the current lock alone.
|
|
26669
26729
|
*/
|
|
@@ -26711,6 +26771,11 @@ var ShipSim = class {
|
|
|
26711
26771
|
this.pos.x += this.vel.x * dt;
|
|
26712
26772
|
this.pos.y += this.vel.y * dt;
|
|
26713
26773
|
this.pos.z += this.vel.z * dt;
|
|
26774
|
+
const r = Math.hypot(this.pos.x, this.pos.y, this.pos.z);
|
|
26775
|
+
if (r > MAGNETOSPHERE_M) {
|
|
26776
|
+
this.reset();
|
|
26777
|
+
SHIP_STATE.respawnAt = Date.now();
|
|
26778
|
+
}
|
|
26714
26779
|
const ta = SHIP_ANG_ACCEL;
|
|
26715
26780
|
this.angVel.x += torqueBody.x * ta * dt;
|
|
26716
26781
|
this.angVel.y += torqueBody.y * ta * dt;
|
|
@@ -26737,6 +26802,7 @@ var ShipSim = class {
|
|
|
26737
26802
|
SHIP_STATE.orient = this.orient;
|
|
26738
26803
|
SHIP_STATE.dir = this.direction();
|
|
26739
26804
|
SHIP_STATE.asteroid = this.asteroid.pos;
|
|
26805
|
+
SHIP_STATE.asteroidField = this.asteroidField;
|
|
26740
26806
|
SHIP_STATE.station = this.station.pos;
|
|
26741
26807
|
SHIP_STATE.lockedTarget = this.lockedTarget ? this.lockedTarget.pos : null;
|
|
26742
26808
|
SHIP_STATE.beam = this.beam;
|
|
@@ -26771,24 +26837,32 @@ var ProximitySensor = class extends BenchNode {
|
|
|
26771
26837
|
this.out = this.addPort(1 /* Number */, false, "PROXIMITY");
|
|
26772
26838
|
}
|
|
26773
26839
|
evaluate() {
|
|
26774
|
-
const p = SHIP_SIM.pos,
|
|
26775
|
-
|
|
26776
|
-
|
|
26777
|
-
|
|
26840
|
+
const p = SHIP_SIM.pos, s = SHIP_SIM.station.pos;
|
|
26841
|
+
let best = Math.hypot(p.x - s.x, p.y - s.y, p.z - s.z) - STATION_LOCK_RADIUS;
|
|
26842
|
+
for (const ast of SHIP_SIM.asteroidField) {
|
|
26843
|
+
const d2 = Math.hypot(p.x - ast.pos.x, p.y - ast.pos.y, p.z - ast.pos.z) - ast.radius;
|
|
26844
|
+
if (d2 < best) best = d2;
|
|
26845
|
+
}
|
|
26846
|
+
const d = Math.max(0, best);
|
|
26778
26847
|
this.out.value = d >= PROXIMITY_RANGE ? 0 : clampData((1 - d / PROXIMITY_RANGE) * DATA_MAX);
|
|
26779
26848
|
}
|
|
26780
26849
|
};
|
|
26781
26850
|
var SHIP_IN_CONTROLS = [
|
|
26782
26851
|
"THRUST",
|
|
26783
26852
|
"REVERSE",
|
|
26853
|
+
// Order: X+, X-, Y+, Y- so a 2-axis joystick wires straight through (RIGHT→X+, LEFT→X-, UP→Y+, DOWN→Y-).
|
|
26854
|
+
"TRANSLATE RIGHT",
|
|
26855
|
+
"TRANSLATE LEFT",
|
|
26784
26856
|
"TRANSLATE UP",
|
|
26785
26857
|
"TRANSLATE DOWN",
|
|
26858
|
+
// YAW first then PITCH so X+/X- / Y+/Y- on a 2-axis joystick map straight onto YAW LEFT / YAW
|
|
26859
|
+
// RIGHT / PITCH UP / PITCH DOWN without crossed cables.
|
|
26860
|
+
"YAW RIGHT",
|
|
26861
|
+
"YAW LEFT",
|
|
26786
26862
|
"PITCH UP",
|
|
26787
26863
|
"PITCH DOWN",
|
|
26788
|
-
"YAW LEFT",
|
|
26789
|
-
"YAW RIGHT",
|
|
26790
|
-
"ROLL LEFT",
|
|
26791
26864
|
"ROLL RIGHT",
|
|
26865
|
+
"ROLL LEFT",
|
|
26792
26866
|
"LINEAR DAMPER",
|
|
26793
26867
|
"ANGULAR DAMPER"
|
|
26794
26868
|
];
|
|
@@ -26803,17 +26877,19 @@ var ShipIn = class extends BenchNode {
|
|
|
26803
26877
|
evaluate() {
|
|
26804
26878
|
}
|
|
26805
26879
|
refresh() {
|
|
26880
|
+
const FWD = 1, REV = 0.5, STRAFE = 0.5;
|
|
26806
26881
|
const thrustBody = vec(
|
|
26807
|
-
|
|
26808
|
-
|
|
26809
|
-
this.ctl("
|
|
26882
|
+
(this.ctl("TRANSLATE LEFT") - this.ctl("TRANSLATE RIGHT")) * STRAFE,
|
|
26883
|
+
// camera looks +Z; +X is camera-left, so RIGHT must push body −X
|
|
26884
|
+
(this.ctl("TRANSLATE UP") - this.ctl("TRANSLATE DOWN")) * STRAFE,
|
|
26885
|
+
this.ctl("THRUST") * FWD - this.ctl("REVERSE") * REV,
|
|
26810
26886
|
0
|
|
26811
26887
|
);
|
|
26812
26888
|
const torqueBody = vec(
|
|
26813
26889
|
this.ctl("PITCH DOWN") - this.ctl("PITCH UP"),
|
|
26814
26890
|
// pitch about X (DOWN − UP: nose-up is −X)
|
|
26815
|
-
this.ctl("YAW
|
|
26816
|
-
// yaw about Y
|
|
26891
|
+
this.ctl("YAW LEFT") - this.ctl("YAW RIGHT"),
|
|
26892
|
+
// yaw about Y (LEFT yaws nose left)
|
|
26817
26893
|
this.ctl("ROLL RIGHT") - this.ctl("ROLL LEFT"),
|
|
26818
26894
|
// roll about Z
|
|
26819
26895
|
0
|
|
@@ -26824,7 +26900,7 @@ var ShipIn = class extends BenchNode {
|
|
|
26824
26900
|
var SENSORS_IN_PORTS = [
|
|
26825
26901
|
{ type: 1 /* Number */, name: "LOCK MODE" },
|
|
26826
26902
|
// 1 CLEAR … 6 CUSTOM
|
|
26827
|
-
{ type: 3 /* Vector */, name: "CUSTOM
|
|
26903
|
+
{ type: 3 /* Vector */, name: "CUSTOM TGT" },
|
|
26828
26904
|
// used when LOCK MODE = 6
|
|
26829
26905
|
{ type: 1 /* Number */, name: "BEAM X+" },
|
|
26830
26906
|
{ type: 1 /* Number */, name: "BEAM X-" },
|
|
@@ -26865,7 +26941,7 @@ var SensorsIn = class extends BenchNode {
|
|
|
26865
26941
|
evaluate() {
|
|
26866
26942
|
}
|
|
26867
26943
|
refresh() {
|
|
26868
|
-
SHIP_SIM.applyLockMode(Math.round(this.val("LOCK MODE")), this.vecIn("CUSTOM
|
|
26944
|
+
SHIP_SIM.applyLockMode(Math.round(this.val("LOCK MODE")), this.vecIn("CUSTOM TGT"));
|
|
26869
26945
|
const yawRate = (this.val("BEAM X-") - this.val("BEAM X+")) / DATA_MAX;
|
|
26870
26946
|
const pitchRate = (this.val("BEAM Y+") - this.val("BEAM Y-")) / DATA_MAX;
|
|
26871
26947
|
SHIP_SIM.aimBeam(yawRate, pitchRate, Math.round(this.val("ELEMENT")), 0.02);
|
|
@@ -26898,13 +26974,22 @@ var SensorsOut = class extends BenchNode {
|
|
|
26898
26974
|
this.out("LOCKED").value = 0;
|
|
26899
26975
|
}
|
|
26900
26976
|
const b = SHIP_SIM.beam;
|
|
26901
|
-
const a = SHIP_SIM.asteroid;
|
|
26902
26977
|
const bd = qrotate(SHIP_SIM.orient, qnormalize({ x: b.aim.x, y: b.aim.y, z: b.aim.z, w: 0 }));
|
|
26903
|
-
|
|
26904
|
-
|
|
26905
|
-
|
|
26906
|
-
|
|
26907
|
-
|
|
26978
|
+
let bestT = Infinity;
|
|
26979
|
+
let bestAst = null;
|
|
26980
|
+
for (const ast of SHIP_SIM.asteroidField) {
|
|
26981
|
+
const t = raySphereHit(SHIP_SIM.pos, bd, ast.pos, ast.radius);
|
|
26982
|
+
if (t !== null && t < bestT) {
|
|
26983
|
+
bestT = t;
|
|
26984
|
+
bestAst = ast;
|
|
26985
|
+
}
|
|
26986
|
+
}
|
|
26987
|
+
const aHit = bestAst;
|
|
26988
|
+
const hit = bestAst ? bestT : null;
|
|
26989
|
+
this.out("MASS").value = b.massRange && aHit !== null ? clampData(aHit.mass) : 0;
|
|
26990
|
+
this.out("SCAN RANGE").value = b.massRange && aHit !== null && hit !== null ? clampData(hit) : 0;
|
|
26991
|
+
this.out("COMP %").value = b.spectro && aHit !== null ? clampData((aHit.comp[b.element] ?? 0) * DATA_MAX) : 0;
|
|
26992
|
+
this.out("SPECTRO POS").vec = vec(b.aim.x * DATA_MAX, b.aim.y * DATA_MAX, b.aim.z * DATA_MAX, 0);
|
|
26908
26993
|
}
|
|
26909
26994
|
};
|
|
26910
26995
|
var NODE_LIBRARY = [
|
|
@@ -26962,9 +27047,11 @@ var NODE_LIBRARY = [
|
|
|
26962
27047
|
{ kind: "slider", label: "SLIDER", group: "Controls", nodeType: "analog", make: (id) => new AnalogControl(id, false) },
|
|
26963
27048
|
{ kind: "button1", label: "BUTTON", group: "Controls", nodeType: "button", make: (id) => new Button(id, 1) },
|
|
26964
27049
|
{ kind: "button4", label: "4-BUTTON", group: "Controls", nodeType: "button", make: (id) => new Button(id, 4) },
|
|
26965
|
-
{ kind: "joy1", label: "1-AXIS JOYSTICK", group: "Controls", nodeType: "joystick", make: (id) => new Joystick(id,
|
|
26966
|
-
{ kind: "
|
|
26967
|
-
{ kind: "
|
|
27050
|
+
{ kind: "joy1", label: "1-AXIS JOYSTICK Y", group: "Controls", nodeType: "joystick", make: (id) => new Joystick(id, "y") },
|
|
27051
|
+
{ kind: "joy1x", label: "1-AXIS JOYSTICK X", group: "Controls", nodeType: "joystick", make: (id) => new Joystick(id, "x") },
|
|
27052
|
+
{ kind: "joy2", label: "2-AXIS JOYSTICK", group: "Controls", nodeType: "joystick", make: (id) => new Joystick(id, "xy") },
|
|
27053
|
+
{ kind: "joy2cross", label: "2-AXIS JOYSTICK +", group: "Controls", nodeType: "joystick", make: (id) => new Joystick(id, "cross") },
|
|
27054
|
+
{ kind: "throttle", label: "THROTTLE", group: "Controls", nodeType: "throttle", make: (id) => new Joystick(id, "y") },
|
|
26968
27055
|
{ kind: "valuedisp", label: "VALUE DISPLAY", group: "Displays", nodeType: "readout", make: (id) => new ValueDisplay(id) },
|
|
26969
27056
|
{ kind: "elementdisp", label: "ELEMENT DISPLAY", group: "Displays", nodeType: "elementdisp", make: (id) => new ElementDisplay(id) },
|
|
26970
27057
|
{ kind: "counter", label: "COUNTER", group: "Displays", nodeType: "counter", make: (id) => new Counter(id) },
|
|
@@ -26973,6 +27060,7 @@ var NODE_LIBRARY = [
|
|
|
26973
27060
|
{ kind: "linearlight", label: "LINEAR LIGHT", group: "Displays", nodeType: "light", make: (id) => new LightDisplay(id, "linear") },
|
|
26974
27061
|
{ kind: "scope", label: "OSCILLOSCOPE", group: "Displays", nodeType: "scope", make: (id) => new Oscilloscope(id) },
|
|
26975
27062
|
{ kind: "speaker", label: "SPEAKER", group: "Displays", nodeType: "speaker", make: (id) => new Speaker(id) },
|
|
27063
|
+
{ kind: "notes", label: "NOTE", group: "Helpers", nodeType: "notes", make: (id) => new Notes(id) },
|
|
26976
27064
|
{ kind: "sine", label: "SINE WAVE", group: "Signal", nodeType: "sine", make: (id) => new SineWave(id) },
|
|
26977
27065
|
{ kind: "triggered", label: "TRIGGERED", group: "Signal", make: (id) => new Triggered(id) },
|
|
26978
27066
|
{ kind: "proximity", label: "PROXIMITY SENSOR", group: "Sensors", make: (id) => new ProximitySensor(id) }
|
|
@@ -27207,6 +27295,18 @@ live(
|
|
|
27207
27295
|
{ nodeId: external_exports.string(), port: external_exports.string(), value: external_exports.number() },
|
|
27208
27296
|
(a) => ({ cmd: "set_input", nodeId: a.nodeId, port: a.port, value: a.value })
|
|
27209
27297
|
);
|
|
27298
|
+
live(
|
|
27299
|
+
"move_node",
|
|
27300
|
+
"Reposition a node on the canvas in flow-space coordinates (the same units that get_graph reports under position.x/y). Works on every node, fixtures included. Wires re-route automatically.",
|
|
27301
|
+
{ id: external_exports.string(), x: external_exports.number(), y: external_exports.number() },
|
|
27302
|
+
(a) => ({ cmd: "move_node", id: a.id, x: a.x, y: a.y })
|
|
27303
|
+
);
|
|
27304
|
+
live(
|
|
27305
|
+
"set_collapsed",
|
|
27306
|
+
"Collapse a node down to just its header strip (collapsed=true) or restore the full card (collapsed=false). Purely a UI state \u2014 wiring, values, and engine behavior are unchanged.",
|
|
27307
|
+
{ id: external_exports.string(), collapsed: external_exports.boolean() },
|
|
27308
|
+
(a) => ({ cmd: "set_collapsed", id: a.id, collapsed: a.collapsed })
|
|
27309
|
+
);
|
|
27210
27310
|
live(
|
|
27211
27311
|
"clear_graph",
|
|
27212
27312
|
"Wipe all player-added nodes and cables on the live canvas back to the bare fixed walls.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-lab-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "MCP server to drive the IFR Node Lab graph from any MCP client (Claude / Codex / Gemini …) — locally or, via a PartyKit relay, against the deployed app.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|