Saxonberg Server API
    Preparing search index...

    Hierarchy

    • SphericalLocationBase
      • default
    Index

    Constructors

    Properties

    Accessors

    Methods

    Constructors

    • Constructor - generates unique runtime ID.

      Subclass constructors should call super() and then initialize their fields. Use field initializers for default values where possible.

      IMPORTANT: Direct new SomeStuff() is rejected — every Stuff must be created via StuffApi.create(() => new YourClass()) or StuffApi.clone(...). The construction sentinel above guarantees this; raw new outside the Api layer throws here.

      Constructor-body method calls bypass the Proxy (the Proxy is installed AFTER the constructor returns). Initialize fields here; do NOT invoke methods that carry

      Returns default

      from inside a constructor body.

    Properties

    _address: string | null = null

    Declared address path in the namespace, or null. Sparse — null is the common case and the resolve-walk falls through it to a containment ancestor or the spatial zone.

    _atmosphere: string | null = null
    _biomePath: string | null = null
    _detailAtmospheres: Record<string, string> = {}
    _detailGravities: Record<string, Quantity<"m/s²">> = {}
    _detailHumidities: Record<string, Quantity<"%">> = {}
    _detailMaterialPaths: Record<string, string> = {}

    Per-Detail Material overrides — flat map from detailKey to the Material's templatePath. Stored as a plain Record (not a Map) so default JSON serialization handles it without a marshaller.

    _detailPressures: Record<string, Quantity<"Pa">> = {}
    _detailTemperatures: Record<string, Quantity<"K">> = {}
    _detailWinds: Record<string, Quantity<"m/s">> = {}
    _focus: { phi: number; radius: number; rho: number; theta: number } | null = null

    Persistent declarative-content field. _focus holds the YAML- shape input {rho, theta, phi, radius}; the runtime tuple lives on SphericalCoordinatesMixin.coordinates ([rho, theta, phi]) and radius (number). The setter bridges them — see setFocus.

    Parallel to CartesianLocation.coords per declarative-content- slate § coords on CartesianLocation (Spherical note).

    _gravity: Quantity<"m/s²"> | null = null
    _humidity: Quantity<"%"> | null = null
    _materialPath: string | null = null

    Path to the bulk default Material singleton. Resolved lazily on each getMaterial() call so HMR replacement is observed immediately.

    _pressure: Quantity<"Pa"> | null = null
    _temperature: Quantity<"K"> | null = null
    _wind: Quantity<"m/s"> | null = null
    contents: Set<Stuff & Containable> = ...

    The contained items. Read access goes through getContents(); mutation goes through addContainable / removeContainable, which only Containable.setContainer may legitimately invoke.

    coordinates: [number, number, number] = ...

    [rho, theta, phi] — radial distance + two angles.

    exits: Map<string, default> = ...

    Explicit exit map. Derived exits (cartesian adjacency, vessel 'out') are NOT stored here — they are synthesized lazily by the zone and by ExitableVessel.getExit() respectively.

    Host-internal storage; external callers use getExits() / getExit(direction).

    fixtureSlots: Map<string, Stuff & Adornment> = ...

    Fixtures keyed by slot name. Single source of truth — the Slotted base's slots Map stays empty for Adornable hosts because occupy / vacate on Adornable are routed through addFixture / removeFixture.

    Runtime-only — fixtures are reconstructed by seed clone hooks (BoundaryApi.attachExistingBoundary).

    illustration: string | null = null
    longDescription: string = ''
    nextFixtureIndex: number = 1

    Counter for synthetic slot names. Instance-local, runtime-only.

    radius: number = 1.0

    Sphere radius. Default 1.0 makes a unit sphere.

    shortDescription: string = ''
    stuffId: string

    Runtime ID for this object (generated using nanoid). This is NOT the MongoDB _id - it's a runtime identifier.

    _mixinName: string = 'SingletonMixin'
    commandContributions: CommandContributions = ...

    Visible is target-shape only — no verb contributions. See the mixin docstring for why look.yaml belongs on Perceiver's self bucket, not on Visible's target-side buckets.

    fieldMarshallers: {
        _gravity: string;
        _humidity: string;
        _pressure: string;
        _temperature: string;
        _wind: string;
    } & { mass: string } = ...

    Field-marshaller bindings for the five Quantity-typed bulk fields. The per-detail maps round-trip via standard JSON (Quantity.toJSON / fromJSON) — Record<string, Quantity<U>> serializes natively without a map marshaller.

    instructionFields: string[] = ...

    exits is the canonical instruction field shape for declarative content. applyExits consumes a Record<string, ExitInstruction> and installs the runtime entries — no paired getter for the spec (the runtime exits: Map<string, Exit> has its own API). See applyExits and feedback_property_vs_instruction_fields.

    markupAugmenters: MarkupAugmenter[] = ...

    Markup-augmenter contribution. senseStripAugmenter reads the per-call filter from AugmentOpts and the viewer's sensorium (derived from BodyPlan.getModalities()), and drops <sense channel="X">…</sense> regions and <detail sense="X"> wrappings whose channel isn't in filter ∩ sensorium.

    Lives on VisibleMixin (not DetailedMixin) because <sense> regions can appear in any Visible-mixed long, with or without detail authoring. Ordering: VisibleMixin sits above Detailed in the typical composition chain, so the parent-first walker runs senseStripAugmenter BEFORE wrapDetailKeysAugmenter — strip-then-wrap is correct because wrapping inside a region destined for the strip is wasted work.

    persistentFields: string[] = ...
    subscribableFields: SubscribableFieldDescriptor[] = ...

    Projection field for live subscriptions. Reads getObviousExits() (explicit ∪ zone-derived, !hidden) and shapes each entry as { direction } for the wire. Destination paths are deliberately NOT shipped — the pane renders a "go

    " click target, not a hyperlink to the destination.

    No dependsOnFields plumbing today: rooms with explicit exits settle at hydration and cartesian-derived exits are positional. If runtime exit add/remove ever becomes a hot path (door sealing, dynamic walls), wire addExit / removeExit to fire FieldChangedEvent { field: 'exits' } the same way Container's addContainable / removeContainable do for contents.

    Accessors

    Methods

    • Install a forward/back exit pair in one call. Both sides share the same Door reference when one is supplied, so opening from either side flips a single state.

      Reciprocity: the opposite direction is inferred from NavigationApi.invertDirection(direction) for cardinal directions. For non-cardinal labels ('office', 'portal', vessel-specific names) the caller MUST supply opts.opposite — there is no structural inverse to infer. Passing opts.opposite for a cardinal direction overrides the inferred inverse.

      Parameters

      Returns Promise<void>

    • State-mutation primitive. Locked down — only callable from Containable.setContainer. Use ContainmentApi.move(item, container) from application code.

      Fires FieldChangedEvent { field: 'contents' } after a real addition so the MQL subscription substrate's dependency index picks up containment-shape changes for the contents descriptor. The substrate matches on (KIND, 'field', 'contents') only — oldValue / newValue are inspected by the diff pass via re-projection of the host, not by the index, so the count delta carried here is informational (debugging / future coarse-grain optimizations) rather than load-bearing.

      Parameters

      Returns void

    • Phase 2 applier — clone each adornment template and attach it as a fixture. Mirrors applyPopulates, minus the singleton dispatch: fixtures are per-instance, so every entry is cloned fresh. A template that doesn't compose AdornmentMixin is a configuration error (it can't be a fixture) and throws, naming the path.

      Parameters

      Returns Promise<void>

    • Declarative-content applier. The instruction field is consumed here: each ExitInstruction is translated into an explicit Exit (or addBidirectionalExit for cardinal / explicit-bidirectional entries). Destinations and doors lazy-clone via StuffApi.singleton, so a depended-on Location is materialized on first need; further singleton(x) calls during a cascade hit the registered proxy and short-circuit cycle scenarios.

      Per-direction idempotency: a matching existing exit (same destination, same door) is a no-op; a mismatch throws with a diagnostic naming both seed paths.

      Parameters

      Returns Promise<void>

    • Destroy this object.

      Locked down by @CallSecurity(ApiOnly) — only callers under mud/api/ (in practice, StuffApi.destruct) may invoke it. @Unshadowable because the unregistration path must always run; a shadow that intercepts and skips it would leak the object into the registry forever. @Final because subclass overrides would defeat the same invariant — the loader hook throws FinalViolationError at import time on any subclass redefinition.

      Subclass cleanup belongs on the optional onDestruct() witness (consulted by StuffApi.destruct while the target is still live); refusal logic belongs on canDestruct(). This terminal destroy() is the unshadowable mark-and-unregister step only.

      Returns void

    • Usable ceiling height — the side of the cube inscribed in the sphere, 2r/√3. The cube's space diagonal equals the sphere's diameter; the cube's side is the practical floor-to-ceiling extent of the room.

      Returns Quantity<"m"> | null

    • Merged lookup:

      1. explicit → wins
      2. (subclass hook — ExitableVessel overrides for 'out')
      3. zone-derived (only CartesianZone returns anything)
      4. undefined

      Parameters

      • direction: string

      Returns default | undefined

    • Read the recency timestamp. Read by the residency sweep — which calls it on the raw target (via RAW_TARGET) so the sweep's own introspection never counts as a touch.

      Returns number

    • Affordance-annotated long description — see the interface docstring for the augmenter pipeline contract. Calls Mml.augment with the host (this), the supplied viewer, and the per-call opts (the senses build threads opts.filter through here for verb-specific sense filtering). Every contributing mixin's augmenters run in parent-first → child-last order.

      Parameters

      Returns string

    • Exits displayed by look — explicit ∪ derived, filtered by !hidden.

      Zones that synthesize cardinal-derived exits (CartesianZone) opt in via Zone.hasDerivedAdjacency(); zones without adjacency derivation (SphericalZone) skip the iteration entirely so we don't waste 10 always-undefined deriveExit calls per query.

      Returns default[]

    • Self-presentation — the casual-register render string for this object, the answer to "what does this Stuff call itself?" Three- step resolution:

      1. Named.name if present and non-empty — the object's proper name ("Alice", "Excalibur", "Town Square").
      2. Visible.shortDescription if present and non-empty — the object's visual identity ("a heavy oak door").
      3. The baked-in fallback (DEFAULT_PRESENTATION).

      For a Globbable stack (quantity !== 1) the count folds in as an affix — "30 coins" — pluralized via GrammarApi.pluralize (which honors host-side getPluralForm() overrides for irregulars). Named takes precedence over Visible so a Named-with-description renders by its proper name; code that needs the formal register calls getFullName() when typed as Named.

      Viewer-blind by design. This is the shared baseline every Stuff exposes; the viewer-aware naming step (recognition / identification — see docs/subsystems/belief.md) composes on top of it. Left shadowable (NOT @Final) so masking / disguise effects can override the rendered identity via a method shadow.

      Returns string

    • Build the composable Mml fragment for this object's display name — the Mml sibling of getPresentation. Mml.ref (and so every <item> / <name> / … identity tag) renders this, not a raw string, so a name joins the compose chain as a fragment like everything else. The label is the already-resolved, viewer-aware name (recognition runs in the render layer and hands it in).

      Return null for the plain default — Mml.ref then wraps the label in Mml.text, which escapes it exactly once, so player-authored names / status decoration are safe by construction and the fragment is never re-escaped downstream. Override to build a richer fragment (a TPA terminal wraps its name in <color> to tint by state). The plain-string getPresentation stays the surface for non-prose consumers (logs, context.note, MQL scalars).

      Parameters

      • _label: string

      Returns Mml | null

    • Effective receiving-surface area used by VisionModality.lightAt to convert accumulated lumens to lux. v1 commits to the room's own radius (interpreted as m²) — bigger spheres read dimmer for the same total flux. The exact-physics version (full surface area 4πr² or a cross-section) is deferred until content needs the fidelity; a single scalar keeps the propagation walk simple.

      Returns number

    • Resolve the temperature at this scope (optionally narrowed by a detailKey). Routes through BiomeApi.resolveTemperatureFor, which walks innermost-container-outward then biome / zone / universe.

      Parameters

      • OptionaldetailKey: string

      Returns Promise<Quantity<"K">>

    • Read seam. Instance method, but unwraps via ProxyApi.unwrap before reaching the # slot — this inside an instance method called through the proxy is the proxy, and the # slot lives on the raw target.

      Returns string | null

    • Narrowed override: a SphericalLocation lives in a SphericalZone by SphericalZone.addLocation's rejection of non-Spherical locations. The cast happens once here, at the boundary; callers with a typed SphericalLocation reference get the narrowed type for free. Symmetric with CartesianLocation.getZone.

      Returns default | null

    • Check if this object has been destroyed.

      @Unshadowable: the destroyed-state read is a framework invariant — any shadow that lied about it would let consumers touch a torn-down Stuff. @Final: subclasses overriding this would defeat the same invariant; the loader hook throws FinalViolationError at import time on any subclass that redefines it.

      Returns boolean

    • Mutual-exit verification — same as CartesianLocation. The verifier skips non-cardinal directions, so spherical exits authored with semantic labels ('office', 'plaza') are no-ops here; they rely on addBidirectionalExit for inverse wiring at construction time.

      Parameters

      • Optional_context: unknown

      Returns Promise<void>

    • Setter with side effect. Stamps the runtime coordinate tuple and radius via the existing SphericalCoordinatesMixin.setCoordinates / setRadius, then registers this location with the resolved SphericalZone via addLocation(this) (Spherical's addLocation reads the coordinates that we just stamped — no per-arg coordinate delivery).

      Idempotent on the happy path (same focus → no-op). The idempotency check uses SphericalZone.hasLocationAtFocus.

      Parameters

      • value: { phi: number; radius: number; rho: number; theta: number }

      Returns Promise<void>

    • Strict on Quantity<'kg'>. Callers holding a raw number wrap via Quantity.of(n, 'kg') at the call site; tag / alt-unit authoring is the marshaller's job, not a runtime API concern.

      Parameters

      Returns void

    • Override the temperature at the room/vessel scope or at a specific detailKey. null clears the override (the next read falls through to the chain).

      Parameters

      • value: Quantity<"K"> | null
      • OptionaldetailKey: string

      Returns void

    • Stamp this Stuff's templatePath and re-key the byTemplatePath index so future findByTemplatePath lookups see the new path. No-op when path matches the current value.

      Locked down by @CallSecurity(ApiOnly) because flipping a Stuff's identity post-clone would break FromTemplate policies and any caller-side caching of template-path identity. @Final @Unshadowable because the index update has to run for every successful set — a subclass override that forgot the index call (or a shadow that intercepted) would silently desync byTemplatePath.

      Unwraps via ProxyApi.unwrap so the #-slot access lands on the raw target (see comment on #templatePath above).

      Parameters

      • path: string

      Returns void

    • Set the spatial zone. Gated by FromSpatialZone — only the SpatialZone class and its subclasses (CartesianZone, SphericalZone) may call this through the proxy. The addLocation / removeLocation chokepoints on the zone side are the legitimate callers; everyone else is rejected.

      Clone-time seeding from StuffApi.#cloneInner doesn't go through this method — it uses the caller-allowlisted _stampZone seam below.

      @Final @Unshadowable because the index of substrate invariants that consult getZone() (containment's cross-zone gate, Mobile.traverse, MQL scope walks) trusts the slot's value; a subclass override or shadow that lied about it could break those invariants. No legitimate subclass needs to extend this anyway — the only legitimate write paths are the SpatialZone chokepoints and clone-time.

      Parameters

      Returns void

    • Refresh the recency timestamp to now. Timestamp-fixed (no caller-supplied value). Called on the raw target by the security gate on every successful dispatch (Phase 2) and by the residency presence walk.

      Returns void

    • Mutual-exit invariant check, run at Location load (via postRegister) and on traversal as a fallback. Walks ONLY the _pendingVerify set — exits the addExit-time triage flagged as "could be wired but isn't yet."

      For each pending exit:

      • If it has settled by some other path (its inverse was wired by the destination's own verifier, it became oneWay / blocked, etc.), evict from the pending set and move on.
      • Else attempt to resolve: if the destination is now loaded and a matching back-exit exists, wire the inverse pointer pair. If the destination is loaded but the topology is wrong, mark the exit blocked = true with a logged warning. Either way, evict.
      • Else (destination still unloaded, or back-exit's destination unloaded), leave in the pending set for a future pass.

      Idempotent. Zone-derived cartesian exits are synthesized per-call and inherently mutual by grid adjacency — they aren't tracked.

      Returns void