nucleation 0.10.21 → 0.10.23
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/BlockPos.mjs +1 -0
- package/Dimensions.mjs +1 -0
- package/FieldRange.mjs +1 -0
- package/ItemScale.mjs +1 -0
- package/MeshBounds.mjs +1 -0
- package/MeshProgress.mjs +1 -0
- package/README.md +12 -0
- package/RegionBounds.mjs +1 -0
- package/Schematic.d.mts +32 -0
- package/Schematic.d.ts +32 -0
- package/Schematic.mjs +100 -0
- package/SdfBounds.mjs +1 -0
- package/SdfNormal.mjs +1 -0
- package/TextureInfo.mjs +1 -0
- package/diplomat-runtime.mjs +19 -14
- package/nucleation.wasm +0 -0
- package/package.json +7 -2
- package/renderer/AnimationEffect.d.mts +44 -0
- package/renderer/AnimationEffect.d.ts +44 -0
- package/renderer/AnimationEffect.mjs +204 -0
- package/renderer/Autostack.d.mts +43 -0
- package/renderer/Autostack.d.ts +43 -0
- package/renderer/Autostack.mjs +134 -0
- package/renderer/BlockPos.d.mts +28 -0
- package/renderer/BlockPos.d.ts +28 -0
- package/renderer/BlockPos.mjs +130 -0
- package/renderer/BlockState.d.mts +39 -0
- package/renderer/BlockState.d.ts +39 -0
- package/renderer/BlockState.mjs +134 -0
- package/renderer/Blocks.d.mts +91 -0
- package/renderer/Blocks.d.ts +91 -0
- package/renderer/Blocks.mjs +308 -0
- package/renderer/Brush.d.mts +99 -0
- package/renderer/Brush.d.ts +99 -0
- package/renderer/Brush.mjs +335 -0
- package/renderer/BuildAnimation.d.mts +179 -0
- package/renderer/BuildAnimation.d.ts +179 -0
- package/renderer/BuildAnimation.mjs +1148 -0
- package/renderer/BuildingTool.d.mts +46 -0
- package/renderer/BuildingTool.d.ts +46 -0
- package/renderer/BuildingTool.mjs +121 -0
- package/renderer/CellExecutor.d.mts +51 -0
- package/renderer/CellExecutor.d.ts +51 -0
- package/renderer/CellExecutor.mjs +171 -0
- package/renderer/CellularSdfConfig.d.mts +22 -0
- package/renderer/CellularSdfConfig.d.ts +22 -0
- package/renderer/CellularSdfConfig.mjs +69 -0
- package/renderer/ChunkMeshResult.d.mts +75 -0
- package/renderer/ChunkMeshResult.d.ts +75 -0
- package/renderer/ChunkMeshResult.mjs +253 -0
- package/renderer/CircuitBuilder.d.mts +118 -0
- package/renderer/CircuitBuilder.d.ts +118 -0
- package/renderer/CircuitBuilder.mjs +516 -0
- package/renderer/Curve3D.d.mts +27 -0
- package/renderer/Curve3D.d.ts +27 -0
- package/renderer/Curve3D.mjs +101 -0
- package/renderer/DefinitionRegion.d.mts +274 -0
- package/renderer/DefinitionRegion.d.ts +274 -0
- package/renderer/DefinitionRegion.mjs +973 -0
- package/renderer/Design.d.mts +348 -0
- package/renderer/Design.d.ts +348 -0
- package/renderer/Design.mjs +1334 -0
- package/renderer/Diff.d.mts +88 -0
- package/renderer/Diff.d.ts +88 -0
- package/renderer/Diff.mjs +316 -0
- package/renderer/Dimensions.d.mts +28 -0
- package/renderer/Dimensions.d.ts +28 -0
- package/renderer/Dimensions.mjs +130 -0
- package/renderer/DistanceField.d.mts +39 -0
- package/renderer/DistanceField.d.ts +39 -0
- package/renderer/DistanceField.mjs +114 -0
- package/renderer/ExecutionMode.d.mts +42 -0
- package/renderer/ExecutionMode.d.ts +42 -0
- package/renderer/ExecutionMode.mjs +127 -0
- package/renderer/Field3.d.mts +40 -0
- package/renderer/Field3.d.ts +40 -0
- package/renderer/Field3.mjs +160 -0
- package/renderer/FieldProgram.d.mts +40 -0
- package/renderer/FieldProgram.d.ts +40 -0
- package/renderer/FieldProgram.mjs +167 -0
- package/renderer/FieldProgramBinaryOp.d.mts +42 -0
- package/renderer/FieldProgramBinaryOp.d.ts +42 -0
- package/renderer/FieldProgramBinaryOp.mjs +118 -0
- package/renderer/FieldProgramBuilder.d.mts +104 -0
- package/renderer/FieldProgramBuilder.d.ts +104 -0
- package/renderer/FieldProgramBuilder.mjs +486 -0
- package/renderer/FieldProgramDistanceKind.d.mts +26 -0
- package/renderer/FieldProgramDistanceKind.d.ts +26 -0
- package/renderer/FieldProgramDistanceKind.mjs +78 -0
- package/renderer/FieldProgramUnaryOp.d.mts +34 -0
- package/renderer/FieldProgramUnaryOp.d.ts +34 -0
- package/renderer/FieldProgramUnaryOp.mjs +102 -0
- package/renderer/FieldProgramValueType.d.mts +25 -0
- package/renderer/FieldProgramValueType.d.ts +25 -0
- package/renderer/FieldProgramValueType.mjs +75 -0
- package/renderer/FieldRange.d.mts +15 -0
- package/renderer/FieldRange.d.ts +15 -0
- package/renderer/FieldRange.mjs +109 -0
- package/renderer/Fingerprint.d.mts +44 -0
- package/renderer/Fingerprint.d.ts +44 -0
- package/renderer/Fingerprint.mjs +197 -0
- package/renderer/GeneratedChunk.d.mts +35 -0
- package/renderer/GeneratedChunk.d.ts +35 -0
- package/renderer/GeneratedChunk.mjs +178 -0
- package/renderer/GeneratedChunkCoverage.d.mts +25 -0
- package/renderer/GeneratedChunkCoverage.d.ts +25 -0
- package/renderer/GeneratedChunkCoverage.mjs +75 -0
- package/renderer/GeneratedChunkOverlayMode.d.mts +24 -0
- package/renderer/GeneratedChunkOverlayMode.d.ts +24 -0
- package/renderer/GeneratedChunkOverlayMode.mjs +72 -0
- package/renderer/GeneratedWorldStream.d.mts +28 -0
- package/renderer/GeneratedWorldStream.d.ts +28 -0
- package/renderer/GeneratedWorldStream.mjs +86 -0
- package/renderer/Geo.d.mts +41 -0
- package/renderer/Geo.d.ts +41 -0
- package/renderer/Geo.mjs +121 -0
- package/renderer/Hdl.d.mts +56 -0
- package/renderer/Hdl.d.ts +56 -0
- package/renderer/Hdl.mjs +163 -0
- package/renderer/InterpolationSpace.d.mts +25 -0
- package/renderer/InterpolationSpace.d.ts +25 -0
- package/renderer/InterpolationSpace.mjs +73 -0
- package/renderer/IoLayout.d.mts +26 -0
- package/renderer/IoLayout.d.ts +26 -0
- package/renderer/IoLayout.mjs +81 -0
- package/renderer/IoLayoutBuilder.d.mts +73 -0
- package/renderer/IoLayoutBuilder.d.ts +73 -0
- package/renderer/IoLayoutBuilder.mjs +315 -0
- package/renderer/IoType.d.mts +41 -0
- package/renderer/IoType.d.ts +41 -0
- package/renderer/IoType.mjs +125 -0
- package/renderer/ItemModelConfig.d.mts +65 -0
- package/renderer/ItemModelConfig.d.ts +65 -0
- package/renderer/ItemModelConfig.mjs +223 -0
- package/renderer/ItemModelPackBuilder.d.mts +32 -0
- package/renderer/ItemModelPackBuilder.d.ts +32 -0
- package/renderer/ItemModelPackBuilder.mjs +104 -0
- package/renderer/ItemModelResult.d.mts +72 -0
- package/renderer/ItemModelResult.d.ts +72 -0
- package/renderer/ItemModelResult.mjs +268 -0
- package/renderer/ItemScale.d.mts +31 -0
- package/renderer/ItemScale.d.ts +31 -0
- package/renderer/ItemScale.mjs +133 -0
- package/renderer/LayoutFunction.d.mts +52 -0
- package/renderer/LayoutFunction.d.ts +52 -0
- package/renderer/LayoutFunction.mjs +159 -0
- package/renderer/MchprsWorld.d.mts +131 -0
- package/renderer/MchprsWorld.d.ts +131 -0
- package/renderer/MchprsWorld.mjs +423 -0
- package/renderer/MeshBounds.d.mts +40 -0
- package/renderer/MeshBounds.d.ts +40 -0
- package/renderer/MeshBounds.mjs +181 -0
- package/renderer/MeshConfig.d.mts +101 -0
- package/renderer/MeshConfig.d.ts +101 -0
- package/renderer/MeshConfig.mjs +306 -0
- package/renderer/MeshJob.d.mts +44 -0
- package/renderer/MeshJob.d.ts +44 -0
- package/renderer/MeshJob.mjs +116 -0
- package/renderer/MeshPhase.d.mts +38 -0
- package/renderer/MeshPhase.d.ts +38 -0
- package/renderer/MeshPhase.mjs +90 -0
- package/renderer/MeshProgress.d.mts +32 -0
- package/renderer/MeshProgress.d.ts +32 -0
- package/renderer/MeshProgress.mjs +134 -0
- package/renderer/MeshResult.d.mts +76 -0
- package/renderer/MeshResult.d.ts +76 -0
- package/renderer/MeshResult.mjs +269 -0
- package/renderer/MultiMeshResult.d.mts +50 -0
- package/renderer/MultiMeshResult.d.ts +50 -0
- package/renderer/MultiMeshResult.mjs +166 -0
- package/renderer/Nbt.d.mts +50 -0
- package/renderer/Nbt.d.ts +50 -0
- package/renderer/Nbt.mjs +161 -0
- package/renderer/NucleationError.d.mts +53 -0
- package/renderer/NucleationError.d.ts +53 -0
- package/renderer/NucleationError.mjs +136 -0
- package/renderer/OutputCondition.d.mts +45 -0
- package/renderer/OutputCondition.d.ts +45 -0
- package/renderer/OutputCondition.mjs +129 -0
- package/renderer/Palette.d.mts +157 -0
- package/renderer/Palette.d.ts +157 -0
- package/renderer/Palette.mjs +487 -0
- package/renderer/PaletteBuilder.d.mts +119 -0
- package/renderer/PaletteBuilder.d.ts +119 -0
- package/renderer/PaletteBuilder.mjs +457 -0
- package/renderer/README.md +67 -0
- package/renderer/RawMeshExport.d.mts +74 -0
- package/renderer/RawMeshExport.d.ts +74 -0
- package/renderer/RawMeshExport.mjs +243 -0
- package/renderer/RedstoneGraph.d.mts +58 -0
- package/renderer/RedstoneGraph.d.ts +58 -0
- package/renderer/RedstoneGraph.mjs +242 -0
- package/renderer/RegionBounds.d.mts +41 -0
- package/renderer/RegionBounds.d.ts +41 -0
- package/renderer/RegionBounds.mjs +182 -0
- package/renderer/RenderConfig.d.mts +101 -0
- package/renderer/RenderConfig.d.ts +101 -0
- package/renderer/RenderConfig.mjs +271 -0
- package/renderer/Renderer.d.mts +51 -0
- package/renderer/Renderer.d.ts +51 -0
- package/renderer/Renderer.mjs +219 -0
- package/renderer/ResourcePack.d.mts +105 -0
- package/renderer/ResourcePack.d.ts +105 -0
- package/renderer/ResourcePack.mjs +447 -0
- package/renderer/ResourcePackList.d.mts +32 -0
- package/renderer/ResourcePackList.d.ts +32 -0
- package/renderer/ResourcePackList.mjs +96 -0
- package/renderer/Routing.d.mts +66 -0
- package/renderer/Routing.d.ts +66 -0
- package/renderer/Routing.mjs +220 -0
- package/renderer/Schematic.d.mts +977 -0
- package/renderer/Schematic.d.ts +977 -0
- package/renderer/Schematic.mjs +3820 -0
- package/renderer/SchematicBuilder.d.mts +103 -0
- package/renderer/SchematicBuilder.d.ts +103 -0
- package/renderer/SchematicBuilder.mjs +401 -0
- package/renderer/SchematicRegions.d.mts +93 -0
- package/renderer/SchematicRegions.d.ts +93 -0
- package/renderer/SchematicRegions.mjs +411 -0
- package/renderer/SchematicSplitResult.d.mts +26 -0
- package/renderer/SchematicSplitResult.d.ts +26 -0
- package/renderer/SchematicSplitResult.mjs +84 -0
- package/renderer/Scripting.d.mts +40 -0
- package/renderer/Scripting.d.ts +40 -0
- package/renderer/Scripting.mjs +138 -0
- package/renderer/Sdf.d.mts +234 -0
- package/renderer/Sdf.d.ts +234 -0
- package/renderer/Sdf.mjs +1234 -0
- package/renderer/SdfAxis.d.mts +25 -0
- package/renderer/SdfAxis.d.ts +25 -0
- package/renderer/SdfAxis.mjs +75 -0
- package/renderer/SdfBounds.d.mts +19 -0
- package/renderer/SdfBounds.d.ts +19 -0
- package/renderer/SdfBounds.mjs +161 -0
- package/renderer/SdfCellMode.d.mts +26 -0
- package/renderer/SdfCellMode.d.ts +26 -0
- package/renderer/SdfCellMode.mjs +78 -0
- package/renderer/SdfNormal.d.mts +16 -0
- package/renderer/SdfNormal.d.ts +16 -0
- package/renderer/SdfNormal.mjs +122 -0
- package/renderer/Shape.d.mts +143 -0
- package/renderer/Shape.d.ts +143 -0
- package/renderer/Shape.mjs +458 -0
- package/renderer/SortStrategy.d.mts +86 -0
- package/renderer/SortStrategy.d.ts +86 -0
- package/renderer/SortStrategy.mjs +272 -0
- package/renderer/Store.d.mts +83 -0
- package/renderer/Store.d.ts +83 -0
- package/renderer/Store.mjs +369 -0
- package/renderer/StoreIo.d.mts +71 -0
- package/renderer/StoreIo.d.ts +71 -0
- package/renderer/StoreIo.mjs +292 -0
- package/renderer/TextureAtlas.d.mts +40 -0
- package/renderer/TextureAtlas.d.ts +40 -0
- package/renderer/TextureAtlas.mjs +122 -0
- package/renderer/TextureInfo.d.mts +34 -0
- package/renderer/TextureInfo.d.ts +34 -0
- package/renderer/TextureInfo.mjs +149 -0
- package/renderer/TickSettleMode.d.mts +34 -0
- package/renderer/TickSettleMode.d.ts +34 -0
- package/renderer/TickSettleMode.mjs +84 -0
- package/renderer/TickSimulation.d.mts +572 -0
- package/renderer/TickSimulation.d.ts +572 -0
- package/renderer/TickSimulation.mjs +1299 -0
- package/renderer/TypedCircuitExecutor.d.mts +101 -0
- package/renderer/TypedCircuitExecutor.d.ts +101 -0
- package/renderer/TypedCircuitExecutor.mjs +378 -0
- package/renderer/Value.d.mts +73 -0
- package/renderer/Value.d.ts +73 -0
- package/renderer/Value.mjs +275 -0
- package/renderer/VideoConfig.d.mts +15 -0
- package/renderer/VideoConfig.d.ts +15 -0
- package/renderer/VideoConfig.mjs +44 -0
- package/renderer/VoxelModel.d.mts +34 -0
- package/renderer/VoxelModel.d.ts +34 -0
- package/renderer/VoxelModel.mjs +113 -0
- package/renderer/Voxelizer.d.mts +80 -0
- package/renderer/Voxelizer.d.ts +80 -0
- package/renderer/Voxelizer.mjs +261 -0
- package/renderer/WorldChunkView.d.mts +75 -0
- package/renderer/WorldChunkView.d.ts +75 -0
- package/renderer/WorldChunkView.mjs +224 -0
- package/renderer/WorldGenerator.d.mts +75 -0
- package/renderer/WorldGenerator.d.ts +75 -0
- package/renderer/WorldGenerator.mjs +255 -0
- package/renderer/WorldSink.d.mts +50 -0
- package/renderer/WorldSink.d.ts +50 -0
- package/renderer/WorldSink.mjs +177 -0
- package/renderer/WorldStream.d.mts +45 -0
- package/renderer/WorldStream.d.ts +45 -0
- package/renderer/WorldStream.mjs +184 -0
- package/renderer/WsPartitionHints.d.mts +29 -0
- package/renderer/WsPartitionHints.d.ts +29 -0
- package/renderer/WsPartitionHints.mjs +102 -0
- package/renderer/WsProfile.d.mts +46 -0
- package/renderer/WsProfile.d.ts +46 -0
- package/renderer/WsProfile.mjs +152 -0
- package/renderer/WsRunResult.d.mts +83 -0
- package/renderer/WsRunResult.d.ts +83 -0
- package/renderer/WsRunResult.mjs +326 -0
- package/renderer/WsSegmentJob.d.mts +28 -0
- package/renderer/WsSegmentJob.d.ts +28 -0
- package/renderer/WsSegmentJob.mjs +81 -0
- package/renderer/diplomat-runtime.d.mts +15 -0
- package/renderer/diplomat-runtime.d.ts +15 -0
- package/renderer/diplomat-runtime.mjs +779 -0
- package/renderer/diplomat-wasm.mjs +52 -0
- package/renderer/diplomat.config.mjs +5 -0
- package/renderer/index.d.mts +193 -0
- package/renderer/index.d.ts +193 -0
- package/renderer/index.mjs +196 -0
- package/renderer/nucleation.wasm +0 -0
- package/renderer/veneer/design.d.ts +167 -0
- package/renderer/veneer/design.mjs +480 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/** Typings for the JS design veneer (`nucleation/design`), the 1:1 mirror
|
|
2
|
+
* of `bindings/python/nucleation/design.py` over the generated wasm core. */
|
|
3
|
+
|
|
4
|
+
export type Vec3 = [number, number, number] | number[];
|
|
5
|
+
|
|
6
|
+
export interface GateObj {
|
|
7
|
+
anchor: Vec3;
|
|
8
|
+
step: Vec3;
|
|
9
|
+
name?: string | null;
|
|
10
|
+
}
|
|
11
|
+
/** A bus gate; unnamed gates auto-name `g0`, `g1`, ... in order. */
|
|
12
|
+
export function Gate(anchor: Vec3, step: Vec3, name?: string | null): GateObj;
|
|
13
|
+
|
|
14
|
+
export interface StyleOpts {
|
|
15
|
+
busBlock?: string | null;
|
|
16
|
+
transparentBlock?: string | null;
|
|
17
|
+
/** wire-format spellings pass through untouched */
|
|
18
|
+
bus_block?: string;
|
|
19
|
+
transparent_block?: string;
|
|
20
|
+
}
|
|
21
|
+
/** Per-bus routing style; omitted fields fall back to router defaults. */
|
|
22
|
+
export function Style(opts?: StyleOpts): Record<string, string>;
|
|
23
|
+
|
|
24
|
+
export declare class CheckReport {
|
|
25
|
+
constructor(raw: any);
|
|
26
|
+
raw: any;
|
|
27
|
+
readonly clean: boolean;
|
|
28
|
+
readonly drc: any[];
|
|
29
|
+
readonly lvs: Record<string, any>;
|
|
30
|
+
readonly rules: any[];
|
|
31
|
+
readonly buses: Record<string, any>;
|
|
32
|
+
readonly skew: Record<string, any>;
|
|
33
|
+
get(key: string): any;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export declare class DesignCheckError extends Error {
|
|
37
|
+
report: CheckReport;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export declare class Bus {
|
|
41
|
+
design: Design;
|
|
42
|
+
name: string;
|
|
43
|
+
gateNames: string[];
|
|
44
|
+
readonly state: string;
|
|
45
|
+
readonly skew: { per_bit_rt: number[]; skew_rt: number; max_rt: number };
|
|
46
|
+
moveGate(gate: number | string, anchor: Vec3): { state: string; rerouted_segments: number };
|
|
47
|
+
addGate(anchor: Vec3, step: Vec3, name?: string | null): string;
|
|
48
|
+
rule(rule?: Record<string, any>): void;
|
|
49
|
+
rip(): void;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export declare class Executor {
|
|
53
|
+
cell: any; // core CellExecutor
|
|
54
|
+
static forSchematic(schematic: any, settle?: number): Executor;
|
|
55
|
+
set(name: string, value: number | boolean | string): void;
|
|
56
|
+
get(name: string): number | boolean;
|
|
57
|
+
setInput(name: string, value: number | boolean | string): void;
|
|
58
|
+
readOutput(name: string): any; // core Value
|
|
59
|
+
settle(budget?: number): boolean;
|
|
60
|
+
reset(): void;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export declare class Flat {
|
|
64
|
+
constructor(raw: any);
|
|
65
|
+
raw: any; // core Schematic
|
|
66
|
+
executor(settle?: number): Executor;
|
|
67
|
+
toBytes(format?: string): Uint8Array;
|
|
68
|
+
save(path: string): Promise<void>; // Node only
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface PortDecl {
|
|
72
|
+
anchor: Vec3;
|
|
73
|
+
step: Vec3;
|
|
74
|
+
width: number;
|
|
75
|
+
ty?: "uint" | "bool" | string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export declare class Design {
|
|
79
|
+
readonly raw: any; // core Design
|
|
80
|
+
static create(name: string): Design;
|
|
81
|
+
static forSchematic(name: string, schematic: any): Design;
|
|
82
|
+
static fromNucm(data: Uint8Array | number[]): Design;
|
|
83
|
+
static fromLitematic(data: Uint8Array | number[]): Design;
|
|
84
|
+
static loadNucm(path: string): Promise<Design>; // Node only
|
|
85
|
+
static importLitematic(path: string): Promise<Design>; // Node only
|
|
86
|
+
|
|
87
|
+
declareInput(name: string, port: PortDecl): void;
|
|
88
|
+
declareOutput(name: string, port: PortDecl): void;
|
|
89
|
+
|
|
90
|
+
routeBus(name: string, opts: {
|
|
91
|
+
driver: string; sinks: string | string[];
|
|
92
|
+
gates?: GateObj[]; style?: StyleOpts | Record<string, string> | string | null;
|
|
93
|
+
}): Bus;
|
|
94
|
+
routeBusOr(name: string, opts: {
|
|
95
|
+
drivers: string | string[]; sinks: string | string[];
|
|
96
|
+
gates?: GateObj[]; style?: StyleOpts | Record<string, string> | string | null;
|
|
97
|
+
}): Bus;
|
|
98
|
+
addGate(bus: string, gate: string, anchor: Vec3, step: Vec3): string;
|
|
99
|
+
moveGate(bus: string, gate: string, anchor: Vec3): { state: string; rerouted_segments: number };
|
|
100
|
+
setBusRule(bus: string, rule?: Record<string, any>): void;
|
|
101
|
+
busState(name: string): string;
|
|
102
|
+
busSkew(name: string): { per_bit_rt: number[]; skew_rt: number; max_rt: number };
|
|
103
|
+
rip(name: string): void;
|
|
104
|
+
|
|
105
|
+
addCell(name: string, schematic: any): string;
|
|
106
|
+
place(name: string, cell: string, at: Vec3, rot?: number): void;
|
|
107
|
+
moveInstance(name: string, at: Vec3, rot?: number): {
|
|
108
|
+
rerouted: string[]; failed: Record<string, string>;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/** Executor hardware (levers/lamps, hand-drivable) vs a routable dust
|
|
112
|
+
* input. Reversible: `"executor"` restores the shipped blocks exactly. */
|
|
113
|
+
setPortMode(instance: string, port: string, mode: "bus" | "executor"): PortModeReport;
|
|
114
|
+
promotePort(instance: string, port: string): PortModeReport;
|
|
115
|
+
portModes(): Array<{ name: string; mode: "bus" | "executor"; patch: PortPatch }>;
|
|
116
|
+
planPortPromotion(instance: string, port: string): PortPatch;
|
|
117
|
+
|
|
118
|
+
setBlock(x: number, y: number, z: number, block: string): void;
|
|
119
|
+
|
|
120
|
+
check(opts?: { strict?: boolean }): CheckReport;
|
|
121
|
+
flatten(): Flat;
|
|
122
|
+
bake(budget?: number): Flat;
|
|
123
|
+
|
|
124
|
+
toNucmB64(): string;
|
|
125
|
+
toLitematicB64(): string;
|
|
126
|
+
toBytes(pathOrSuffix: string): Uint8Array;
|
|
127
|
+
save(path: string): Promise<void>; // Node only
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** What Bus mode lays down, and the executor hardware it replaces. */
|
|
131
|
+
export interface PortPatch {
|
|
132
|
+
wires: Vec3[];
|
|
133
|
+
hardware: Vec3[];
|
|
134
|
+
step: Vec3;
|
|
135
|
+
removed: number;
|
|
136
|
+
added: number;
|
|
137
|
+
/** True when the port's hardware was a horizontal ROW and a form adapter
|
|
138
|
+
* was grown to reach the vertical 2y-pitch bus stack. */
|
|
139
|
+
pivoted: boolean;
|
|
140
|
+
note: string;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Outcome of a port-mode switch. `changed` is in WORLD coordinates. */
|
|
144
|
+
export interface PortModeReport {
|
|
145
|
+
port: string;
|
|
146
|
+
mode: "bus" | "executor";
|
|
147
|
+
note: string;
|
|
148
|
+
changed: Array<{ at: Vec3; from: string | null; to: string | null }>;
|
|
149
|
+
/** Buses ripped because their endpoint stopped existing. */
|
|
150
|
+
removed_buses: string[];
|
|
151
|
+
moves: { rerouted: string[]; failed: Record<string, string> };
|
|
152
|
+
patch: PortPatch;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export interface VeneerSurface {
|
|
156
|
+
Design: typeof Design;
|
|
157
|
+
Executor: typeof Executor;
|
|
158
|
+
Flat: typeof Flat;
|
|
159
|
+
Bus: typeof Bus;
|
|
160
|
+
CheckReport: typeof CheckReport;
|
|
161
|
+
DesignCheckError: typeof DesignCheckError;
|
|
162
|
+
Gate: typeof Gate;
|
|
163
|
+
Style: typeof Style;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Bind the veneer to a loaded wasm core module; memoized on the core. */
|
|
167
|
+
export function veneer(core: any): VeneerSurface;
|
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
/** Idiomatic veneer over the generated `Design` / `CellExecutor` core.
|
|
2
|
+
*
|
|
3
|
+
* Thin by contract: every method here only marshals arrays, object
|
|
4
|
+
* literals and options into the exact JSON strings and positional splats
|
|
5
|
+
* the generated bridge expects, and parses the JSON it writes back. No
|
|
6
|
+
* routing/design logic lives on this side. This module mirrors
|
|
7
|
+
* `bindings/python/nucleation/design.py` 1:1 (same names in camelCase,
|
|
8
|
+
* same shapes; object literals where Python takes dataclasses/kwargs).
|
|
9
|
+
*
|
|
10
|
+
* Import as `nucleation/design`, passing the loaded core module once:
|
|
11
|
+
*
|
|
12
|
+
* import * as core from "nucleation"; // or the runtime engine URL
|
|
13
|
+
* import { veneer } from "nucleation/design";
|
|
14
|
+
* const { Design, Gate, Style, Executor } = veneer(core);
|
|
15
|
+
*
|
|
16
|
+
* `veneer(core)` exists because the wasm core is loaded at RUNTIME by URL
|
|
17
|
+
* in the browser apps; there is no static import this module could take.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
// --------------------------------------------------------------------------
|
|
21
|
+
// small value objects (plain objects accepted anywhere these are)
|
|
22
|
+
// --------------------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
/** A bus gate: `Gate([x, y, z], [sx, sy, sz], name?)`.
|
|
25
|
+
* Unnamed gates are auto-named `g0`, `g1`, ... in declaration order. */
|
|
26
|
+
export function Gate(anchor, step, name = null) {
|
|
27
|
+
return { anchor: [...anchor], step: [...step], name };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Per-bus routing style; omitted fields fall back to router defaults. */
|
|
31
|
+
export function Style({ busBlock = null, transparentBlock = null, ...rest } = {}) {
|
|
32
|
+
// Python spells the wire keys snake_case; accept both spellings.
|
|
33
|
+
const s = { ...rest };
|
|
34
|
+
if (busBlock != null) s.bus_block = busBlock;
|
|
35
|
+
if (transparentBlock != null) s.transparent_block = transparentBlock;
|
|
36
|
+
return s;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function styleJson(style) {
|
|
40
|
+
if (style == null) return "{}";
|
|
41
|
+
if (typeof style === "string") return style; // already wire-format JSON
|
|
42
|
+
if (typeof style === "object") return JSON.stringify(style);
|
|
43
|
+
throw new TypeError("style must be a Style/object, JSON string, null or undefined");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** -> [wire JSON, [gate names]] with `g<i>` auto-naming. */
|
|
47
|
+
function gatesJson(gates) {
|
|
48
|
+
const items = (gates ?? []).map((g, i) => {
|
|
49
|
+
if (typeof g !== "object" || !g.anchor || !g.step) {
|
|
50
|
+
throw new TypeError("gates must be Gate(...) results or {anchor, step, name?} objects");
|
|
51
|
+
}
|
|
52
|
+
return { name: g.name ?? `g${i}`, anchor: [...g.anchor], step: [...g.step] };
|
|
53
|
+
});
|
|
54
|
+
return [JSON.stringify(items), items.map((g) => g.name)];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function namesJson(names) {
|
|
58
|
+
return JSON.stringify(typeof names === "string" ? [names] : [...names]);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function unwrap(schematic) {
|
|
62
|
+
return schematic instanceof FlatBase ? schematic.raw : schematic;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function b64ToBytes(b64) {
|
|
66
|
+
if (typeof Buffer !== "undefined") return Buffer.from(b64, "base64");
|
|
67
|
+
const bin = atob(b64);
|
|
68
|
+
const out = new Uint8Array(bin.length);
|
|
69
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
70
|
+
return out;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// --------------------------------------------------------------------------
|
|
74
|
+
// reports
|
|
75
|
+
// --------------------------------------------------------------------------
|
|
76
|
+
|
|
77
|
+
/** Parsed `d.check()`: `.clean` plus the DRC/LVS/rule sections. */
|
|
78
|
+
export class CheckReport {
|
|
79
|
+
constructor(raw) {
|
|
80
|
+
this.raw = raw;
|
|
81
|
+
}
|
|
82
|
+
get clean() { return this.raw.clean ?? false; }
|
|
83
|
+
get drc() { return this.raw.drc ?? []; }
|
|
84
|
+
get lvs() { return this.raw.lvs ?? {}; }
|
|
85
|
+
get rules() { return this.raw.rules ?? []; }
|
|
86
|
+
get buses() { return this.raw.buses ?? {}; }
|
|
87
|
+
get skew() { return this.raw.skew ?? this.raw.buses ?? {}; }
|
|
88
|
+
/** `report.get("drc")` — the Python `report["drc"]` spelling. */
|
|
89
|
+
get(key) { return this.raw[key]; }
|
|
90
|
+
toString() {
|
|
91
|
+
return `CheckReport(clean=${this.clean}, drc=${this.drc.length}, rules=${this.rules.length})`;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Thrown by `d.check({ strict: true })` when the report is not clean. */
|
|
96
|
+
export class DesignCheckError extends Error {
|
|
97
|
+
constructor(report) {
|
|
98
|
+
super(`design check failed: ${JSON.stringify(report.raw, null, 2)}`);
|
|
99
|
+
this.name = "DesignCheckError";
|
|
100
|
+
this.report = report;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// --------------------------------------------------------------------------
|
|
105
|
+
// executor sugar
|
|
106
|
+
// --------------------------------------------------------------------------
|
|
107
|
+
|
|
108
|
+
function toValue(core, v) {
|
|
109
|
+
if (v instanceof core.Value) return v;
|
|
110
|
+
if (typeof v === "boolean") return core.Value.fromBool(v);
|
|
111
|
+
if (typeof v === "number") {
|
|
112
|
+
if (Number.isInteger(v)) {
|
|
113
|
+
return v >= 0 ? core.Value.fromU32(v) : core.Value.fromI32(v);
|
|
114
|
+
}
|
|
115
|
+
return core.Value.fromF32(v);
|
|
116
|
+
}
|
|
117
|
+
if (typeof v === "string") return core.Value.fromString(v);
|
|
118
|
+
throw new TypeError(`cannot convert ${v} to a port Value`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function fromValue(value) {
|
|
122
|
+
for (const conv of ["asU32", "asI32", "asBool", "asF32"]) {
|
|
123
|
+
try {
|
|
124
|
+
return value[conv]();
|
|
125
|
+
} catch {
|
|
126
|
+
/* next */
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return value;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** `const ex = baked.executor(); ex.set("a", 0x55); ex.settle(); ex.get("a_out")`.
|
|
133
|
+
*
|
|
134
|
+
* `set`/`get` convert plain JS values to/from typed port `Value`s (the JS
|
|
135
|
+
* spelling of Python's `ex["a"] = 0x55; ex["a_out"]`); the explicit
|
|
136
|
+
* `setInput` / `readOutput` / `settle` methods stay available, and
|
|
137
|
+
* everything else is reachable on `.cell` (the core `CellExecutor`).
|
|
138
|
+
*/
|
|
139
|
+
class ExecutorBase {
|
|
140
|
+
constructor(core, cell) {
|
|
141
|
+
this._core = core;
|
|
142
|
+
this.cell = cell;
|
|
143
|
+
}
|
|
144
|
+
set(name, value) { this.cell.setInput(name, toValue(this._core, value)); }
|
|
145
|
+
get(name) { return fromValue(this.cell.readOutput(name)); }
|
|
146
|
+
setInput(name, value) { this.cell.setInput(name, toValue(this._core, value)); }
|
|
147
|
+
readOutput(name) { return this.cell.readOutput(name); }
|
|
148
|
+
settle(budget = 4000) { return this.cell.settle(budget); }
|
|
149
|
+
reset() { return this.cell.reset(); }
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** A flattened/baked artifact: the core `Schematic` plus sugar.
|
|
153
|
+
*
|
|
154
|
+
* `.executor()` builds a settled typed executor over the embedded
|
|
155
|
+
* contract; `.toBytes(format)` serializes it (`"schem"`, `"litematic"`,
|
|
156
|
+
* `"snapshot"`, `"mcstructure"`); `.save(path)` writes it in Node;
|
|
157
|
+
* `.raw` is the core `Schematic` for APIs that want it.
|
|
158
|
+
*/
|
|
159
|
+
class FlatBase {
|
|
160
|
+
constructor(core, raw) {
|
|
161
|
+
this._core = core;
|
|
162
|
+
this.raw = raw;
|
|
163
|
+
}
|
|
164
|
+
executor(settle = 4000) {
|
|
165
|
+
return surfaces.get(this._core).Executor.forSchematic(this.raw, settle);
|
|
166
|
+
}
|
|
167
|
+
/** Artifact bytes; `format` from the path suffix in `.save()`. */
|
|
168
|
+
toBytes(format = "schem") {
|
|
169
|
+
const b64 = {
|
|
170
|
+
schem: () => this.raw.toSchematicB64(),
|
|
171
|
+
schematic: () => this.raw.toSchematicB64(),
|
|
172
|
+
litematic: () => this.raw.toLitematicB64(),
|
|
173
|
+
snapshot: () => this.raw.toSnapshotB64(),
|
|
174
|
+
nuc: () => this.raw.toSnapshotB64(),
|
|
175
|
+
mcstructure: () => this.raw.toMcstructureB64(),
|
|
176
|
+
}[format];
|
|
177
|
+
if (!b64) throw new Error(`unknown artifact format ${JSON.stringify(format)}`);
|
|
178
|
+
return b64ToBytes(b64());
|
|
179
|
+
}
|
|
180
|
+
/** Node-only path save (browsers: use `.toBytes()` + a download). */
|
|
181
|
+
async save(path) {
|
|
182
|
+
const fs = await import("node:fs");
|
|
183
|
+
fs.writeFileSync(path, this.toBytes(String(path).split(".").pop()));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// --------------------------------------------------------------------------
|
|
188
|
+
// bus handle
|
|
189
|
+
// --------------------------------------------------------------------------
|
|
190
|
+
|
|
191
|
+
/** Anything the core writes back from a call that used to be void — a route
|
|
192
|
+
* report, say. `null` when the core wrote nothing, so a caller can treat
|
|
193
|
+
* "this build does not report it" and "nothing to report" the same way. */
|
|
194
|
+
function optionalReport(raw) {
|
|
195
|
+
if (typeof raw !== "string" || raw.trim() === "") return null;
|
|
196
|
+
try {
|
|
197
|
+
return JSON.parse(raw);
|
|
198
|
+
} catch {
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** Handle returned by `routeBus`: live `.state`, drag and rip. */
|
|
204
|
+
export class Bus {
|
|
205
|
+
constructor(design, name, gateNames, report = null) {
|
|
206
|
+
this.design = design;
|
|
207
|
+
this.name = name;
|
|
208
|
+
this.gateNames = [...gateNames];
|
|
209
|
+
/** What realizing the bus did beyond routing it — e.g. `promotions`, the
|
|
210
|
+
* executor-only ports it converted so the bus could land. `null` on cores
|
|
211
|
+
* that do not report it. */
|
|
212
|
+
this.report = report;
|
|
213
|
+
}
|
|
214
|
+
/** Ports the router promoted to make this bus land, as
|
|
215
|
+
* `[{port, from, to, note}]` (best effort: `[]` when unreported). */
|
|
216
|
+
get promotions() {
|
|
217
|
+
const p = this.report?.promotions ?? this.report?.promoted ?? [];
|
|
218
|
+
return Array.isArray(p) ? p : [];
|
|
219
|
+
}
|
|
220
|
+
get state() { return this.design.busState(this.name); }
|
|
221
|
+
get skew() { return this.design.busSkew(this.name); }
|
|
222
|
+
_gate(gate) { return typeof gate === "number" ? this.gateNames[gate] : gate; }
|
|
223
|
+
/** Drag a gate (by index or name) to `[x, y, z]`; -> reroute report. */
|
|
224
|
+
moveGate(gate, anchor) { return this.design.moveGate(this.name, this._gate(gate), anchor); }
|
|
225
|
+
addGate(anchor, step, name = null) {
|
|
226
|
+
name = name ?? `g${this.gateNames.length}`;
|
|
227
|
+
const state = this.design.addGate(this.name, name, anchor, step);
|
|
228
|
+
this.gateNames.push(name);
|
|
229
|
+
return state;
|
|
230
|
+
}
|
|
231
|
+
rule(rule = {}) { this.design.setBusRule(this.name, rule); }
|
|
232
|
+
rip() { this.design.rip(this.name); }
|
|
233
|
+
toString() { return `Bus(${JSON.stringify(this.name)}, ${this.state})`; }
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// --------------------------------------------------------------------------
|
|
237
|
+
// the design document
|
|
238
|
+
// --------------------------------------------------------------------------
|
|
239
|
+
|
|
240
|
+
/** Options-object/array veneer over the generated wire-format `Design`.
|
|
241
|
+
*
|
|
242
|
+
* Anything not wrapped here (`setBlock`, `toNucmB64`, ...) is reachable
|
|
243
|
+
* on `.raw` (the core object) unchanged.
|
|
244
|
+
*/
|
|
245
|
+
class DesignBase {
|
|
246
|
+
constructor(core, raw) {
|
|
247
|
+
this._core = core;
|
|
248
|
+
this._d = raw;
|
|
249
|
+
}
|
|
250
|
+
get raw() { return this._d; }
|
|
251
|
+
|
|
252
|
+
// -- ports ---------------------------------------------------------------
|
|
253
|
+
|
|
254
|
+
declareInput(name, { anchor, step, width, ty = "uint" }) {
|
|
255
|
+
const [ax, ay, az] = anchor, [sx, sy, sz] = step;
|
|
256
|
+
this._d.declareInput(name, ax, ay, az, sx, sy, sz, width, ty);
|
|
257
|
+
}
|
|
258
|
+
declareOutput(name, { anchor, step, width, ty = "uint" }) {
|
|
259
|
+
const [ax, ay, az] = anchor, [sx, sy, sz] = step;
|
|
260
|
+
this._d.declareOutput(name, ax, ay, az, sx, sy, sz, width, ty);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// -- buses ---------------------------------------------------------------
|
|
264
|
+
|
|
265
|
+
routeBus(name, { driver, sinks, gates = [], style = null }) {
|
|
266
|
+
const [gj, gateNames] = gatesJson(gates);
|
|
267
|
+
const raw = this._d.routeBus(name, driver, namesJson(sinks), gj, styleJson(style));
|
|
268
|
+
return new Bus(this, name, gateNames, optionalReport(raw));
|
|
269
|
+
}
|
|
270
|
+
routeBusOr(name, { drivers, sinks, gates = [], style = null }) {
|
|
271
|
+
const [gj, gateNames] = gatesJson(gates);
|
|
272
|
+
const raw = this._d.routeBusOr(name, namesJson(drivers), namesJson(sinks), gj, styleJson(style));
|
|
273
|
+
return new Bus(this, name, gateNames, optionalReport(raw));
|
|
274
|
+
}
|
|
275
|
+
/** Route a bus whose driver and sinks are DIFFERENT WIDTHS, with the
|
|
276
|
+
* alignment stated rather than guessed.
|
|
277
|
+
*
|
|
278
|
+
* `align`: `"lsb"` (default — bit 0 to bit 0, so the magnitude survives),
|
|
279
|
+
* `"msb"` (top bit to top bit, i.e. a shift up by the width difference), or
|
|
280
|
+
* `"shift"` with `shift` bits (positive moves toward the MSB).
|
|
281
|
+
* `truncate` permits DROPPING source bits that fall outside the destination;
|
|
282
|
+
* without it a lossy connection is refused, because throwing away a word's
|
|
283
|
+
* high bits is not the router's decision to make. Destination bits nothing
|
|
284
|
+
* drives read 0 with no hardware at all.
|
|
285
|
+
*/
|
|
286
|
+
routeBusAdapted(name, { driver, sinks, gates = [], style = null,
|
|
287
|
+
align = "lsb", shift = 0, truncate = false }) {
|
|
288
|
+
const [gj, gateNames] = gatesJson(gates);
|
|
289
|
+
const code = { lsb: 0, msb: 1, shift: 2 }[String(align).toLowerCase()];
|
|
290
|
+
if (code === undefined) {
|
|
291
|
+
throw new TypeError(`align must be "lsb", "msb" or "shift" (got ${JSON.stringify(align)})`);
|
|
292
|
+
}
|
|
293
|
+
const raw = this._d.routeBusAdapted(
|
|
294
|
+
name, driver, [...sinks].join(","), gj, styleJson(style), code, shift | 0, !!truncate);
|
|
295
|
+
return new Bus(this, name, gateNames, optionalReport(raw));
|
|
296
|
+
}
|
|
297
|
+
/** How a bus's bits line up: `{driver, width, sinks: [{port, width, bits}]}`
|
|
298
|
+
* shaped by the core. `null` on cores that do not report it. */
|
|
299
|
+
busWidthMap(name) {
|
|
300
|
+
if (typeof this._d.busWidthMap !== "function") return null;
|
|
301
|
+
try {
|
|
302
|
+
return JSON.parse(this._d.busWidthMap(name));
|
|
303
|
+
} catch {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
addGate(bus, gate, anchor, step) {
|
|
308
|
+
const [x, y, z] = anchor, [sx, sy, sz] = step;
|
|
309
|
+
return this._d.addGate(bus, gate, x, y, z, sx, sy, sz);
|
|
310
|
+
}
|
|
311
|
+
moveGate(bus, gate, anchor) {
|
|
312
|
+
const [x, y, z] = anchor;
|
|
313
|
+
return JSON.parse(this._d.moveGate(bus, gate, x, y, z));
|
|
314
|
+
}
|
|
315
|
+
setBusRule(bus, rule = {}) { this._d.setBusRule(bus, JSON.stringify(rule)); }
|
|
316
|
+
busState(name) { return this._d.busState(name); }
|
|
317
|
+
busSkew(name) { return JSON.parse(this._d.busSkew(name)); }
|
|
318
|
+
rip(name) { this._d.rip(name); }
|
|
319
|
+
/** Re-realize a ripped/failed bus from its stored declaration; -> state. */
|
|
320
|
+
reroute(name) { return this._d.reroute(name); }
|
|
321
|
+
/** Delete a bus outright — fragment AND declaration, freeing the name. */
|
|
322
|
+
removeBus(name) { this._d.removeBus(name); }
|
|
323
|
+
|
|
324
|
+
// -- cells / instances ---------------------------------------------------
|
|
325
|
+
|
|
326
|
+
addCell(name, schematic) { return this._d.addCell(name, unwrap(schematic)); }
|
|
327
|
+
place(name, cell, at, rot = 0) {
|
|
328
|
+
const [x, y, z] = at;
|
|
329
|
+
this._d.place(name, cell, x, y, z, rot);
|
|
330
|
+
}
|
|
331
|
+
moveInstance(name, at, rot = 0) {
|
|
332
|
+
const [x, y, z] = at;
|
|
333
|
+
return JSON.parse(this._d.moveInstance(name, x, y, z, rot));
|
|
334
|
+
}
|
|
335
|
+
/** Remove an instance. Buses that terminated on one of its ports are
|
|
336
|
+
* DELETED (they lost an endpoint) and named in the report; buses that
|
|
337
|
+
* merely crossed its space are ripped and co-rerouted.
|
|
338
|
+
* -> `{removed_buses, rerouted, failed}`. */
|
|
339
|
+
removeInstance(name) { return JSON.parse(this._d.removeInstance(name)); }
|
|
340
|
+
|
|
341
|
+
// -- instance ports (derived routing endpoints) ---------------------------
|
|
342
|
+
|
|
343
|
+
/** Every endpoint the placed instances expose, as
|
|
344
|
+
* `{name: "u0.sum", instance, port, role, ty, width, hardware, wires,
|
|
345
|
+
* step, routable, blocked}`.
|
|
346
|
+
*
|
|
347
|
+
* `name` is exactly what `routeBus` accepts. `role` is the CELL-facing
|
|
348
|
+
* direction: `"output"` drives a bus, `"input"` receives one. A cell
|
|
349
|
+
* contract names EXECUTOR hardware (levers/buttons in, lamps out) while a
|
|
350
|
+
* bus lands on dust, so `wires` carries the derived dust connection cells
|
|
351
|
+
* — and a port with no dust to tap (a bare lever input) reports
|
|
352
|
+
* `routable: false` with the reason in `blocked`. */
|
|
353
|
+
instancePorts() { return JSON.parse(this._d.instancePorts()); }
|
|
354
|
+
|
|
355
|
+
/** Switch a port between executor hardware and a routable dust input —
|
|
356
|
+
* `mode` is `"bus"` or `"executor"`.
|
|
357
|
+
*
|
|
358
|
+
* This is the composability switch. A community cell's inputs are LEVERS,
|
|
359
|
+
* and nothing in redstone drives a lever, so `add.sum -> bcd.bin` needs
|
|
360
|
+
* `bin` in `"bus"` mode first. The conversion is a reversible per-instance
|
|
361
|
+
* patch: `"executor"` restores the shipped blocks byte-exactly.
|
|
362
|
+
*
|
|
363
|
+
* Returns `{port, mode, note, changed: [{at, from, to}], removed_buses,
|
|
364
|
+
* moves, patch}`. `note` is a ready-made toast; `changed` is in WORLD
|
|
365
|
+
* coordinates. A bus that terminated on the port is RIPPED and named in
|
|
366
|
+
* `removed_buses` — its endpoint physically stopped existing. */
|
|
367
|
+
setPortMode(instance, port, mode) {
|
|
368
|
+
return JSON.parse(this._d.setPortMode(instance, port, mode));
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/** `setPortMode(instance, port, "bus")`. */
|
|
372
|
+
promotePort(instance, port) { return this.setPortMode(instance, port, "bus"); }
|
|
373
|
+
|
|
374
|
+
/** Ports whose mode has been switched: `[{name, mode, patch}]`. Anything
|
|
375
|
+
* absent is in `"executor"` mode. */
|
|
376
|
+
portModes() { return JSON.parse(this._d.portModes()); }
|
|
377
|
+
|
|
378
|
+
/** What promoting a port WOULD do, without doing it: `{wires, hardware,
|
|
379
|
+
* step, removed, added, pivoted, note}`. Throws with the reason when the
|
|
380
|
+
* port cannot be promoted (a ceiling lever, say). */
|
|
381
|
+
planPortPromotion(instance, port) {
|
|
382
|
+
return JSON.parse(this._d.planPortPromotion(instance, port));
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/** Resolve one endpoint name to the geometry a bus would use:
|
|
386
|
+
* `{name, anchor, step, width, direction, connectable}`. `direction` is
|
|
387
|
+
* DESIGN-facing, so `"input"` drives buses. Throws with the reason when
|
|
388
|
+
* the name is unknown or the port cannot terminate a bus. */
|
|
389
|
+
resolvePort(name) { return JSON.parse(this._d.resolvePort(name)); }
|
|
390
|
+
|
|
391
|
+
// -- loose layer (explicit forward; more via `.raw`) ---------------------
|
|
392
|
+
|
|
393
|
+
setBlock(x, y, z, block) { this._d.setBlock(x, y, z, block); }
|
|
394
|
+
|
|
395
|
+
// -- lifecycle -----------------------------------------------------------
|
|
396
|
+
|
|
397
|
+
check({ strict = false } = {}) {
|
|
398
|
+
const report = new CheckReport(JSON.parse(this._d.check()));
|
|
399
|
+
if (strict && !report.clean) throw new DesignCheckError(report);
|
|
400
|
+
return report;
|
|
401
|
+
}
|
|
402
|
+
flatten() { return new (surfaces.get(this._core).Flat)(this._d.flatten()); }
|
|
403
|
+
/** The flattened stack composited into ONE region — what an interchange
|
|
404
|
+
* artifact wants. `flatten()` keeps `inst:*`/`bus:*` regions (the
|
|
405
|
+
* renderer needs them); a single-region schematic cannot lose a
|
|
406
|
+
* named-layer cell to the loose layer's bounding box. */
|
|
407
|
+
flattenComposite() {
|
|
408
|
+
return new (surfaces.get(this._core).Flat)(this._d.flattenComposite());
|
|
409
|
+
}
|
|
410
|
+
bake(budget = 4000) { return new (surfaces.get(this._core).Flat)(this._d.bake(budget)); }
|
|
411
|
+
|
|
412
|
+
// -- persistence ---------------------------------------------------------
|
|
413
|
+
|
|
414
|
+
toNucmB64() { return this._d.toNucmB64(); }
|
|
415
|
+
toLitematicB64() { return this._d.toLitematicB64(); }
|
|
416
|
+
toSchemB64() { return this._d.toSchemB64(); }
|
|
417
|
+
/** Document/artifact bytes by suffix: `.nucm` -> project tier,
|
|
418
|
+
* `.litematic` -> layered interchange, anything else -> the flattened
|
|
419
|
+
* artifact, composited (the browser-side spelling of Python's
|
|
420
|
+
* `d.save(path)`). */
|
|
421
|
+
toBytes(pathOrSuffix) {
|
|
422
|
+
const suffix = String(pathOrSuffix).split(".").pop();
|
|
423
|
+
if (suffix === "nucm") return b64ToBytes(this._d.toNucmB64());
|
|
424
|
+
if (suffix === "litematic") return b64ToBytes(this._d.toLitematicB64());
|
|
425
|
+
if (suffix === "schem" || suffix === "schematic") return b64ToBytes(this._d.toSchemB64());
|
|
426
|
+
return this.flattenComposite().toBytes(suffix);
|
|
427
|
+
}
|
|
428
|
+
/** Node-only path save, tier dispatched by suffix like Python's. */
|
|
429
|
+
async save(path) {
|
|
430
|
+
const fs = await import("node:fs");
|
|
431
|
+
fs.writeFileSync(path, this.toBytes(path));
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// --------------------------------------------------------------------------
|
|
436
|
+
// binding to a loaded core
|
|
437
|
+
// --------------------------------------------------------------------------
|
|
438
|
+
|
|
439
|
+
const surfaces = new WeakMap(); // module namespaces are frozen; memoize here
|
|
440
|
+
|
|
441
|
+
/** Bind the veneer to a loaded wasm core module; returns the surface. */
|
|
442
|
+
export function veneer(core) {
|
|
443
|
+
const memo = surfaces.get(core);
|
|
444
|
+
if (memo) return memo;
|
|
445
|
+
|
|
446
|
+
class Executor extends ExecutorBase {
|
|
447
|
+
constructor(cell) { super(core, cell); }
|
|
448
|
+
static forSchematic(schematic, settle = 4000) {
|
|
449
|
+
const ex = new Executor(core.CellExecutor.forSchematic(unwrap(schematic)));
|
|
450
|
+
if (settle) ex.cell.settle(settle);
|
|
451
|
+
return ex;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
class Flat extends FlatBase {
|
|
455
|
+
constructor(raw) { super(core, raw); }
|
|
456
|
+
}
|
|
457
|
+
class Design extends DesignBase {
|
|
458
|
+
constructor(raw) { super(core, raw); }
|
|
459
|
+
static create(name) { return new Design(core.Design.create(name)); }
|
|
460
|
+
static forSchematic(name, schematic) {
|
|
461
|
+
return new Design(core.Design.forSchematic(name, unwrap(schematic)));
|
|
462
|
+
}
|
|
463
|
+
static fromNucm(data) { return new Design(core.Design.fromNucm(Array.from(data))); }
|
|
464
|
+
static fromLitematic(data) { return new Design(core.Design.fromLitematic(Array.from(data))); }
|
|
465
|
+
static async loadNucm(path) {
|
|
466
|
+
const fs = await import("node:fs");
|
|
467
|
+
return Design.fromNucm(fs.readFileSync(String(path)));
|
|
468
|
+
}
|
|
469
|
+
static async importLitematic(path) {
|
|
470
|
+
const fs = await import("node:fs");
|
|
471
|
+
return Design.fromLitematic(fs.readFileSync(String(path)));
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const surface = {
|
|
476
|
+
Design, Executor, Flat, Bus, CheckReport, DesignCheckError, Gate, Style,
|
|
477
|
+
};
|
|
478
|
+
surfaces.set(core, surface);
|
|
479
|
+
return surface;
|
|
480
|
+
}
|