pub struct PrefabMeta {Show 13 fields
pub prefab_id: String,
pub structure: Option<StructureMeta>,
pub structure_set: Option<TileSet>,
pub anchors: BTreeMap<String, Anchor>,
pub connectors: Vec<Connector>,
pub lighting: Option<Lighting>,
pub license: Option<License>,
pub walk_y: Option<i32>,
pub waterline_y: Option<i32>,
pub shown_faces: Vec<String>,
pub spatial_contract: Option<SpatialContract>,
pub footprint_class: Option<String>,
pub extra: BTreeMap<String, Value>,
}Expand description
A prefab’s sibling metadata file.
Fields§
§prefab_id: StringThe DSL prefab id, prefab/<id>.
structure: Option<StructureMeta>The structure-template reference, for a piece whose blocks fit one template.
Exactly one of this and Self::structure_set is present — see the
type’s own note on the two packagings, and Self::from_json, which is
where “exactly one” is enforced.
structure_set: Option<TileSet>The tile set, for a piece whose blocks did not fit one template.
Packaging, not authoring. A zone past the 48-per-axis structure cap
ships as several .nbt files plus this manifest; everything else about
the document — the id, the zone-local anchors, the connectors, the
one lighting block, the one provenance row — is what it is for a
single-template piece, because it describes the same building. Nothing
that refers to a piece may ask which of the two it is: read
Self::templates.
This was a second document type (TileSetMeta, in the schem crate),
field-for-field this one with structure swapped for structure_set.
The copy had already lost waterline_y, so a tiled shore could not
declare the waterline the ocean-horizon invariant (DW0344) keys off and
went silently unchecked. One document is what makes that class of drift
unrepresentable.
anchors: BTreeMap<String, Anchor>Named anchors, keyed by DSL anchor name. {} for a piece that declares
none.
connectors: Vec<Connector>Jigsaw sockets. [] for a piece that is placed directly rather than
drawn from a pool.
lighting: Option<Lighting>The lighting declaration.
Absent means legacy metadata that predates the field, which is a
different claim from {"profile": "unmeasured"} — the positive statement
that a measurement is owed.
The block’s own shape is Lighting, and it is the one part of this
document that still refuses a key it does not know. Its job is a rule
about values — a measured profile must carry its measurement, an
unmeasured one must not — so a misspelled measurement key there is a
claim quietly becoming its own absence, which the profile/measurement
agreement alone does not catch for rationale or method. The cost is
real and is stated where an author will meet it
(docs/reference/prefab-procedure.md §9): a key added inside lighting
is a hard parse failure for an older engine, so adding one is a
dsl_version matter rather than a metadata edit.
license: Option<License>Licence, provenance prose, and the machine-readable provenance row.
walk_y: Option<i32>The local y of this piece’s own walk plane — the cell a body’s feet occupy when it stands on the piece’s principal floor (spec-0060 §4).
This is the number an area’s origin is DERIVED from on a horizon whose
datum is a walk plane: an ocean world’s walk plane is SEA_LEVEL + 1,
so an area seating this piece is placed at walk_ref_y - walk_y and the
piece stands one block above the sea, which is the vanilla-normal beach
relationship. A keep interior declaring 1 is seated at 62 and stands
dry at 63; an island piece declaring 3 is seated at 60.
It has no default, and that is the decision (spec-0060 §4.1). A
default is the retired global datum wearing a different name: it would
be right for the one tileset it was copied from and silently wrong for
every other, and the piece that lands under the sea because of it floods
on boot with nothing looking. A piece a campaign seats without one is
DW0886.
It is a MEASUREMENT of the piece, so it is written by the generator that
built the piece and never typed by hand
(CLAUDE.md: a census derivable from the object is never hand-written).
waterline_y: Option<i32>The local y of this piece’s top authored water block — its waterline — for open-air pieces built to a tileset convention that authors a sea.
Two rules read it, and they ask different questions. DW0887 asks
whether the claim is TRUE — whether the piece’s own bytes put a water
block at that plane and none above it — and refuses a declaration that
is a fiction wherever the document and its .nbt are read together.
DW0344 asks whether the PLACEMENT honours it: in a horizon: ocean
world the declared waterline must land at world sea level.
Absent for pieces that author no sea, which neither rule then judges. A
piece that authors water and declares nothing is not refused by
DW0887; under ocean its placement is DW0344’s subject and under
void its runoff is DW0318’s.
shown_faces: Vec<String>The sides of this piece the player is meant to see — the piece’s own claim that a given face is finished exterior surface rather than the cut edge of something that belongs inside a hill.
Local side names, in the piece’s own frame, from the same six-word
vocabulary ContractFace::dir uses: east west up down south
north. They turn with the placement, so a piece rotated a quarter turn
shows the side it was built to show.
It is the third thing a piece says about its own outside, and the three
are different claims about the same object rather than one claim written
three ways: Self::waterline_y says where the piece meets the sea,
SpatialContract::faces says where a body crosses a side, and this
says which sides are finished. None of the others can stand in for it —
a cave with a mouth declares one walk face and is still a block of rock
on the other five — which is why DW0885 reads this and not them.
Absent means no side is shown, and that is the load-bearing default: a piece authored to be buried is exactly a piece that writes nothing here, so the silence has to be the strict answer or the defect declares itself by omission. What discharges the obligation for such a piece is the world burying it, which is geometry the declaration cannot fake.
spatial_contract: Option<SpatialContract>The piece’s spatial contract, when it declares one.
Absent means legacy metadata — the piece makes no spatial claim — exactly
as an absent lighting block differs from unmeasured.
footprint_class: Option<String>The size class of box this piece is built to fill — a name from the
metrics table’s size-class.* ladder (spec-0050 §5).
Optional for the library at large, and that is deliberate rather than
lax: every piece in the library predates the field, and DW0848 binds
only where the claim is made. What is not optional is the claim being
true — a piece declaring a class its own bytes could serve no box of is
refused at admission and again wherever a detail plan consumes it, so a
pre-check-era piece cannot be consumed unjudged.
Absent means what absence means everywhere in this document: the claim is
not made. A piece bound by a details[] row is still checked for exact
frame equality (DW0843) whether or not it declares — that is the
consumer’s exact check, and this is the library’s approximate one.
extra: BTreeMap<String, Value>Every top-level key this version does not model, kept verbatim so that reading and writing the document is not the same as editing it.
A reader that wants to report one has it in hand; a reader that does not care carries it through. Emitted after the modelled keys, in key order.
Implementations§
Source§impl PrefabMeta
impl PrefabMeta
Sourcepub fn from_json(text: &str) -> Result<PrefabMeta, String>
pub fn from_json(text: &str) -> Result<PrefabMeta, String>
Parse metadata from JSON text.
The one reader of both packagings. “Which shape is this” has exactly
two answers and no third, so a document declaring neither block, or both,
is refused here rather than handed half-read to a step that will place
some of its blocks. A tile set is validated as it is read
(TileSet::validate) for the same reason: a manifest that does not
tile its own volume reassembles into a building with a hole in it and
reports success.
Sourcepub fn templates(&self) -> Vec<PieceTemplate<'_>>
pub fn templates(&self) -> Vec<PieceTemplate<'_>>
Every structure template this piece’s blocks arrive in, in a deterministic order (grid order for a tile set).
Empty only for a value built in code that declares neither block, which
Self::from_json refuses — nothing read from disk is in that state.
Sourcepub fn size(&self) -> [i32; 3]
pub fn size(&self) -> [i32; 3]
The piece’s extent [x, y, z] — the WHOLE building, whichever packaging
its blocks arrived in. [0, 0, 0] only for the value
Self::templates documents as unreachable from disk.
Sourcepub fn data_version(&self) -> Option<i32>
pub fn data_version(&self) -> Option<i32>
The MC data version the piece’s templates target (ADR-0009), when it declares one.
Sourcepub fn is_tiled(&self) -> bool
pub fn is_tiled(&self) -> bool
True when the piece’s blocks arrive as several templates — a fact about packaging that only a tool reporting on packaging may ask.
Sourcepub fn base(&self) -> &str
pub fn base(&self) -> &str
The filename stem the piece’s files are named from — the single
template’s id, or the tile set’s base. They are the same concept
under two keys, so a diagnostic that wants to name the piece’s document
asks here rather than reaching into one packaging.
Sourcepub fn grid(&self) -> [i32; 3]
pub fn grid(&self) -> [i32; 3]
The tile grid [x, y, z]; [1, 1, 1] for a piece that fit one
template. Packaging, like Self::is_tiled.
Sourcepub fn read(path: &Path) -> Result<Option<PrefabMeta>, String>
pub fn read(path: &Path) -> Result<Option<PrefabMeta>, String>
Read the document at path, or Ok(None) when there is no file there.
Sourcepub fn beside_nbt(nbt_path: &Path) -> Result<Option<PrefabMeta>, String>
pub fn beside_nbt(nbt_path: &Path) -> Result<Option<PrefabMeta>, String>
Load <nbt_path>.json (the sibling metadata), or Ok(None) when absent.
Sourcepub fn schema() -> Value
pub fn schema() -> Value
The JSON Schema of this document, for delvec schema --stage prefab-metadata.
Deliberately not part of --stage all. all is the campaign DSL’s
staged documents, and the gallery’s coverage gate enumerates its units
from exactly that export: a library-asset document folded into it would
demand a gallery stage-document binding for every field of a file no
stage document contains. A prefab’s declarations are proven where they
are read — shown_faces by the exposure ledger, walk_y and
waterline_y by the seating and waterline bindings — which is a binding
a schema unit could not give them.
It is exported anyway, and for the reason the walk record is: this is the command an author is told to run to see the shape of a document they must write, and a piece’s metadata is one of those.
Sourcepub fn unknown_keys(&self) -> Vec<(&str, &str)>
pub fn unknown_keys(&self) -> Vec<(&str, &str)>
Every key of this document — top level and per anchor — that this version
does not model, as (where, key) pairs in a stable order.
where is "" for a top-level key and the anchor’s name for an anchor
key. A reader that wants to say something about a key it kept asks here;
nothing has to re-open the file to find out.
Sourcepub fn skeleton(
id: &str,
size: [i32; 3],
data_version: i32,
generator: &str,
license: License,
) -> PrefabMeta
pub fn skeleton( id: &str, size: [i32; 3], data_version: i32, generator: &str, license: License, ) -> PrefabMeta
A minimal skeleton for a freshly admitted external piece.
Sourcepub fn edit_anchor(&mut self, name: &str, edit: AnchorEdit)
pub fn edit_anchor(&mut self, name: &str, edit: AnchorEdit)
Annotate a named anchor’s place and purpose, creating the anchor when it is not there yet.
An anchor is an object, not a value. A tool that names where the anchor
is has said nothing about the hardware the prefab wired at it
(Anchor::dispenser, Anchor::trigger_block), about which contract
element an exporter resolved it into (Anchor::resolves_to), or about
any key this version has never heard of (Anchor::extra) — so none of
those is touched. Replacing the whole anchor instead is the same silent
deletion this type exists to prevent at the top level, one level down,
and on the block of the document that has grown most often.
The place itself is one property expressed two ways — a cell or a region
— so an edit redeclares all four of its fields together and a pos does
supersede a stale region.
The role is a fifth field and not a fifth way of saying where: what
an anchor is for is a property of the anchor, so it is written when the
edit speaks about it, cleared when the edit says it has none, and left
alone when the edit says nothing (AnchorEdit::role).
Sourcepub fn gate_anchor(&self, name: &str) -> Result<Option<GateAnchor>, String>
pub fn gate_anchor(&self, name: &str) -> Result<Option<GateAnchor>, String>
The ONE authority on the region and block a gate anchor names, in piece-local coordinates.
A gate anchor is declared in one of two forms, and the compiler must read both identically:
- explicitly — the anchor carries its own
regionandblock, which is how a hand-authored piece has always written one; - through the piece’s spatial contract — the anchor carries a
resolves_toofbar:<region>, which is what an exporter writes. The cells and the block already live in that edge’sContractBar, so repeating them on the anchor would be a second authority for one fact, and the exporter rightly does not.
Nothing derived either form from the other, and the whole compiler read
only the first. A piece declaring its gates the second way therefore had
no gate at all: the anchor resolved to a bare point, every verb that fills
or clears a gate was refused (DW0343), and the information the refusal
asked for was sitting in the same document.
Both readers ask this function and nothing else — the planner, which
resolves the anchor to world cells, and
AnchorRegistry’s prefab implementation, which
answers whether the compiler can fill it — so the two cannot come to
disagree about what a gate is or where it stands.
Three answers, and the third is the one that earns the Result:
Ok(None)— not a gate anchor. A point anchor, a trap anchor, or an anchor whoseresolves_tonames a space, ano_bodyregion, aviavolume or away. None of those is a thing content fills or clears.Ok(Some(gate))— a gate, and here is the box and the block.Err(why)— declared as a gate and not resolvable to one fillable box. Refused rather than guessed, because every alternative writes blocks somewhere the document did not ask for.whyis a clause the caller folds into its own diagnostic.
A way is deliberately not a gate here. Its
opens is a direction — laid cells are absent as
built and appear when opened, cleared cells stand and are voided — and
the single-region gate model carries no direction to put it in. Reading
one as a gate would silently pick a direction for the author.
Sourcepub fn add_connector(&mut self, c: Connector)
pub fn add_connector(&mut self, c: Connector)
Append a socket connector (idempotent by local_pos + facing).
Trait Implementations§
Source§impl Clone for PrefabMeta
impl Clone for PrefabMeta
Source§fn clone(&self) -> PrefabMeta
fn clone(&self) -> PrefabMeta
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for PrefabMeta
impl Debug for PrefabMeta
Source§impl<'de> Deserialize<'de> for PrefabMeta
impl<'de> Deserialize<'de> for PrefabMeta
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl JsonSchema for PrefabMeta
impl JsonSchema for PrefabMeta
Source§fn schema_id() -> Cow<'static, str>
fn schema_id() -> Cow<'static, str>
Source§fn json_schema(generator: &mut SchemaGenerator) -> Schema
fn json_schema(generator: &mut SchemaGenerator) -> Schema
Source§fn inline_schema() -> bool
fn inline_schema() -> bool
$ref keyword. Read more