API reference / @jsprismarine/lighting / LightEngine
Class: LightEngine
Defined in: LightEngine.ts:78
The server's internal light model: a block light layer that floods out of emitters and a sky light layer that falls from the open sky, both kept current as blocks change and both advanced in bounded steps so a tick cannot stall.
These levels never reach a player. The Bedrock protocol has no light packet and neither LevelChunkPacket nor SubChunkPacket carries light arrays, so the connected client computes and renders light itself from the block palette it already has. The server keeps its own copy for the three rules that read it: mob spawning, crop growth, and daylight detectors. Where the two models disagree, the player sees the client's answer and the server acts on this one.
Java's directional opacity, which lets a slab, a stair or a piston pass light in some directions and not others, is deliberately not implemented. Bedrock's block data expresses one minecraft:light_dampening scalar per state with no direction, the Bedrock client applies that scalar, and a server that modeled Java's per-face rule would compute light the client contradicts for every slab and stair in the world.
The engine reads the world through an injected BlockLightView and holds no reference to chunk, block or world classes. The server has to announce a chunk with LightEngine.onChunkLoaded before the engine stores light in it.
Constructors
Constructor
new LightEngine(
view):LightEngine
Defined in: LightEngine.ts:84
Parameters
view
Returns
LightEngine
Accessors
pending
Get Signature
get pending():
LightQueueDepth
Defined in: LightEngine.ts:92
The work the engine still has to do. LightEngine.flush returns the same numbers.
Returns
Methods
flush()
flush(
budget?):LightFlushResult
Defined in: LightEngine.ts:228
Advances the light by at most budget queue nodes and reports what is left, so a tick can spend a fixed amount of time on light and decide from the result whether to come back.
Every decrease node runs before any increase node, which is what makes a removed light source darken its neighborhood before the surviving sources fill it in again. Stopping mid-flush leaves the light part way through that sequence: levels are readable but not yet correct, and they become correct once queued reaches 0.
Parameters
budget?
number = Number.POSITIVE_INFINITY
The most nodes to process. Unbounded when omitted.
Returns
The work done and the work left.
Throws
When the budget is negative or not a number.
getBlockLight()
getBlockLight(
x,y,z):number
Defined in: LightEngine.ts:104
The block light at a world position, 0 to 15.
Parameters
x
number
World x.
y
number
World y.
z
number
World z.
Returns
number
The level, or 0 for a position in a column the engine has not been told about. Check that the chunk is loaded before reading a 0 as darkness.
getSkyLight()
getSkyLight(
x,y,z):number
Defined in: LightEngine.ts:119
The sky light at a world position, 0 to 15, before the time of day and the weather scale it. The daylight cycle multiplies this number; it does not change it.
Parameters
x
number
World x.
y
number
World y.
z
number
World z.
Returns
number
The level, 0 in a dimension with no sky and 0 for a position in a column the engine has not been told about.
hasChunk()
hasChunk(
chunkX,chunkZ):boolean
Defined in: LightEngine.ts:87
Whether this engine currently holds lighting for a chunk column.
Parameters
chunkX
number
chunkZ
number
Returns
boolean
onBlockChanged()
onBlockChanged(
position,oldState,newState):void
Defined in: LightEngine.ts:198
Queues the smallest piece of work that makes both layers correct again after one block changed. Nothing is computed here; LightEngine.flush does the computing.
The sky layer is patched rather than rebuilt: the column's heightmap entry moves only when the change was at or above the highest light-blocking block, and the only scan is the walk down the column that finds the next blocker after the top one is broken.
A change that alters neither emission nor dampening queues nothing, so a server can call this for every block change without filtering first.
Parameters
position
Where the block changed.
oldState
The light properties of the block that was there.
newState
The light properties of the block that is there now.
Returns
void
onChunkLoaded()
onChunkLoaded(
chunkX,chunkZ):void
Defined in: LightEngine.ts:136
Takes a chunk into the light model and computes its light from scratch: it builds the sky heightmap, makes every emitter in the column a source, and re-seeds across the border of each loaded neighbor so light that stopped at the chunk's edge while it was absent flows in.
Calling this for a chunk the engine already holds discards that chunk's stored light and computes it again, which is how a caller forces a full recompute.
Parameters
chunkX
number
The chunk x.
chunkZ
number
The chunk z.
Returns
void
onChunkUnloaded()
onChunkUnloaded(
chunkX,chunkZ):void
Defined in: LightEngine.ts:180
Drops a chunk's stored light. Light in the neighbors that came from this chunk is left as it is; it is recomputed when the chunk comes back, because LightEngine.onChunkLoaded re-seeds across the border.
Parameters
chunkX
number
The chunk x.
chunkZ
number
The chunk z.
Returns
void