Templates
Each scaffold tool of the MCP writes one of these files into a game, with Feature replaced by the name it was given and feature by that name in kebab case, and a page stub beside it under the game’s wiki/ folder. The registry serves each as an item under /r, so game add behaviour writes the same file unrenamed. The files live in packages/templates, where the typecheck and lint read them against the engine.
Behaviour
Section titled “Behaviour”add_behaviour writes src/behaviours/<Name>.tsx: a trait, a Behaviour that says where it runs, and the component that adds the trait to the nearest Entity.
import { trait } from "koota";import { RunContext, useBehaviour, type Behaviour,} from "@daniel-zarinski/engine";
/** What Feature does to its entity, in one line. */export const FeatureTrait = trait({ speed: 1 });
export const FeatureBehaviour: Behaviour<typeof FeatureTrait> = { trait: FeatureTrait, runsOn: RunContext.Client, wiki: "/behaviours/feature/", source: "src/behaviours/Feature.tsx",};
export interface FeatureProps { /** What speed means, and its unit. */ speed: number;}
export function Feature(props: FeatureProps) { useBehaviour(FeatureBehaviour, props);
return null;}Entity
Section titled “Entity”add_entity writes src/components/<Name>.tsx: an Entity with a mesh and one behaviour to start from.
import { Entity, Spin, type EntityProps } from "@daniel-zarinski/engine";
/** What Feature is in the world, in one line. */export function Feature({ position }: Pick<EntityProps, "position">) { return ( <Entity position={position}> <Spin speed={1} /> <mesh> <boxGeometry args={[0.5, 0.5, 0.5]} /> <meshStandardMaterial color="gold" /> </mesh> </Entity> );}add_scene writes src/scenes/<Name>.tsx and returns the import and the <Scene> line to paste into src/app/app.tsx, as Scene describes.
import { Camera, CameraTarget, Hud, Panel, Player, Slot, Text, World,} from "@daniel-zarinski/engine";
/** What happens in the feature scene, in one line. */export function Feature() { return ( <World map="meadow"> <Player /> <Camera follow={CameraTarget.Player} /> <Hud> <Panel slot={Slot.Bottom}> <Text>Feature</Text> </Panel> </Hud> </World> );}add_panel writes src/devtools/<Name>Panel.tsx and returns the import and the entry to paste into the panels list in src/app/devtools.tsx, as Devtools describes.
import { Stat } from "@daniel-zarinski/devtools";
/** What the Feature panel shows, in one line. */export function FeaturePanel() { return <Stat value="-" unit="feature" />;}Shader
Section titled “Shader”add_shader writes src/shaders/<Name>.tsx: a fragment that includes one LYGIA function, and a <Name>Material component that draws it as the material of the mesh it sits in, as Shader describes. Put the material inside a mesh, then edit the fragment and its uniforms.
import { Shader } from "@daniel-zarinski/engine";
// Edit from void main() on. The engine declares uTime, uPointer and vUv// ahead of it, and one uniform per uniforms key below.const fragment = `#include "lygia/generative/snoise.glsl"
void main() { float noise = 0.5 + 0.5 * snoise(vec3(vUv * uScale, uTime * uSpeed)); gl_FragColor = vec4(vec3(noise), 1.0);}`;
export interface FeatureMaterialProps { /** How fast the pattern changes, per second of world time. */ speed?: number; /** How many cells of the pattern cross the mesh. */ scale?: number;}
/** The material of the mesh it sits in: what Feature draws, in one line. */export function FeatureMaterial({ speed = 0.5, scale = 4,}: FeatureMaterialProps) { return ( <Shader fragment={fragment} uniforms={{ uSpeed: speed, uScale: scale }} /> );}add_map writes src/maps/<name>.json: a flat, empty map, 64 m across unless size says otherwise, or with from: "meadow" a copy of the engine’s meadow. It has no page stub. It returns the registerMaps line to paste into src/app/app.tsx only while the app file lacks one; every game template carries it. game add map <name> [--size <metres>] [--from meadow] does the same from the cli. Open the game with ?map=<name> in development to see the map alone, as Devtools describes.
{ "seed": 1, "size": 64, "cell": 1, "hills": { "amplitude": 0, "wavelength": 40, "detail": 0 }, "scatter": { "treeRound": 0, "treeTall": 0, "bushRound": 0, "rockBoulder": 0, "rockFlat": 0, "grassTuft": 0, "seedOffset": 0 }, "regions": {}, "paths": {}, "views": {}, "props": {}, "rim": 0}