luv

Workshop wiki

world.lisp

luvcraft/birthday/world.lisp

system luvcraft/birthday · 32 definitions · on GitHub

The birthday meadow: a gentle world for a small person to run around in.

A birthday-world-source is a little-world-source with kinder geography: low, long-period grassy hills, every surface grass rather than a biome rule, and one flat party clearing around the origin, smoothstep-blended into the hills so the gazebo gets a natural lawn. Flower blocks freckle the grass from the same coordinate hashes the little world uses -- never randomness -- densest in a wreath around the clearing. Trees are sparser than stock and never root inside the clearing ring.

Edits, residency, and lighting semantics are inherited from the little world. Two inherited paths would quietly hand a subclass stock terrain, so both are specialized here: the off-thread chunk load (the stock request's perform method rebuilds a little-world-source by name, and its landmark capture calls the stock generator) gets its own request class, and persistence gets its own :BIRTHDAY-MEADOW save kind so a world saved under worlds/alex-birthday.sexp comes back as the same meadow plus edits.

in-package#:luvcraft.birthday

The meadow's shape, gathered as knobs so the party can be re-landscaped live. All readings stay pure functions of the source's seed and these globals, so any chunk regenerates bit-identically on any thread.

defparameter*clearing-radius*14.0d0"Inside this distance from the origin the lawn is perfectly flat."
defparameter*clearing-blend-radius*26.0d0"By this distance the lawn has fully blended into the hills."
defparameter*clearing-height*6.0d0"The flat party lawn's surface height."
defparameter*meadow-base-height*5.5d0"The mean surface height of the rolling meadow."
defparameter*meadow-hill-period*96"The long period of the meadow's one broad hill octave."
defparameter*meadow-hill-amplitude*2.0d0"How far the broad hills swell above and below the base height."
defparameter*meadow-swell-period*40

The period of the faint secondary swell that keeps hills from reading as a single sine.

defparameter*meadow-swell-amplitude*0.6d0"The faint secondary swell's amplitude."
defparameter*clearing-flower-density*0.05d0

Flower chance per grass column on the party lawn itself: a light freckle that leaves the gazebo's ground open.

defparameter*ring-flower-density*0.16d0"Flower chance in the wreath between the lawn and the hills."
defparameter*far-flower-density*0.035d0"Flower chance far out in the hills."
defparameter*flower-fade-radius*60.0d0"Distance by which the wreath's density has faded to the far density."
defparameter*tree-exclusion-radius*26.0d0

No tree roots closer to the origin than this. It matches the blend ring, so the whole approach to the party stays open, not just the lawn.

defunbirthday-meadow-smoothstep
edge0edge1value

0 at or below edge0, 1 at or above edge1, smooth in between.

let
amount
max0.0d0
min1.0d0
/
-valueedge0
-edge1edge0
*amountamount
-3.0d0
*2.0d0amount
defunbirthday-flower-block-p
sourcexz

Whether the grass at X,Z has burst into flowers.

Deterministic like every other terrain reading: a coordinate hash against a density that peaks in the wreath just outside the party clearing and fades with distance, leaving the far hills a sprinkle and the lawn itself lightly freckled.

defunbirthday-surface-block
sourcexz
ifluvcraft::*flowers-block*luvcraft::*grass-block*
defunmaterialize-birthday-meadow-chunk
sourceworldchunk-xchunk-z

Materialize one meadow terrain chunk at vertical layer zero.

The column fill mirrors the little world's; only the readings differ: meadow heights, and every surface grass or flowers.

luvcraft::with-world-change-transaction
world
let*
chunk
luvcraft::ensure-world-chunkworldchunk-x0chunk-z
shape
luvcraft::voxel-space-chunk-shape
luvcraft::block-world-spaceworld
width
luvcraft::chunk-shape-widthshape
height
luvcraft::chunk-shape-heightshape
depth
luvcraft::chunk-shape-depthshape
origin
luvcraft::chunk-domain-origin
luvcraft::block-chunk-domainchunk
dotimes
local-zdepth
dotimes
local-xwidth
let*
x
+
luvcraft::world-coordinate-xorigin
local-x
z
+
luvcraft::world-coordinate-zorigin
local-z
surface-block
dotimes
y
1+surface
setf
cond
=ysurface
surface-block
or
zeropy
<y
-surface2
luvcraft::*stone-block*
tluvcraft::*dirt-block*
chunk
defmethodluvcraft:materialize-block-world-chunk
chunk-xchunk-ychunk-z
unless
zeropchunk-y
error"The birthday meadow materializes only chunk layer zero."
materialize-birthday-meadow-chunksourceworldchunk-xchunk-z
defunmap-birthday-tree-blocks
sourcewidthheightdepthowner-xowner-zemit

Call emit with BLOCK X Y Z for the tree rooted in chunk owner-x,owner-z.

At most one tree per chunk, in about a third of them, and never inside the exclusion ring around the party. The shape is the little world's tree; the meadow's kindness is in where and how often it grows. The placement margin keeps trunk and canopy inside the owner chunk, so the direct populate path and the streaming landmark capture agree exactly.

let*
origin-x
*owner-xwidth
origin-z
*owner-zdepth
hash
luvcraft::little-world-hashsourceowner-xowner-z
tree-x
+origin-x3
mod
ashhash-3
tree-z
+origin-z3
mod
ashhash-11
-depth6
surface
trunk-height
+3
mod
ashhash-23
2
crown
+surfacetrunk-height
when
loopforyfrom
1+surface
tocrowndo
funcallemitluvcraft::*wood-block*tree-xytree-z
loopforxfrom
-tree-x2
to
+tree-x2
do
loopforzfrom
-tree-z2
to
+tree-z2
when
<=
+
abs
-xtree-x
abs
-ztree-z
3
do
funcallemitluvcraft::*leaf-block*xcrownz
loopforxfrom
1-tree-x
to
1+tree-x
do
loopforzfrom
1-tree-z
to
1+tree-z
do
funcallemitluvcraft::*leaf-block*x
1+crown
z
funcallemitluvcraft::*leaf-block*tree-x
+crown2
tree-z
defunpopulate-birthday-meadow-chunk
sourceworldchunk-xchunk-z

Plant this chunk's tree, if it has one, into resident terrain.

luvcraft::with-world-change-transaction
world
let*
shape
luvcraft::voxel-space-chunk-shape
luvcraft::block-world-spaceworld
width
luvcraft::chunk-shape-widthshape
height
luvcraft::chunk-shape-heightshape
depth
luvcraft::chunk-shape-depthshape
map-birthday-tree-blockssourcewidthheightdepthchunk-xchunk-z
lambda
blockxyz
setfblock
defmethodluvcraft:populate-block-world-chunk
chunk-xchunk-ychunk-z
unless
zeropchunk-y
error"The birthday meadow populates only chunk layer zero."
populate-birthday-meadow-chunksourceworldchunk-xchunk-z

Streaming. The inherited make-block-chunk-load-request would capture stock landmarks, and its request's perform method rebuilds a stock source in the worker, so the meadow carries its own request class.

defunbirthday-landmarks-for-chunk
sourceworldkey

Capture the meadow landmarks whose owned sites lie inside chunk key.

destructuring-bind
chunk-xchunk-ychunk-z
key
declare
ignorechunk-y
let*
shape
luvcraft::voxel-space-chunk-shape
luvcraft::block-world-spaceworld
width
luvcraft::chunk-shape-widthshape
height
luvcraft::chunk-shape-heightshape
depth
luvcraft::chunk-shape-depthshape
minimum-x
*chunk-xwidth
minimum-z
*chunk-zdepth
landmarksnil
map-birthday-tree-blockssourcewidthheightdepthchunk-xchunk-z
lambda
blockxyz
when
and
<=minimum-xx
<x
+minimum-xwidth
<=minimum-zz
<z
+minimum-zdepth
<=0y
push
listblockxyz
landmarks
nreverselandmarks
defclassbirthday-world-load-request
:documentation

A chunk load whose worker rebuilds a birthday-world-source, so off-thread terrain matches the meadow rather than the stock hills.

defmethodluvcraft:make-block-chunk-load-request
worldkeydemand-tokenpriority
let*
shape
luvcraft::voxel-space-chunk-shape
luvcraft::block-world-spaceworld
width
luvcraft::chunk-shape-widthshape
height
luvcraft::chunk-shape-heightshape
depth
luvcraft::chunk-shape-depthshape
captured-editsnil
maphash
lambda
coordinateblock
destructuring-bind
xyz
coordinate
when
and
=
firstkey
=
floorzdepth
thirdkey
push
listblockxyz
captured-edits
luvcraft::block-edit-overlay-entries
luvcraft:little-world-source-editssource
make-instance'birthday-world-load-request:key
list:loadkey
:prioritypriority:seed
luvcraft:little-world-source-seedsource
:demand-tokendemand-token:widthwidth:heightheight:depthdepth:landmarks:editscaptured-edits
luv:zdefmethod
luvcraft::perform-production-request:zone:production/load-chunk
"Generate one isolated meadow chunk and transfer its content columns."
destructuring-bind
chunk-xchunk-ychunk-z
second
luvcraft::production-request-keyrequest
let*
source
make-instance'birthday-world-source:seed
luvcraft::little-world-load-request-seedrequest
world
luvcraft::make-block-world:chunk-width
luvcraft::little-world-load-request-widthrequest
:chunk-height
luvcraft::little-world-load-request-heightrequest
:chunk-depth
luvcraft::little-world-load-request-depthrequest
:sourcesource
luvcraft:materialize-block-world-chunksourceworldchunk-xchunk-ychunk-z
dolist
landmark
luvcraft::little-world-load-request-landmarksrequest
destructuring-bind
blockxyz
landmark
setfblock
dolist
edit
luvcraft::little-world-load-request-editsrequest
destructuring-bind
blockxyz
edit
setfblock
let
chunk
luvcraft::world-chunk-atworldchunk-xchunk-ychunk-z
make-instance'luvcraft:block-chunk-load-payload:key
listchunk-xchunk-ychunk-z
:content
luvcraft::block-chunk-contentchunk

Persistence. Without these two methods a saved meadow would round-trip through the inherited :LITTLE-WORLD kind and wake up with stock hills.

defmethodluvcraft:world-source-save-description
list:birthday-meadow:source-version+birthday-world-source-version+:seed
luvcraft:little-world-source-seedsource
:edits
luvcraft::block-edit-overlay-save-descriptions
luvcraft:little-world-source-editssource
defmethodluvcraft:restore-world-source-save-description
kind
eql:birthday-meadow
description
let
version
luvcraft::description-valuedescription:source-version"birthday-meadow source"
seed
luvcraft::description-valuedescription:seed"birthday-meadow source"
edits
luvcraft::description-valuedescription:edits"birthday-meadow source"
unless
luvcraft::invalid-luvcraft-save"Birthday-meadow source version ~S is unsupported; expected ~D."version+birthday-world-source-version+
unless
integerpseed
luvcraft::invalid-luvcraft-save"A birthday-meadow seed must be an integer, not ~S."seed
defunmake-birthday-world
&key
seed121
chunk-height32

Make the birthday meadow with resident chunks around the party lawn.

chunk-height defaults to 32 so there is sky room for balloons and fireworks. chunk-radius NIL leaves the resident set empty for streaming to fill, the way make-empty-little-block-world does.

check-typechunk-height
integer8
let*
source
make-instance'birthday-world-source:seedseed
world
luvcraft::make-block-world:id
list:birthday-meadowseed
:chunk-heightchunk-height:sourcesource
world