Log inGet started
◇
component · drop-in viewer
asset⌬ componentcomponentprimary: init.luau·originates fromworld e339ab22-c…

EndlessDirector

Endless Nightmare's engine: it builds the procedurally generated house the player is standing in, a floor at a time, and never stops.

by◐aiden·posted 1d ago
What it does

game.house.EndlessDirector

Endless Nightmare's engine: it builds the procedurally generated house the player is standing in, a floor at a time, and never stops.

Attach it to one entity — the scene build puts it on endless_director inside game.house.sceneContent. It needs no sibling component; the rooms it makes are ordinary scene entities, and the story house is untouched.

Fields

FieldDefaultWhat it does
activefalseFlip it on to start a run. Inert until then, so the story house is never disturbed.
seed20261012Together with the floor, decides every room. Two peers with the same pair build the same house.
floor1The floor the player is on. It climbs and never caps.
spread2How many rooms either side of the player stay loaded.
roomsExplored0Rooms built this floor; resets each floor.

What it does

  • Builds the rooms within spread of the player and unloads the ones behind them, so an hour-long run does not cost an hour of memory.
  • Steps the floor when the player reaches the room marked stairs, replacing the floor rather than adding to it.
  • Announces each floor on the bus (modeChanged) and writes the run to the shared store under GameRules.DATA.endless, so every peer sees the same floor number and the same statistic.
  • Emits a power_on noise when a floor is generated — a new floor is loud, and the thing hunting the player is allowed to hear it.

Generation runs at most four times a second: a player crosses a room in about two seconds and building one is not free.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

game/house/EndlessDirector.component — ENDLESS NIGHTMARE's engine. THE MODE THAT NEVER ENDS. It builds the house the player is standing in, a floor at a time, and there is no last floor: `Endless.plan` answers for any number, so the counter climbs for as long as the player lives. GENERATION IS INCREMENTAL AND BOUNDED, which is what keeps a run that lasts an hour from costing an hour of memory: only the rooms within `spread` cells of the player exist, the ones behind them are unloaded, and the next floor replaces the last rather than adding to it. Reusable room shapes throughout — nothing here generates new geometry. ONE HOUSE FOR EVERYONE. The plan is a pure function of (seed, floor), so every peer in a session builds the same rooms from the same two numbers and nobody has to send a layout across the wire. The story house is untouched: the arena sits at `Endless.ORIGIN`, well clear of it, so a run of one never stands inside the other.

localBody( ) → void

This client's body. Guarded, because it is nil for a moment on join and before the avatar binds, and a nil read on an id that does not resolve logs a warning every single frame it happens.

buildCell(cell: ?) → void

argtypedescription
cell?

unloadCell(k: ?) → void

argtypedescription
k?

ensureAround(gx: ?, gz: ?) → void

argtypedescription
gx?
gz?

publishStats( ) → void

startFloor(floor: ?) → void

argtypedescription
floor?

awake( ) → void

update(dt: ?) → void

argtypedescription
dt?

onDestroy( ) → void

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

Showing up to 3 levels deep. Open a part to see what it holds further down.

22+items
▣
module · born here
❒asset
# game.Bus The one table the game's parts talk over. **Every slice announces what happened and listens for what it cares about; no slice requires another**, and this is the table in the middle they share. ```lua local Bus = require("game.Bus") Bus.emit(Bus.E.noise, { id = "sprint", position = p, source = "player" }) local handle = Bus.on(Bus.E.playerCaught, function(payload) print(payload.monster) -- "resident" end) Bus.off(Bus.E.playerCaught, handle) ``` `Bus.E` is the event-name list, spelled once so no slice can invent a string nobody else listens for. It is the same set as `GameRules.EVENTS`, which also documents the payload each event carries; the scene entrypoint checks the two agree on every load and warns if they have drifted. `on`, `once`, `off`, `emit`, `count`, `clear`, plus `error()` and `clearError()` for the last handler failure. ## Two rules, because getting them wrong desynchronises a co-op run 1. **The bus is local.** It is a module, and a module is one instance *per peer*. An emit reaches the parts of the game running on this machine and nowhere else. Anything another player must agree about — a door, a key, the objective list, the monster — is written to the **shared store** (`runtime_data.world`, under the keys in `GameRules.DATA`) and read back by every peer. Emit the local *response* to a thing; store the *fact* of it. A part that emits `doorOpened` and never writes the store has a door that opens for one player and stays shut for everyone else. 2. **An emit is synchronous.** Handlers run before `emit` returns, in subscription order, on the frame the thing happened. The payload table is handed out, not copied — read it, do not keep it, do not mutate it. A handler that throws is caught and reported, so one broken listener cannot silence every other listener on the same event; `Bus.error()` reads the last one back. Who calls it: every slice. The house emits doors and pickups, the monsters emit their state and a sighting, the survival systems emit noise, damage and clues, the interface listens to most of it, and the audio director listens to nearly all of it.
▲ 0↑ born
▣
module · born here
❒asset
# game.house.Endless The house of **Endless Nightmare**, as data. No geometry, no entities: `plan(floor, seed)` answers what is on a floor and `EndlessDirector` builds it. ```lua local Endless = require("game.house.Endless") local plan = Endless.plan(3, seed) plan.cells -- every room on the floor, by key plan.stairs -- the room that leads deeper plan.difficulty -- from GameRules.endlessDifficultyFor(floor) ``` - **`plan(floor, seed)`** — rooms, the doors between them, what each room is, where the supplies are, and which room is the way down. A **pure function of (seed, floor)**, so two peers build the same house from two numbers and nobody sends a layout across the wire, and so a run can be repeated exactly. - **`cellRect(gx, gz)`** — a room's interior rectangle in world space. - **`cellAt(x, z)`** — which grid cell a world position is in. - **`openingsFor(cell, rect)`** — the doorway each side of a cell needs, in the form the wall builder takes. - **`ORIGIN`** — where the arena sits (2000 m out), well clear of the story house, so a run of one never stands inside the other. The systems slice moves the player here when a run starts. **Connectivity is by construction:** a room is only ever added beside a room that already exists, and a loop is occasionally closed so the house can be circled rather than only retraced. There is no sealed pocket, no door that opens onto a wall, and no supply in an unreachable room — they cannot be generated. Rooms are **reusable shapes**, not new geometry: a cell is a rectangle with a doorway per neighbour, exactly the shape the twelve hand-built areas use, so the generator and the story house cannot drift apart. There is no final floor; `plan` answers for any number.
▲ 0↑ born
◐
material · born here
❒asset
▲ 0↑ born
◐
material · born here
❒asset
▲ 0↑ born
◐
material · born here
❒asset
▲ 0↑ born
◐
material · born here
❒asset
▲ 0↑ born
◐
material · born here
❒asset
▲ 0↑ born
◇
component · born here
❒asset
# game.house.HouseDoor A door leaf that swings on its own hinge. It is what stands in the doorway of every room in the house, so a doorway reads as shut rather than as a hole. `HouseBuilder` attaches it to each `door_<id>` leaf, with the door's lock. ## Who opens it Not this component. It owns the **swing** and the **lock data**; the systems slice owns the **interaction** — whether the player holds the key, what the prompt says, and the message when a door refuses. The systems slice sets `open = true` when the player may pass. So the house never has to know about inventory, and the inventory never has to know about hinges. ## Fields | Field | What it is | |---|---| | `open` | Whether the leaf is swung aside. **Sync** — a door one player opens is open for everyone. | | `lockedBy` | The `GameRules.ITEMS` id that opens it, or `""`. Empty means it is never locked. | | `swing` | How far the leaf turns, in degrees. | | `hinge` | Which edge it turns about, `1` or `-1`. | | `width`, `axis` | The leaf's size and which way its width runs, so the hinge can be found from them. | | `speed` | Degrees a second while it swings. | ## The hinge is the whole problem A door is a box, and a box turns about its own **centre** — which swings the leaf straight through both walls. So the leaf's position is carried around its hinge: the hinge sits at one edge, and opening is that point staying still while the rest of the leaf travels around it. `awake` finds the hinge from the leaf's position, width and axis; every frame of the swing re-derives the position from the closed one, so a door that is interrupted halfway still ends exactly shut or exactly open.
▲ 0↑ born
◐
material · born here
❒asset
▲ 0↑ born
▣
module · born here
❒asset
# game.house.HouseBuilder The twelve areas of **The House That Knows You**, as data and one builder. `HouseBuilder.build()` is called from `game.house.sceneContent`, which the scene build calls, so what it makes is baked into `scenes/house.scene/scene.json` and is there the moment the world opens. ## The plan is data - **`ROOMS`** — each area's interior rectangle: `x0..x1`, `z0..z1`, `y0..y1`. The entrance hall is `HALL`, and is built by the scene skeleton, not here. - **`DOORS`** — a doorway is declared by `(a, side, at, other)`: room `a` cuts an opening on the wall named by `side`, centred at `at` measured along it. It is declared by room-and-side rather than by a coordinate because two rooms never share a wall: interiors are spaced so neighbouring walls **abut** and never coincide, and each room cuts its own. Two coplanar walls look perfect in a still frame and shimmer the moment the camera moves. - **`STAIRS`** — the three places the house changes level, each with the room it starts in, the room it arrives in, and the item that locks it. The hole a stair needs is derived from the same entry, so a stair and its hole cannot disagree. - **`PROPS`** — what each room is furnished with; `hide = true` marks a place the player can get inside. - **`UNLIT_ROOMS`** — the basement, secret room, attic and storage room carry no light on purpose. They are torch territory. ## What it exposes - `build()` — build it all. Called from the scene build. - `area(id)` — the centre of an area, for any slice that needs to place something in a room. `roomOf(id)` gives the rectangle. - `doorInfo(id)` — a doorway's lock, for the systems slice. - `hidingPlaces()` — every `hide_<room>_<n>` entity, by name. ## What it names, so other slices can find it `room_<area>` is each room's root; `light_<area>` its bulb; `door_<id>` a door leaf; `door_stair_<id>` a locked stair door; `hide_<area>_<n>` a hiding place; `prop_<area>_<n>` furniture; `spawn_resident_<area>` and `patrol_<area>` the two anchors the monsters slice uses. The furniture is **blocked out**: named, in the right place, at the right size, in a plain material, so the game runs and the polish pass can put the real prop exactly there.
▲ 0↑ born
▣
module · born here
❒asset
# game.GameRules The constants and rules of **The House That Knows You** — the one module every part of the game reads, so two systems written in different sessions agree on what a room is called, how loud a sprint is, how long a torch battery lasts and which ending the player earned. It holds **no behaviour and no entities**: pure data plus a handful of pure functions. Require it and read it; never write to it. ```lua local RULES = require("game.GameRules") ``` ## What is in it - **`ART_DIRECTION`** — the one sentence every generation prompt reuses word for word, and **`REFERENCES`** — the pictures the game is judged against. - **`PALETTE`** — that sentence as numbers, for the interface and for materials. - **`HOUSE`** — the wall height, the wall thickness, the doorway size, the room module, the storey height and the player's own dimensions. Every prop in the game is sized against these. - **`AREAS`** / **`AREA_BY_ID`** — the twelve areas, each with its floor, its nominal centre on the ground plan and the item that unlocks it. - **`OBJECTIVES`** — the twelve-step chain, in order, each naming the area it happens in and the item it needs. - **`ITEMS`**, **`REQUIRED_CLUES`**, **`CLUE_COUNT_FOR_TRUTH`** — what can be picked up, and what the ending is decided on. - **`ENDINGS`** and **`selectEnding(cluesFound, secretRoomOpened)`** — the three endings and the rule that picks one, stated once so the interface and the systems cannot disagree. - **`SURVIVAL`** — speeds, stamina, health, torch battery, interaction ranges. - **`DIFFICULTY`** — easy, normal, nightmare. These change the monster's persistence, reach and the supply density **only**; all three run the same monster logic. - **`MONSTERS`** and **`MONSTER_STATES`** — THE RESIDENT and THE BROODMOTHER, and the states both run: patrol, investigate, chase, search, attack, recover. - **`NOISE`** — the interface between what a player *does* and what a monster *hears*. A system emits a noise id; the monster AI turns it into a reach. Nothing else may write a raw radius. - **`SPIDERS`** — the baby-spider event: five presses, six seconds, the slow-motion tutorial, the prompts, the damage. - **`ENDLESS`** / **`endlessDifficultyFor(floor)`** — Endless Nightmare, and a floor number that never stops climbing. - **`MODES`**, **`MAX_PLAYERS`**, **`DATA`** — the game modes and the keys shared state lives under. ## Who calls it Every slice: the house builder, both monsters, the survival systems, the interface and the audio director. Every component that runs in play reads its numbers from here rather than carrying its own copy.
▲ 0↑ born
backing path · game/house/EndlessDirector.component

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported on this asset or on the parts this page shows. Parts it leaves out are not counted here.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.