luv

Workshop wiki

world.lisp

luvcraft/world.lisp

system luvcraft/world · 113 definitions · on GitHub

Discrete world coordinates, finite chunk domains, and resident block data.

in-package#:luvcraft.world

Coordinate values are deliberately distinct even though all three carry integer components. World, chunk, and domain-local addresses are not interchangeable. World and chunk coordinates may be negative; local coordinates are checked by a particular chunk domain.

declaim
inline%make-world-coordinate
defstruct
world-coordinate
:constructor%make-world-coordinate
xyz
x0:typeinteger:read-onlyt
y0:typeinteger:read-onlyt
z0:typeinteger:read-onlyt
defunmake-world-coordinate
xyz
check-typexinteger
check-typeyinteger
check-typezinteger
%make-world-coordinatexyz
declaim
inline%make-chunk-coordinate
defstruct
chunk-coordinate
:constructor%make-chunk-coordinate
xyz
x0:typeinteger:read-onlyt
y0:typeinteger:read-onlyt
z0:typeinteger:read-onlyt
defunmake-chunk-coordinate
xyz
check-typexinteger
check-typeyinteger
check-typezinteger
%make-chunk-coordinatexyz
declaim
inline%make-local-coordinate
defstruct
local-coordinate
:constructor%make-local-coordinate
xyz
x0:typeinteger:read-onlyt
y0:typeinteger:read-onlyt
z0:typeinteger:read-onlyt
defunmake-local-coordinate
xyz
check-typexinteger
check-typeyinteger
check-typezinteger
%make-local-coordinatexyz

A primitive direction is a displacement, not any of the affine coordinate kinds above. The six shared instances are safe to retain indefinitely; temporary coordinates translated by them may instead be DYNAMIC-EXTENT.

declaim
inline%make-voxel-direction
defstruct
voxel-direction
:constructor%make-voxel-direction
dxdydz
dx0:type
integer-11
:read-onlyt
dy0:type
integer-11
:read-onlyt
dz0:type
integer-11
:read-onlyt
defunmake-voxel-direction
dxdydz
unless
and
integerpdx
integerpdy
integerpdz
error"(~S ~S ~S) is not a primitive voxel direction."dxdydz
%make-voxel-directiondxdydz
defunworld-coordinate-neighbor
coordinatedirection

Translate a world cell address by one primitive direction.

check-typecoordinateworld-coordinate
check-typedirectionvoxel-direction
make-world-coordinate
+
world-coordinate-xcoordinate
voxel-direction-dxdirection
+
world-coordinate-ycoordinate
voxel-direction-dydirection
+
world-coordinate-zcoordinate
voxel-direction-dzdirection
defunchunk-coordinate-neighbor
coordinatedirection

Translate a chunk address by one primitive direction.

check-typecoordinatechunk-coordinate
check-typedirectionvoxel-direction
make-chunk-coordinate
+
chunk-coordinate-xcoordinate
voxel-direction-dxdirection
+
chunk-coordinate-ycoordinate
voxel-direction-dydirection
+
chunk-coordinate-zcoordinate
voxel-direction-dzdirection
defunopposite-voxel-direction
direction
check-typedirectionvoxel-direction
defstruct
chunk-shape
:constructor%make-chunk-shape
width16:type
integer1
:read-onlyt
height16:type
integer1
:read-onlyt
depth16:type
integer1
:read-onlyt
defunmake-chunk-shape
&key
depth16
dolist
check-typedimension
integer1
%make-chunk-shapewidthheightdepth
defunnormalize-cell-extent
extent
let
components
etypecaseextent
real
listextentextentextent
sequence
unless
=
lengthextent
3
error"A voxel cell extent needs exactly three components."
coerceextent'list
unless
every
lambda
component
and
realpcomponent
pluspcomponent
components
error"Voxel cell extents must be positive real numbers: ~S"extent
apply#'make-vec3
mapcar
lambda
component
coercecomponent'double-float
components
defclassvoxel-space
id:initarg:id:readervoxel-space-id
chunk-shape:initarg:chunk-shape:readervoxel-space-chunk-shape
cell-extent:initarg:cell-extent:typevec3:quantity
:quantity:voxel-cell-extent:unit
:metre1
:cell-1
:tensor-order1
:readervoxel-space-cell-extent
defunmake-voxel-space
&key
id
gensym"VOXEL-SPACE-"
chunk-shape
cell-extent1d0
check-typechunk-shapechunk-shape
make-instance'voxel-space:idid:chunk-shapechunk-shape:cell-extent
defunworld-coordinate-cell-origin
spacecoordinate

Map a discrete cell coordinate through space's explicit metric extent.

check-typespacevoxel-space
check-typecoordinateworld-coordinate
let
extent
voxel-space-cell-extentspace
make-vec3
*
world-coordinate-xcoordinate
vec3-xextent
*
world-coordinate-ycoordinate
vec3-yextent
*
world-coordinate-zcoordinate
vec3-zextent
defunvoxel-space-decompose-components
spacexyz

Decompose a world site into chunk and local scalar components.

Return CHUNK-X, CHUNK-Y, CHUNK-Z, LOCAL-X, LOCAL-Y, and LOCAL-Z without constructing coordinate objects. Euclidean division keeps every local component non-negative, including for negative world coordinates. This is the dense traversal counterpart of world-coordinate-chunk-and-local.

check-typespacevoxel-space
check-typexinteger
check-typeyinteger
check-typezinteger
let
shape
voxel-space-chunk-shapespace
multiple-value-bind
chunk-xlocal-x
floorx
chunk-shape-widthshape
multiple-value-bind
chunk-ylocal-y
floory
chunk-shape-heightshape
multiple-value-bind
chunk-zlocal-z
floorz
chunk-shape-depthshape
valueschunk-xchunk-ychunk-zlocal-xlocal-ylocal-z
defunworld-coordinate-chunk-and-local
spacecoordinate

Decompose coordinate by Euclidean division in space.

The local result is always non-negative, including for negative world coordinates.

check-typespacevoxel-space
check-typecoordinateworld-coordinate
multiple-value-bind
chunk-xchunk-ychunk-zlocal-xlocal-ylocal-z
voxel-space-decompose-componentsspace
world-coordinate-xcoordinate
world-coordinate-ycoordinate
world-coordinate-zcoordinate
values
make-chunk-coordinatechunk-xchunk-ychunk-z
make-local-coordinatelocal-xlocal-ylocal-z
defunchunk-local-world-coordinate
spacechunklocal
check-typespacevoxel-space
check-typechunkchunk-coordinate
check-typelocallocal-coordinate
let
shape
voxel-space-chunk-shapespace
unless
and
<
local-coordinate-xlocal
chunk-shape-widthshape
<
local-coordinate-ylocal
chunk-shape-heightshape
<
local-coordinate-zlocal
chunk-shape-depthshape
not
minusp
local-coordinate-xlocal
not
minusp
local-coordinate-ylocal
not
minusp
local-coordinate-zlocal
error"Local coordinate ~S is outside chunk shape ~S."localshape
make-world-coordinate
+
*
chunk-coordinate-xchunk
chunk-shape-widthshape
local-coordinate-xlocal
+
*
chunk-coordinate-ychunk
chunk-shape-heightshape
local-coordinate-ylocal
+
*
chunk-coordinate-zchunk
chunk-shape-depthshape
local-coordinate-zlocal

A chunk domain gives one resident materialization a stable site identity and owns the checked local-coordinate <-> dense-offset correspondence. X is the contiguous axis: x + width * (y + height * z).

defclasschunk-domain
space:initarg:space:readerchunk-domain-space
coordinate:initarg:coordinate:readerchunk-domain-coordinate
defunmake-chunk-domain
spacecoordinate
check-typespacevoxel-space
check-typecoordinatechunk-coordinate
make-instance'chunk-domain:spacespace:coordinatecoordinate
defmethoddomains:domain-cardinality
let
shape
voxel-space-chunk-shape
chunk-domain-spacedomain
*
chunk-shape-widthshape
chunk-shape-heightshape
chunk-shape-depthshape
defunchunk-domain-origin
domain
chunk-local-world-coordinate
chunk-domain-spacedomain
chunk-domain-coordinatedomain
defunchunk-domain-local-coordinate-p
domainlocal
check-typedomainchunk-domain
check-typelocallocal-coordinate
let
shape
voxel-space-chunk-shape
chunk-domain-spacedomain
and
<=0
local-coordinate-xlocal
<
local-coordinate-xlocal
chunk-shape-widthshape
<=0
local-coordinate-ylocal
<
local-coordinate-ylocal
chunk-shape-heightshape
<=0
local-coordinate-zlocal
<
local-coordinate-zlocal
chunk-shape-depthshape
defunchunk-domain-offset
domainlocal
unless
error"Local coordinate ~S is outside domain ~S."localdomain
chunk-domain-offset-componentsdomain
local-coordinate-xlocal
local-coordinate-ylocal
local-coordinate-zlocal
defunchunk-domain-offset-components
domainxyz

Map scalar local coordinates to a dense offset without a row object.

check-typedomainchunk-domain
let
shape
voxel-space-chunk-shape
chunk-domain-spacedomain
unless
and
typepx'integer
<=0x
<x
chunk-shape-widthshape
typepy'integer
<=0y
<y
chunk-shape-heightshape
typepz'integer
<=0z
<z
chunk-shape-depthshape
error"Local coordinate (~S ~S ~S) is outside domain ~S."xyzdomain
+x
*
chunk-shape-widthshape
+y
*
chunk-shape-heightshape
z
defunchunk-domain-local-coordinate
domainoffset
multiple-value-bind
xyz
defunchunk-domain-world-coordinate
domainlocal

Return the world coordinate of local in domain.

check-typedomainchunk-domain
check-typelocallocal-coordinate
chunk-local-world-coordinate
chunk-domain-spacedomain
chunk-domain-coordinatedomain
local
defunchunk-domain-local-components
domainoffset

Map a dense offset to local scalar components without a row object.

check-typedomainchunk-domain
check-typeoffset
integer0
unless
error"Offset ~D is outside domain ~S."offsetdomain
let*
shape
voxel-space-chunk-shape
chunk-domain-spacedomain
width
chunk-shape-widthshape
height
chunk-shape-heightshape
multiple-value-bind
zremainder
multiple-value-bind
yx
floorremainderwidth
valuesxyz
defunchunk-domain-world-components
domainlocal-xlocal-ylocal-z

Map local scalar components to world scalar components without objects.

Use the checked offset operation as the single local-bounds authority.

chunk-domain-offset-componentsdomainlocal-xlocal-ylocal-z
let*
shape
voxel-space-chunk-shape
chunk-domain-spacedomain
coordinate
chunk-domain-coordinatedomain
values
+
*
chunk-coordinate-xcoordinate
chunk-shape-widthshape
local-x
+
*
chunk-coordinate-ycoordinate
chunk-shape-heightshape
local-y
+
*
chunk-coordinate-zcoordinate
chunk-shape-depthshape
local-z
defmacrowith-chunk-domain-step
offsetdestinationcrossing
domainlocaldirection&bodybody

Execute body for one primitive step from local inside domain.

offset, DESTINATION, and CROSSING are bound as by step-chunk-domain-site, but DESTINATION has dynamic extent and must be copied before body retains it. The compiler-visible lifetime keeps rejected adjacency probes off the heap. #E4T0PD

let
domain-value
gensym"DOMAIN"
local-value
gensym"LOCAL"
direction-value
gensym"DIRECTION"
shape
gensym"SHAPE"
width
gensym"WIDTH"
height
gensym"HEIGHT"
depth
gensym"DEPTH"
crossing-x
gensym"CROSSING-X"
crossing-y
gensym"CROSSING-Y"
crossing-z
gensym"CROSSING-Z"
local-x
gensym"LOCAL-X"
local-y
gensym"LOCAL-Y"
local-z
gensym"LOCAL-Z"
`
let*
,domain-value,domain
,local-value,local
,direction-value,direction
check-type,local-valuelocal-coordinate
check-type,direction-valuevoxel-direction
chunk-domain-offset,domain-value,local-value
let*
,shape
voxel-space-chunk-shape
chunk-domain-space,domain-value
,width
chunk-shape-width,shape
,height
chunk-shape-height,shape
,depth
chunk-shape-depth,shape
multiple-value-bind
,crossing-x,local-x
floor
+
local-coordinate-x,local-value
voxel-direction-dx,direction-value
,width
multiple-value-bind
,crossing-y,local-y
floor
+
local-coordinate-y,local-value
voxel-direction-dy,direction-value
,height
multiple-value-bind
,crossing-z,local-z
floor
+
local-coordinate-z,local-value
voxel-direction-dz,direction-value
,depth
let
,destination
make-local-coordinate,local-x,local-y,local-z
,offset
+,local-x
*,width
+,local-y
*,height,local-z
,crossing
and
not
zerop
+
abs,crossing-x
abs,crossing-y
abs,crossing-z
,direction-value
declare
dynamic-extent,destination
,@body
defunstep-chunk-domain-site
domainlocaldirection

Step from one local site in a primitive face direction.

Return the destination OFFSET and wrapped LOCAL-COORDINATE, followed by direction when the step crosses into that adjacent chunk or NIL when it stays inside domain.

with-chunk-domain-step
offsetdestinationcrossing
domainlocaldirection
valuesoffset
copy-local-coordinatedestination
crossing
defgenericlocate-chunk-window-site
windowxyz
:documentation

Resolve world site X,Y,Z through window.

Return (VALUES MATERIALIZATION OFFSET AVAILABILITY). AVAILABILITY is :AVAILABLE or :UNAVAILABLE; field and subsystem policy must interpret that fact rather than making the spatial protocol call absence air, solid, zero, or open sky. Implementations keep their existing aggregate representation.

defmacrowith-chunk-window-step
offsetdestinationcrossingmaterializationavailability
windowdomainlocaldirection&bodybody

Execute body for one domain step continued through window when necessary.

DESTINATION has dynamic extent. MATERIALIZATION and AVAILABILITY are selected through locate-chunk-window-site only for a boundary crossing. #YUBB7X

let
window-value
gensym"WINDOW"
domain-value
gensym"DOMAIN"
local-value
gensym"LOCAL"
direction-value
gensym"DIRECTION"
local-offset
gensym"LOCAL-OFFSET"
world-x
gensym"WORLD-X"
world-y
gensym"WORLD-Y"
world-z
gensym"WORLD-Z"
`
let
,window-value,window
,domain-value,domain
,local-value,local
,direction-value,direction
with-chunk-domain-step
,local-offset,destination,crossing
,domain-value,local-value,direction-value
multiple-value-bind
,materialization,offset,availability
if,crossing
multiple-value-bind
,world-x,world-y,world-z
chunk-domain-world-components,domain-value
local-coordinate-x,local-value
local-coordinate-y,local-value
local-coordinate-z,local-value
locate-chunk-window-site,window-value
+,world-x
voxel-direction-dx,direction-value
+,world-y
voxel-direction-dy,direction-value
+,world-z
voxel-direction-dz,direction-value
valuesnil,local-offset:local
,@body
defmacrodo-chunk-window-neighbors
offsetdestinationcrossingdirectionmaterializationavailabilitywindowdomainlocaldirections&optionalresult
&bodybody

Execute body for the DIRECTIONS neighboring LOCAL through WINDOW.

DIRECTIONS is the caller's explicit neighborhood policy. DESTINATION has dynamic extent on each iteration and must be copied before body retains it. Interior steps remain domain arithmetic; window dispatch occurs only at an actual chunk crossing. #E4T0PD

let
window-value
gensym"WINDOW"
domain-value
gensym"DOMAIN"
local-value
gensym"LOCAL"
directions-value
gensym"DIRECTIONS"
`
let
,window-value,window
,domain-value,domain
,local-value,local
,directions-value,directions
dolist
,direction,directions-value,result
with-chunk-window-step
,offset,destination,crossing,materialization,availability
,window-value,domain-value,local-value,direction
,@body
defmacrodo-chunk-site-neighbors
offsetcrossingdirectionmaterializationavailabilitywindowdomainsite-offsetdirections&optionalresult
&bodybody

Execute body for the DIRECTIONS neighboring the site at SITE-OFFSET.

This is the trusted-scope counterpart of do-chunk-window-neighbors for a site already proved to belong to DOMAIN, such as one popped from a packed frontier. DOMAIN and SITE-OFFSET are validated once; the shape's dimensions and the site's components are then bound as fixnums, and each direction is a primitive step with no coordinate object and no repeated bounds or type check. offset is the destination's dense offset, CROSSING the direction when the step leaves DOMAIN, and MATERIALIZATION with AVAILABILITY are selected through locate-chunk-window-site only for a crossing. Public stepping keeps its checks; this scope pays them once per visited site. #FGT96H

let
window-value
gensym"WINDOW"
domain-value
gensym"DOMAIN"
site
gensym"SITE"
shape
gensym"SHAPE"
width
gensym"WIDTH"
height
gensym"HEIGHT"
depth
gensym"DEPTH"
chunk
gensym"CHUNK"
chunk-x
gensym"CHUNK-X"
chunk-y
gensym"CHUNK-Y"
chunk-z
gensym"CHUNK-Z"
site-x
gensym"SITE-X"
site-y
gensym"SITE-Y"
site-z
gensym"SITE-Z"
crossing-x
gensym"CROSSING-X"
crossing-y
gensym"CROSSING-Y"
crossing-z
gensym"CROSSING-Z"
local-x
gensym"LOCAL-X"
local-y
gensym"LOCAL-Y"
local-z
gensym"LOCAL-Z"
local-offset
gensym"LOCAL-OFFSET"
`
let*
,window-value,window
,domain-value,domain
,site,site-offset
check-type,domain-valuechunk-domain
check-type,site
integer0#.most-positive-fixnum
let*
,shape
voxel-space-chunk-shape
chunk-domain-space,domain-value
,width
chunk-shape-width,shape
,height
chunk-shape-height,shape
,depth
chunk-shape-depth,shape
,chunk
chunk-domain-coordinate,domain-value
,chunk-x
chunk-coordinate-x,chunk
,chunk-y
chunk-coordinate-y,chunk
,chunk-z
chunk-coordinate-z,chunk
declare
type
integer1#.most-positive-fixnum
,width,height,depth
typefixnum,chunk-x,chunk-y,chunk-z
unless
error"Offset ~D is outside domain ~S.",site,domain-value
multiple-value-bind
declare
multiple-value-bind
declare
dolist
,direction,directions,result
multiple-value-bind
,crossing-x,local-x
floor
+,site-x
voxel-direction-dx,direction
,width
multiple-value-bind
,crossing-y,local-y
floor
+,site-y
voxel-direction-dy,direction
,height
multiple-value-bind
,crossing-z,local-z
floor
+,site-z
voxel-direction-dz,direction
,depth
declare
typefixnum,crossing-x,crossing-y,crossing-z,local-x,local-y,local-z
let
,local-offset
+,local-x
*,width
+,local-y
*,height,local-z
,crossing
and
or
/=0,crossing-x
/=0,crossing-y
/=0,crossing-z
,direction
declare
typefixnum,local-offset
multiple-value-bind
,materialization,offset,availability
if,crossing
locate-chunk-window-site,window-value
+
*,chunk-x,width
,site-x
voxel-direction-dx,direction
+
*,chunk-y,height
,site-y
voxel-direction-dy,direction
+
*,chunk-z,depth
,site-z
voxel-direction-dz,direction
valuesnil,local-offset:local
,@body
defuncontinue-chunk-window-site
windowdomainlocaldirection

Step local and resolve window only when the step crosses domain.

Return the destination OFFSET, wrapped LOCAL-COORDINATE, and crossing as step-chunk-domain-site does, followed by the neighboring MATERIALIZATION and its AVAILABILITY. A local step returns NIL and :local for the last two values. The one generic window decision therefore occurs only at an aggregate boundary, never for every site in a dense traversal. #L84JCX

with-chunk-window-step
offsetdestinationcrossingmaterializationavailability
windowdomainlocaldirection
valuesoffset
copy-local-coordinatedestination
crossingmaterializationavailability
defmacrodo-chunk-domain-sites
offsetlocaldomain&optionalresult
&bodybody

Execute body for every site in DOMAIN, in dense storage order.

LOCAL is a DYNAMIC-EXTENT LOCAL-COORDINATE and must not be retained after body returns. This gives dense algorithms a nominal coordinate without one heap allocation per site. See #B3UEVE.

let
domain-value
gensym"DOMAIN"
shape
gensym"SHAPE"
width
gensym"WIDTH"
height
gensym"HEIGHT"
depth
gensym"DEPTH"
x
gensym"X"
y
gensym"Y"
z
gensym"Z"
`
let*
,domain-value,domain
,shape
voxel-space-chunk-shape
chunk-domain-space,domain-value
,width
chunk-shape-width,shape
,height
chunk-shape-height,shape
,depth
chunk-shape-depth,shape
,offset0
dotimes
,z,depth
dotimes
dotimes
let
declare
dynamic-extent,local
,@body
incf,offset
,result
defmacrodo-chunk-domain-face
offsetlocaldomaindirection&optionalresult
&bodybody

Execute body for every site on DIRECTION's boundary face in DOMAIN.

LOCAL is a DYNAMIC-EXTENT LOCAL-COORDINATE and must not be retained after body returns.

let
domain-value
gensym"DOMAIN"
direction-value
gensym"DIRECTION"
shape
gensym"SHAPE"
width
gensym"WIDTH"
height
gensym"HEIGHT"
depth
gensym"DEPTH"
x-low
gensym"X-LOW"
x-high
gensym"X-HIGH"
y-low
gensym"Y-LOW"
y-high
gensym"Y-HIGH"
z-low
gensym"Z-LOW"
z-high
gensym"Z-HIGH"
x
gensym"X"
y
gensym"Y"
z
gensym"Z"
`
let*
,domain-value,domain
,direction-value,direction
,shape
voxel-space-chunk-shape
chunk-domain-space,domain-value
,width
chunk-shape-width,shape
,height
chunk-shape-height,shape
,depth
chunk-shape-depth,shape
check-type,direction-valuevoxel-direction
let
,x-low
if
=
voxel-direction-dx,direction-value
1
0
,x-high
if
=
voxel-direction-dx,direction-value
-1
0
,y-low
if
=
voxel-direction-dy,direction-value
1
0
,y-high
if
=
voxel-direction-dy,direction-value
-1
0
,z-low
if
=
voxel-direction-dz,direction-value
1
1-,depth
0
,z-high
if
=
voxel-direction-dz,direction-value
-1
0
1-,depth
loopfor,zfrom,z-lowto,z-highdo
loopfor,yfrom,y-lowto,y-highdo
loopfor,xfrom,x-lowto,x-highdo
let
,offset
declare
dynamic-extent,local
,@body
,result

Block content is a narrow semantic field. The presentable value is a shared Lisp object (or NIL for air); the physical column is a dense u16 offset under the world's block vocabulary. A site is an offset in a domain, not an object with an identity or allocation of its own. Computational code should borrow the aggregate storage below and dispatch once per chunk. Single-site world access still resolves through coordinate descriptors and a chunk key; it is for inspectors, sparse interaction, and other genuinely row-shaped work.

The block vocabulary is the finite domain a content column's indices are closed by: an append-only, world-wide ordering of block objects with NIL (air) at offset zero. One world has one vocabulary, so every chunk's u16 columns mean the same thing, snapshots need no translation, and per-kind tables can be materialized once per vocabulary revision rather than once per chunk. Membership grows only when a never-seen block is placed; offsets never move, so a shape change leaves every existing column and derived product valid. See #CPCZDB.

defclassblock-vocabulary
:documentation

An append-only finite domain of block objects; NIL is always offset 0.

MEMBERS is the adjustable vector interpreting every dense offset; borrowing it as a palette is the ordinary way whole-domain code reads block identity.

defunmake-block-vocabulary
&keymembers

Return a vocabulary with NIL at offset 0 followed by members in order.

make-instance'block-vocabulary:members
consnil
coercemembers'list
:limit#x10000
defunblock-vocabulary-members
vocabulary
domains:identity-vocabulary-membersvocabulary
defunblock-vocabulary-revision
vocabulary
domains:identity-vocabulary-revisionvocabulary
defunblock-vocabulary-member
vocabularyoffset

Return the block object interpreted by offset under vocabulary.

defunblock-vocabulary-offset
vocabularyblock&optional
intern-pt

Return block's dense offset, appending it when intern-p and it is new.

Return NIL for an unknown block when intern-p is false.

domains:identity-vocabulary-offsetvocabularyblockintern-p
defunblock-vocabulary-translation
sourcetarget

Return a u16 vector mapping every source offset to its target offset.

target interns any member it lacks, so the translation is always total.

let*
translation
make-array
lengthmembers
:element-type'
unsigned-byte16
dotimes
offset
lengthmembers
translation
setf
areftranslationoffset
block-vocabulary-offsettarget
arefmembersoffset
defclassblock-content-column
domain:initarg:domain:readerblock-content-column-domain
definition:initarg:definition:initform:readerblock-content-column-definition
vocabulary:initarg:vocabulary:readerblock-content-column-vocabulary
indices:initarg:indices:readerblock-content-column-indices
defunblock-content-column-palette
column

Return the vocabulary's member vector interpreting column's indices.

block-vocabulary-members
block-content-column-vocabularycolumn
defmethodinitialize-instance:after
let
domain
block-content-column-domaincolumn
vocabulary
block-content-column-vocabularycolumn
indices
block-content-column-indicescolumn
check-typedomainchunk-domain
check-typevocabularyblock-vocabulary
check-typeindices
array
unsigned-byte16
unless
error"Block content has ~D indices; domain ~S requires ~D."
lengthindices
domain
let
cardinality
dotimes
offset
lengthindices
unless
<
arefindicesoffset
cardinality
error"Vocabulary offset ~D at offset ~D exceeds cardinality ~D."
arefindicesoffset
offsetcardinality
defmethodfields:field-representation-domain
block-content-column-domaincolumn
defmethodluvcraft.world.fields:materialized-field-definition
field-name
eql:block-content
declare
ignorefield-name
block-content-column-definitioncolumn
defmethodfields:materialized-field-representation
field-name
eql:block-content
declare
ignorefield-name
column
defunmake-block-content-column
domain&keyvocabularyindices

Make a content column over domain under vocabulary.

make-instance'block-content-column:domaindomain:vocabulary:indices
orindices
make-array:element-type'
unsigned-byte16
:initial-element0
defunrebind-block-content-column
columndomain&optionalvocabulary

Bind column's transferred storage to the resident domain and vocabulary.

The caller owns column's storage: when its vocabulary differs from the target, the indices are translated in place so the same dense array serves under the new interpretation.

let
vocabulary
orvocabulary
block-content-column-vocabularycolumn
if
and
eq
block-content-column-domaincolumn
domain
eq
block-content-column-vocabularycolumn
vocabulary
column
let
indices
block-content-column-indicescolumn
unless
eq
block-content-column-vocabularycolumn
vocabulary
let
translation
block-vocabulary-translation
block-content-column-vocabularycolumn
vocabulary
dotimes
offset
lengthindices
setf
arefindicesoffset
areftranslation
arefindicesoffset
make-block-content-columndomain:vocabularyvocabulary:indicesindices
defunblock-content-at-offset
columnoffset
aref
aref
block-content-column-indicescolumn
offset
defgenericborrow-block-content-storage
chunk
:documentation

Return DOMAIN, palette, and INDICES borrowed from chunk without copying.

This is the ordinary entry point for whole-domain computation. Generic dispatch chooses a representation once; the caller then traverses the dense specialized arrays rather than describing individual cells through CLOS.

defmethodborrow-block-content-storage
values
block-content-column-domaincolumn
block-content-column-indicescolumn
defmacrowith-block-content-storage
domainpaletteindices
chunk&bodybody

Execute body with the three borrowed block-content storage values.

`
multiple-value-bind
,domain,palette,indices
,@body
defunensure-block-content-palette-index
columnblock
block-vocabulary-offset
block-content-column-vocabularycolumn
block
defunset-block-content-at-offset
columnoffsetblock
let*
indices
block-content-column-indicescolumn
old-index
arefindicesoffset
unless
=old-indexnew-index
setf
arefindicesoffset
new-index
t
defclassblock-chunk
domain:initarg:domain:readerblock-chunk-domain
content:initarg:content:readerblock-chunk-content
incarnation:initarg:incarnation:initform0:readerblock-chunk-incarnation
change-hook:initarg:change-hook:initformnil
revision:initform0:readerblock-chunk-revision

-X, +X, -Y, +Y, -Z, +Z. A derived product for one chunk depends on only the opposing boundary revision of each neighbor, not on arbitrary edits in that neighbor's interior.

boundary-revisions:initform
make-array6:element-type'
unsigned-byte64
:initial-element0

The chunk's derived voxel light, revised independently from block content. NIL until a lighting solver publishes a field.

light-field:initformnil:accessorblock-chunk-light-field
defunmake-block-chunk
domain&keychange-hook
incarnation0
contentvocabulary

Make a chunk over domain, binding content (or fresh air) to vocabulary.

check-typedomainchunk-domain
unless
or
nullchange-hook
functionpchange-hook
error"A block chunk change hook must be a function or NIL."
make-instance'block-chunk:domaindomain:incarnationincarnation:change-hookchange-hook:content
ifcontent
rebind-block-content-columncontentdomainvocabulary
make-block-content-columndomain:vocabularyvocabulary
defmethodfields:materialized-field-representation
field-name
eql:block-content
declare
ignorefield-name
block-chunk-contentchunk
defunchunk-block-at
chunkxyz
check-typechunkblock-chunk
defunchunk-block-at-offset
chunkoffset

Read one dense site from chunk without constructing a coordinate object.

check-typechunkblock-chunk
check-typeoffset
integer0
unless
<offset
chunk-domain-cardinality
block-chunk-domainchunk
error"Offset ~D is outside chunk ~S."offsetchunk
block-content-at-offset
block-chunk-contentchunk
offset
defunchunk-boundary-index
direction
check-typedirectionvoxel-direction
let
dx
voxel-direction-dxdirection
dy
voxel-direction-dydirection
dz
voxel-direction-dzdirection
cond
and
=dx-1
zeropdy
zeropdz
0
and
=dx1
zeropdy
zeropdz
1
and
zeropdx
=dy-1
zeropdz
2
and
zeropdx
=dy1
zeropdz
3
and
zeropdx
zeropdy
=dz-1
4
and
zeropdx
zeropdy
=dz1
5
t
error"~S is not a block-face direction."direction
defunblock-chunk-boundary-revision
chunkdirection

Return chunk's revision for the boundary facing direction.

check-typechunkblock-chunk
aref
slot-valuechunk'boundary-revisions
defunnote-chunk-boundary-change
chunkxyz
let*
shape
voxel-space-chunk-shape
chunk-domain-space
block-chunk-domainchunk
revisions
slot-valuechunk'boundary-revisions
when
zeropx
incf
arefrevisions0
when
=x
1-
chunk-shape-widthshape
incf
arefrevisions1
when
zeropy
incf
arefrevisions2
when
=y
1-
chunk-shape-heightshape
incf
arefrevisions3
when
zeropz
incf
arefrevisions4
when
=z
1-
chunk-shape-depthshape
incf
arefrevisions5
defun
blockchunkxyz
check-typechunkblock-chunk
setfblock
defun
blockchunkoffset

Set one dense site while retaining chunk and boundary invalidation.

check-typechunkblock-chunk
check-typeoffset
integer0
let
domain
block-chunk-domainchunk
unless
error"Offset ~D is outside chunk ~S."offsetchunk
when
set-block-content-at-offset
block-chunk-contentchunk
offsetblock
incf
slot-valuechunk'revision
multiple-value-bind
xyz

The hook receives the edited site so derived domains such as lighting can react to the cell, not merely the chunk.

let
change-hook
slot-valuechunk'change-hook
whenchange-hook
funcallchange-hookchunkxyz
block
defunmap-chunk-blocks

Describe each site to function as BLOCK and LOCAL-COORDINATE.

This row-shaped convenience protocol is for presentation and irregular local work. Whole-domain algorithms should use with-block-content-storage.

check-typechunkblock-chunk
with-block-content-storage
domainpaletteindices
chunk
do-chunk-domain-sites
offsetlocaldomain

function may retain LOCAL, so pass it an indefinite-extent copy.

funcallfunction
arefpalette
arefindicesoffset
copy-local-coordinatelocal
chunk

A block world is the resident environment, not the complete world description. Its residency revision changes only when chunks enter or leave; its general revision includes residency and content changes; and each chunk has its own content revision.

define-conditionchunk-not-resident
error
world-coordinate:initarg:world-coordinate:readerchunk-not-resident-world-coordinate
chunk-coordinate:initarg:chunk-coordinate:readerchunk-not-resident-chunk-coordinate
:report
lambda
conditionstream
formatstream"No chunk is resident for world coordinate ~S (chunk ~S)."
chunk-not-resident-world-coordinatecondition
chunk-not-resident-chunk-coordinatecondition
defclassblock-world
space:initarg:space:readerblock-world-space
source:initarg:source:initformnil:readerblock-world-source
chunks:initform
make-hash-table:test#'equal
:readerblock-world-chunks

The one vocabulary every resident chunk's content column is closed by.

vocabulary:initarg:vocabulary:initform:readerblock-world-vocabulary
revision:initform0:readerblock-world-revision
residency-revision:initform0:readerblock-world-residency-revision

Derived-domain subscriptions. The cell hook receives (CHUNK X Y Z) in world coordinates after an authored content change; the residency hook receives (X Y Z EVENT) with EVENT :ARRIVED or :DEPARTED in chunk coordinates after residency publication.

cell-change-hook:initformnil:accessorblock-world-cell-change-hook
residency-change-hook:initformnil:accessorblock-world-residency-change-hook
next-chunk-incarnation:initform0
change-transaction-depth:initform0
change-pending-p:initformnil
defunnote-block-world-change
world
if
plusp
slot-valueworld'change-transaction-depth
setf
slot-valueworld'change-pending-p
t
incf
slot-valueworld'revision
defuncall-with-world-change-transaction

Call function and coalesce all world changes into one general revision.

Chunk and residency revisions retain their ordinary precision. The outermost transaction advances world's general revision once if any change occurred, including when function exits non-locally after making a partial change.

check-typeworldblock-world
incf
slot-valueworld'change-transaction-depth
unwind-protect
funcallfunction
decf
slot-valueworld'change-transaction-depth
when
and
zerop
slot-valueworld'change-transaction-depth
slot-valueworld'change-pending-p
setf
slot-valueworld'change-pending-p
nil
incf
slot-valueworld'revision
defunmake-block-world
&key
id
gensym"BLOCK-WORLD-"
chunk-width16
chunk-height16
chunk-depth16
cell-extent1d0
source
make-instance'block-world:sourcesource:space
make-voxel-space:idid:chunk-shape
make-chunk-shape:widthchunk-width:heightchunk-height:depthchunk-depth
:cell-extentcell-extent
defunchunk-key
xyz
check-typexinteger
check-typeyinteger
check-typezinteger
listxyz
defunworld-chunk-at
worldxyz

Return the resident chunk at chunk coordinate X,Y,Z and whether it exists.

check-typeworldblock-world
gethash
block-world-chunksworld
defunworld-chunk-at-coordinate
worldcoordinate

Return the resident chunk at CHUNK-COORDINATE and whether it exists.

check-typecoordinatechunk-coordinate
world-chunk-atworld
chunk-coordinate-xcoordinate
chunk-coordinate-ycoordinate
chunk-coordinate-zcoordinate
defunnext-block-world-chunk-incarnation
world
incf
slot-valueworld'next-chunk-incarnation
defunmake-world-owned-block-chunk
worlddomain&keycontent
make-block-chunkdomain:incarnation:contentcontent:vocabulary
block-world-vocabularyworld
:change-hook
lambda
changed-chunklocal-xlocal-ylocal-z
let
cell-hook
block-world-cell-change-hookworld
whencell-hook
let
origin
chunk-domain-origin
block-chunk-domainchanged-chunk
funcallcell-hookchanged-chunk
+
world-coordinate-xorigin
local-x
+
world-coordinate-yorigin
local-y
+
world-coordinate-zorigin
local-z
defunnote-world-residency-event
worldxyzevent
let
hook
block-world-residency-change-hookworld
whenhook
funcallhookxyzevent
defunensure-world-chunk
worldxyz

Return the resident chunk at X,Y,Z, creating an all-air chunk if absent.

multiple-value-bind
chunkpresent-p
ifpresent-pchunk
let*
domain
make-chunk-domain
block-world-spaceworld
coordinate
new-chunk
setf
gethash
block-world-chunksworld
new-chunk
incf
slot-valueworld'residency-revision
new-chunk
defuninstall-world-chunk-storage
worldxyzcontent

Install transferred block-content storage as a newly resident chunk.

The caller gives world ownership of content and must not mutate it afterward. content is a block-content-column. Installation rebinds that aggregate to the authoritative resident domain and world's vocabulary, translating its indices in place if it was produced under another vocabulary, and publishes it in one single-writer step.

check-typeworldblock-world
check-typecontentblock-content-column
when
nth-value1
error"Chunk (~D ~D ~D) is already resident."xyz
let*
domain
make-chunk-domain
block-world-spaceworld
coordinate
chunk
make-world-owned-block-chunkworlddomain:contentcontent
setf
gethash
block-world-chunksworld
chunk
incf
slot-valueworld'residency-revision
chunk
defunremove-world-chunk
worldxyz

Remove a resident chunk. Return the chunk and whether it was present.

multiple-value-bind
chunkpresent-p
gethash
block-world-chunksworld
whenpresent-p

A removed chunk may outlive its residency in an inspector or cache, but it no longer owns the right to invalidate this world.

setf
slot-valuechunk'change-hook
nil
remhash
block-world-chunksworld
incf
slot-valueworld'residency-revision
valueschunkpresent-p
defunresident-world-chunks
world

Return resident chunks in deterministic chunk-coordinate order.

check-typeworldblock-world
sort
loopforchunkbeingthehash-valuesof
block-world-chunksworld
collectchunk
lambda
leftright
let
a
chunk-domain-coordinate
block-chunk-domainleft
b
chunk-domain-coordinate
block-chunk-domainright
or
<
chunk-coordinate-xa
chunk-coordinate-xb
and
=
chunk-coordinate-xa
chunk-coordinate-xb
or
<
chunk-coordinate-ya
chunk-coordinate-yb
and
=
chunk-coordinate-ya
chunk-coordinate-yb
<
chunk-coordinate-za
chunk-coordinate-zb
defgenericworld-block-at
worldxyz
:documentation

Return one site as BLOCK and :RESIDENT, or NIL and :ABSENT.

This sparse world-coordinate accessor constructs coordinate descriptors and a chunk lookup key. It is appropriate for inspectors, ray hits, collision probes, and sparse interaction. Algorithms over many cells should select a chunk/domain once and use with-block-content-storage instead.

defgeneric
blockworldxyz
:documentation

Set block at one resident world site and return block.

This follows the same sparse coordinate-resolution path as world-block-at. It signals chunk-not-resident rather than materializing absent terrain, and retains chunk revision, boundary revision, and world invalidation semantics.

defunlocate-world-coordinate
worldxyz
let
multiple-value-bind
chunk-coordinatelocal-coordinate
world-coordinate-chunk-and-local
block-world-spaceworld
coordinate
valuescoordinatechunk-coordinatelocal-coordinate
defmethodlocate-chunk-window-site
xyz
multiple-value-bind
chunk-xchunk-ychunk-zlocal-xlocal-ylocal-z
voxel-space-decompose-components
block-world-spaceworld
xyz
multiple-value-bind
chunkpresent-p
world-chunk-atworldchunk-xchunk-ychunk-z
ifpresent-p
valueschunk
chunk-domain-offset-components
block-chunk-domainchunk
local-xlocal-ylocal-z
:available
valuesnilnil:unavailable
defmethodworld-block-at
xyz
multiple-value-bind
chunkoffsetavailability
ecaseavailability
:available
values
block-content-at-offset
block-chunk-contentchunk
offset
:resident
:unavailable
valuesnil:absent
defmethod
blockxyz
multiple-value-bind
world-coordinatechunk-coordinatelocal-coordinate
multiple-value-bind
chunkpresent-p
world-chunk-atworld
chunk-coordinate-xchunk-coordinate
chunk-coordinate-ychunk-coordinate
chunk-coordinate-zchunk-coordinate
unlesspresent-p
error'chunk-not-resident:world-coordinateworld-coordinate:chunk-coordinatechunk-coordinate
setf
chunk-block-atchunk
local-coordinate-xlocal-coordinate
local-coordinate-ylocal-coordinate
local-coordinate-zlocal-coordinate
block

Sparse edits are an overlay on a materialized world, not another dense chunk field. NIL is a meaningful stored value (an explicitly removed block), so hash-table presence distinguishes it from no edit.

defclassblock-edit-overlay
entries:initform
make-hash-table:test#'equal
:readerblock-edit-overlay-entries
defunblock-edit-overlay-count
overlay
hash-table-count
block-edit-overlay-entriesoverlay
defunrecord-block-edit
overlayblockxyz

Record block as the explicit value for world site X,Y,Z.

check-typeoverlayblock-edit-overlay
let
setf
gethash
list
world-coordinate-xcoordinate
world-coordinate-ycoordinate
world-coordinate-zcoordinate
block-edit-overlay-entriesoverlay
block
block
defunblock-edit-at
overlayxyz

Return the edited value at X,Y,Z and whether an edit is present.

check-typeoverlayblock-edit-overlay
let
gethash
list
world-coordinate-xcoordinate
world-coordinate-ycoordinate
world-coordinate-zcoordinate
block-edit-overlay-entriesoverlay
defunsame-chunk-coordinate-p
leftright
and
=
chunk-coordinate-xleft
chunk-coordinate-xright
=
chunk-coordinate-yleft
chunk-coordinate-yright
=
chunk-coordinate-zleft
chunk-coordinate-zright
defunapply-block-edits-to-chunk
overlayworldchunk

Apply every edit in overlay addressed to resident chunk.

check-typeoverlayblock-edit-overlay
check-typeworldblock-world
check-typechunkblock-chunk
let
target
chunk-domain-coordinate
block-chunk-domainchunk
with-world-change-transaction
world
maphash
lambda
keyblock
destructuring-bind
xyz
key
multiple-value-bind
coordinatelocal
declare
ignorelocal
when
same-chunk-coordinate-pcoordinatetarget
setfblock
block-edit-overlay-entriesoverlay
chunk

Ray traversal is expressed in continuous lattice coordinates: integer planes are cell boundaries, independently of the physical cell extent. The traversal stops at absent terrain rather than silently seeing air.

luv.arithmetic.records:define-quantity-struct
block-ray-hit
:constructor%make-block-ray-hit
coordinateadjacent-coordinateblockdistance
coordinatenil:typeworld-coordinate:read-onlyt
adjacent-coordinatenil:type
ornullworld-coordinate
:read-onlyt
blocknil:read-onlyt
distance0d0:typedouble-float:read-onlyt:quantity
:quantity:ray-distance:unit:cell
defunraycast-block-world
worldorigindirectionoccupied-p&keymax-distance

Trace a ray through world's resident lattice.

Return a BLOCK-RAY-HIT and :HIT, NIL and :ABSENT when traversal reaches a non-resident chunk, or NIL and :MISS. origin and direction are vec3 values in continuous cell coordinates. The caller owns and must supply the maximum ray distance appropriate to its interaction.

check-typeworldblock-world
check-typeoriginvec3
check-typedirectionvec3
check-typemax-distance
real0
unless
functionpoccupied-p
error"OCCUPIED-P must be a function."
let*
origin-x
coerce
vec3-xorigin
'double-float
origin-y
coerce
vec3-yorigin
'double-float
origin-z
coerce
vec3-zorigin
'double-float
raw-x
coerce
vec3-xdirection
'double-float
raw-y
coerce
vec3-ydirection
'double-float
raw-z
coerce
vec3-zdirection
'double-float
magnitude
sqrt
+
*raw-xraw-x
*raw-yraw-y
*raw-zraw-z
unless
pluspmagnitude
error"A block-world ray direction must be non-zero."
let*
direction-x
/raw-xmagnitude
direction-y
/raw-ymagnitude
direction-z
/raw-zmagnitude
cell-x
floororigin-x
cell-y
floororigin-y
cell-z
floororigin-z
step-x
cond
pluspdirection-x
1
minuspdirection-x
-1
t0
step-y
cond
pluspdirection-y
1
minuspdirection-y
-1
t0
step-z
cond
pluspdirection-z
1
minuspdirection-z
-1
t0
infinitymost-positive-double-float
delta-x
if
zeropstep-x
infinity
abs
/direction-x
delta-y
if
zeropstep-y
infinity
abs
/direction-y
delta-z
if
zeropstep-z
infinity
abs
/direction-z
boundary-x
if
pluspstep-x
1+cell-x
cell-x
boundary-y
if
pluspstep-y
1+cell-y
cell-y
boundary-z
if
pluspstep-z
1+cell-z
cell-z
next-x
if
zeropstep-x
infinity
/
-boundary-xorigin-x
direction-x
next-y
if
zeropstep-y
infinity
/
-boundary-yorigin-y
direction-y
next-z
if
zeropstep-z
infinity
/
-boundary-zorigin-z
direction-z
adjacentnil
loop
multiple-value-bind
blockstatus
world-block-atworldcell-xcell-ycell-z
when
eqstatus:absent
return
valuesnil:absent
when
funcalloccupied-pblock
return
values
%make-block-ray-hit
make-world-coordinatecell-xcell-ycell-z
adjacentblock
coercedistance'double-float
:hit
let
next-distance
minnext-xnext-ynext-z
when
>next-distancemax-distance
return
valuesnil:miss
setfadjacent
make-world-coordinatecell-xcell-ycell-z
distancenext-distance
cond
and
<=next-xnext-y
<=next-xnext-z
incfcell-xstep-x
incfnext-xdelta-x
and
<=next-ynext-x
<=next-ynext-z
incfcell-ystep-y
incfnext-ydelta-y
t
incfcell-zstep-z
incfnext-zdelta-z