How Tapestries was built
Raw game files read
blocktypes/cloth/tapestry.jsonblocktypes/stone/wallcarving.jsonworldgen/schematics/**/*.json (BlockEntities attribute blobs, decoded)
Processing
Like paintings, blocktypes/cloth/tapestry.json/blocktypes/stone/
wallcarving.json get a full variant walk since tapestries have no recipe/drop table either.
What makes this page different is the second pass: every worldgen schematic file actually
referenced by a structure is pre-filtered (cheaply, from the header's block-code list) down to the
ones containing a tapestry-*/wallcarving-* code, then fully decoded --
the schematic's BlockEntities values are Ascii85-decoded into a binary
TreeAttribute blob per placed block instance, giving the real stored
type runtime attribute (e.g. temporality2).
This is a possibility list, not a guarantee. The game rerolls a schematic's authored tapestry to a uniformly random member of the same theme group at actual placement time (unless pinned), and separately has roughly a 60% chance of not spawning at all, with ~75% of the ones that do turning out rotten (no name/lore/drop). Every member of the reroll group is shown as a possible outcome for that structure, not just the schematic's own literal stored sample.
Each resolved outcome's lore-chapter link comes from the owning block's own
attributes.loreChapterIds map, cross-referenced against the matching lore book
(tapestry/wallcarving category) extracted the same way as any other book
-- see the lore source page.
Decoder. The TreeAttribute layouts follow the game's own
vsapi source (libs/vs-schematic/src/schematicDecode.ts). Every block entity in the
vanilla and BetterRuins schematics decodes without error (npm run decode-stats), and
npm test pins each attribute type.