5.8 KiB
World And Chunk Semantics
This document describes the current WorldShaper world/chunk behavior as of Arc 1.
It is a compatibility and refactor aid, not an endorsement of the long-term model.
Scope
These notes summarize the behavior currently implemented in:
src/worldChunking.tssrc/components/worldshaperShared.ts- regression tests in:
src/worldChunking.test.tssrc/components/worldshaperShared.test.ts
Coordinate Model
Chunk Dimensions
- chunk width and height are normalized with
normalizeChunkDimension - values are floored to integers
- invalid values fall back to
DEFAULT_WORLD_CHUNK_SIZE - normalized dimensions are clamped to a minimum of
1
World To Chunk Coordinates
- chunk coordinates use floor division
- this applies on both positive and negative world coordinates
- examples with chunk size
32:0 -> chunk 031 -> chunk 032 -> chunk 1-1 -> chunk -1-33 -> chunk -2
This means negative coordinates behave as mathematical grid cells, not truncation toward zero.
World To Local Coordinates
- local coordinates are derived from the resolved chunk coordinate
- formula:
world - (chunk * chunkSize) - result stays in the half-open range
[0, chunkSize) - examples with chunk size
32:31 -> local 3132 -> local 0-1 -> local 31-33 -> local 31
Local To World Coordinates
- formula:
(chunkCoord * chunkSize) + localCoord - examples with chunk size
32:chunk -2, local 31 -> world -33
Address Resolution
resolveWorldChunkAddress returns:
chunkXchunkYlocalXlocalYchunkKeyinx:yformfileNameinx_y.jsonform
Chunk Identity And Storage
- chunk keys use
buildChunkKey(chunkX, chunkY) - chunk filenames use
buildChunkFileName(chunkX, chunkY) - filenames preserve negative signs, for example
-3_4.json
Empty Chunk Defaults
createEmptyChunk currently creates:
- schema version
1 - top-level
backgroundTileId roomLayers[0]filled with.charactersroomLayers[1]filled with spaces- empty
heightLayers - empty
instances
This establishes the current meaning that:
.in layer0is the default empty background cell encoding- spaces in non-background layers represent empty overlay cells
Background Tile Behavior
getMapBackgroundTileId currently resolves background tiles in this order:
- top-level
backgroundTileId - legacy nested
tiles.backgroundTileId - empty string fallback
Arc 1 should treat the nested tiles.backgroundTileId shape as compatibility baggage.
Room Layer Semantics
parseRoomLayers currently does the following:
- parses
record.roomLayersif present - ignores malformed entries
- requires a numeric
layer - sorts output by ascending
layer - normalizes row sizes to map bounds
- uses
.fill for layer0 - uses space fill for non-zero layers
- filters blank
instanceIds
If no explicit layer 0 exists:
- a synthetic layer
0is created from top-levelrecord.rows
If there are no usable layers at all:
- a single synthetic layer
0is returned from top-levelrecord.rows
Current zIndex Behavior
- layer
0always getszIndex: 0 - non-zero layers preserve provided
zIndexif present - otherwise non-zero layers default to
0 - non-zero
zIndexvalues are clamped into[0, 5]
This is an important current behavior to preserve during Arc 1, but it looks at least partly accidental because non-zero layers do not derive zIndex from layer number.
Height Patch Semantics
parseHeightLayers currently treats height patches as sparse row-based overlays.
Input Interpretation
rowsare string arrays.is interpreted as empty space- empty margins are trimmed away
- patches are clipped to map bounds
Normalization Rules
- duplicate patch ids are dropped after the first occurrence
zis clamped to a minimum of1xandyare floored to integers- rows completely outside bounds become empty
- leading/trailing empty rows are removed
- leading/trailing empty columns are removed by cropping to occupied content
- trailing whitespace inside retained rows is stripped
Resulting Meaning
The current height patch encoding behaves more like a cropped sparse stamp than a fixed-size tile layer.
That is useful to document now because any future redesign needs to decide whether this sparse behavior is intentional or just a side effect of the current editor implementation.
Chunk Instance Semantics
Arc 1 has not redesigned chunk instances yet, but the current shape is:
id- optional
templateId layerxyrecord
The semantics of templateId + record are still under-specified and should be treated as a known redesign target for later arcs.
Likely Accidental Or Under-Specified Behavior
These behaviors are currently preserved, but should not be treated as settled architecture:
- non-background layers default to
zIndex: 0instead of deriving depth from layer number - duplicate height patch ids are silently dropped after the first occurrence
- top-level
rowsstill act as a fallback source for synthesized background layers - nested
tiles.backgroundTileIdis still accepted - layer
0empties use.while non-zero layer empties use spaces - chunk instance meaning is still implicit rather than explicitly modeled
Arc 2+ Questions
- Should negative-coordinate behavior remain floor-based, or should world addressing be modeled differently at a higher level?
- Should layer depth be derived from
layer,zIndex, or a clearer world-space model? - Should height data remain sparse text rows, or become a more explicit numeric structure?
- Should background tiles stay top-level, or belong to a clearer terrain/base-layer contract?
- What is the correct long-term meaning of chunk instances, templates, and per-instance overrides?