Lighting System
Lighting System
Section titled “Lighting System”The lighting system calculates and propagates light through the world using a flood-fill algorithm with support for colored block light and skylight.
Package Location
Section titled “Package Location”com.hypixel.hytale.server.core.universe.world.lighting
Overview
Section titled “Overview”Hytale uses a 4-channel lighting system:
- Red block light (0-15)
- Green block light (0-15)
- Blue block light (0-15)
- Skylight (0-15)
Light is calculated per chunk section (32x32x32 blocks) using flood-fill propagation.
Light Channels
Section titled “Light Channels”| Channel | Bits | Range | Source |
|---|---|---|---|
| Red | 0-3 | 0-15 | Block light sources |
| Green | 4-7 | 0-15 | Block light sources |
| Blue | 8-11 | 0-15 | Block light sources |
| Skylight | 12-15 | 0-15 | Sky exposure |
Combined format: 16-bit short value
Core Classes
Section titled “Core Classes”ChunkLightingManager
Section titled “ChunkLightingManager”Main manager running on a dedicated daemon thread per world:
package com.hypixel.hytale.server.core.universe.world.lighting;
public class ChunkLightingManager { // Queue chunk for light recalculation public void addToQueue(Vector3i chunkPosition);
// Initialize lighting for newly loaded chunk public void init(WorldChunk chunk);
// Swap calculation algorithm public void setLightCalculation(LightCalculation calculation);
// Mark block area for recalculation public void invalidateLightAtBlock( Vector3i blockPosition, WorldChunk chunk );
// Mark entire chunk for recalculation public void invalidateLightInChunk(WorldChunk chunk);
// Mark specific section (32x32x32) public void invalidateLightInChunkSection( WorldChunk chunk, int sectionIndex );
// Full world invalidation public void invalidateLoadedChunks();}LightCalculation
Section titled “LightCalculation”Interface for pluggable light calculation algorithms:
package com.hypixel.hytale.server.core.universe.world.lighting;
public interface LightCalculation { // Initialize lighting for loaded chunk void init(WorldChunk chunk);
// Process queued chunk position CalculationResult calculateLight(Vector3i chunkPosition);
// Mark block for update void invalidateLightAtBlock( Vector3i blockPosition, WorldChunk chunk );
// Mark sections for update void invalidateLightInChunkSections( WorldChunk chunk, int... sectionIndices );}
// Calculation resultpublic enum CalculationResult { NOT_LOADED, // Chunk or neighbors not in memory DONE, // Processing complete INVALIDATED, // Recalculation requested mid-process WAITING_FOR_NEIGHBOUR // Neighbor section not ready}FloodLightCalculation
Section titled “FloodLightCalculation”Default implementation using flood-fill algorithm:
package com.hypixel.hytale.server.core.universe.world.lighting;
public class FloodLightCalculation implements LightCalculation { // Two-phase calculation: // 1. Local light (block light sources) // 2. Global light (skylight propagation)}Propagation Rules:
| Propagation Type | Light Reduction |
|---|---|
| Direct neighbor (6 faces) | -1 |
| Edge connection (12 edges) | -2 |
| Corner connection (8 corners) | -3 |
| Through semitransparent | Additional -1 |
| Through solid | Blocked |
FullBrightLightCalculation
Section titled “FullBrightLightCalculation”Debug wrapper that sets all skylight to maximum:
package com.hypixel.hytale.server.core.universe.world.lighting;
public class FullBrightLightCalculation implements LightCalculation { // Wraps delegate calculation // After completion, sets all skylight to 15}Light Data Storage
Section titled “Light Data Storage”ChunkLightData
Section titled “ChunkLightData”Immutable light storage for chunk sections:
package com.hypixel.hytale.server.core.universe.world.chunk.section;
public class ChunkLightData { // Constants public static final int TREE_SIZE = 8; // Octtree subdivision public static final int MAX_VALUE = 15; // Max light per channel public static final int CHANNEL_COUNT = 4; // RGBA + sky
// Get individual channel values (0-15) public int getRedBlockLight(int index); public int getGreenBlockLight(int index); public int getBlueBlockLight(int index); public int getSkyLight(int index);
// Get max of RGB channels public int getBlockLightIntensity(int index);
// Get specific channel (0-3) public int getLight(int index, int channel);
// Get raw 16-bit combined value public short getLightRaw(int index);
// Static utilities public static short combineLightValues( int red, int green, int blue, int sky );
public static int getLightValue(short value, int channel);}ChunkLightDataBuilder
Section titled “ChunkLightDataBuilder”Mutable builder for light calculation:
public class ChunkLightDataBuilder { // Set individual channels public void setLight(int index, int channel, int value); public void setSkyLight(int index, int value);
// Set raw combined value public void setLightRaw(int index, short value);
// Build immutable result public ChunkLightData build();}Block Light Sources
Section titled “Block Light Sources”Blocks define their light emission in their block type definition:
// BlockType light propertiespublic class BlockType { // Light emission (ColorLight format) public ColorLight getBlockLight();
// Opacity for light propagation public BlockOpacity getOpacity();}
// Opacity typespublic enum BlockOpacity { SOLID, // Blocks all light SEMITRANSPARENT, // Reduces light by additional 1 CUTOUT, // Reduces light by additional 1 TRANSPARENT // Full light pass-through}ColorLight
Section titled “ColorLight”Light color and radius definition:
package com.hypixel.hytale.protocol;
public class ColorLight { public int radius; // Light reach (1 byte) public int red; // Red intensity 0-15 (1 byte) public int green; // Green intensity 0-15 (1 byte) public int blue; // Blue intensity 0-15 (1 byte)
public ColorLight(int radius, int red, int green, int blue);}Usage Examples
Section titled “Usage Examples”Invalidating Light at Block
Section titled “Invalidating Light at Block”import com.hypixel.hytale.server.core.universe.world.lighting.ChunkLightingManager;import com.hypixel.hytale.math.vector.Vector3i;
// Get lighting manager from worldWorld world = Universe.get().getWorld("default");ChunkLightingManager lightingManager = world.getLightingManager();
// Mark block for recalculation (e.g., after placing light source)Vector3i blockPosition = new Vector3i(100, 64, 200);WorldChunk chunk = world.getChunk(blockPosition);
lightingManager.invalidateLightAtBlock(blockPosition, chunk);Reading Light Values
Section titled “Reading Light Values”import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkLightData;
// Get light data from chunk sectionWorldChunk chunk = world.getChunk(position);int sectionIndex = position.y / 32;ChunkLightData lightData = chunk.getLightData(sectionIndex);
// Calculate local index within sectionint localX = position.x & 31;int localY = position.y & 31;int localZ = position.z & 31;int index = localX + (localY * 32) + (localZ * 32 * 32);
// Read individual channelsint red = lightData.getRedBlockLight(index);int green = lightData.getGreenBlockLight(index);int blue = lightData.getBlueBlockLight(index);int sky = lightData.getSkyLight(index);
// Or get combined block light intensityint blockLight = lightData.getBlockLightIntensity(index);
// Get raw 16-bit valueshort rawLight = lightData.getLightRaw(index);Switching Light Calculation Mode
Section titled “Switching Light Calculation Mode”import com.hypixel.hytale.server.core.universe.world.lighting.*;
// Switch to full bright mode (for testing)ChunkLightingManager manager = world.getLightingManager();LightCalculation current = manager.getLightCalculation();manager.setLightCalculation(new FullBrightLightCalculation(current));
// Invalidate all chunks to applymanager.invalidateLoadedChunks();Light Propagation Algorithm
Section titled “Light Propagation Algorithm”Local Light (Block Light)
Section titled “Local Light (Block Light)”- Find all light-emitting blocks in section
- Add their positions to propagation queue
- For each position in queue:
- Check 6 direct neighbors
- If neighbor has lower light, update and queue
- Apply opacity reduction
- Continue until queue is empty
Global Light (Skylight)
Section titled “Global Light (Skylight)”- Start from section borders
- Three propagation phases:
- Sides: Direct neighbors (-1 reduction)
- Edges: Edge connections (-2 reduction)
- Corners: Corner connections (-3 reduction)
- Check neighbor chunk sections if needed
- Wait for neighbors if not yet calculated
Propagation from center block:
Corner (-3) / Edge (-2) /Side (-1) ─ CENTER ─ Side (-1) \ Edge (-2) \ Corner (-3)Commands
Section titled “Commands”Built-in lighting commands:
| Command | Description |
|---|---|
/lighting calculation flood | Switch to flood algorithm |
/lighting calculation fullbright | Enable full brightness |
/lighting invalidate | Recalculate all loaded chunks |
/lighting invalidate --one | Recalculate player’s chunk section |
Performance Considerations
Section titled “Performance Considerations”- Async Processing: Light calculation runs on dedicated thread
- Queue-based: Changes are queued and processed in order
- Section Granularity: Updates are per 32x32x32 section
- Neighbor Dependencies: Sections wait for neighbors before completing
- Octtree Storage: Compact representation reduces memory
Related
Section titled “Related”- Dynamic Lighting - Entity light sources
- World System - Chunk management
- Block System - Block light properties