└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # Minecraft block lighting 2 | ## Why do we care about light on the server? 3 | On the server side, light is used for a variety of vanilla logic, including (but not limited to): 4 | - Grass growth (and death) 5 | - Crop growth 6 | - Sapling growth 7 | - Ice melting 8 | - Bamboo growth 9 | - Mob spawning (for example, undead mobs won't usually spawn in bright light) 10 | 11 | ## So why are we calculating light for every single chunk? 12 | No idea. In theory, we don't need to calculate lighting for anything other than chunks currently in ticking areas (usually a few chunks' radius around the player where crops are expected to grow and so on). 13 | 14 | ## Algorithm 15 | We propose a 3-pass algorithm for relighting chunks, starting from zero light. 16 | 17 | ### Special cases 18 | If an arbitrary chunk is replaced, its light must be invalidated, and also the light of the surrounding **8 chunks**. This is because a chunk's lighting may have affected any of these adjacent chunks (due to propagation). 19 | 20 | ### Pass 0: Discover light nodes 21 | #### Sky light 22 | For sky light, this involves calculating the "height map" of the chunk. For each X/Z column in the chunk, the heightmap contains the Y coordinate of the **highest block that doesn't affect light, NOT the highest block**. 23 | 24 | Blocks pointed to by the heightmap should be treated as light sources for sky light propagation. 25 | In addition, account for the difference between the current column and the highest immediately adjacent heightmap, to account for cases where sideways propagation is needed. 26 | 27 | | Block | Ignored by heightmap | Reason | 28 | |:------|:--------------------:|:-------| 29 | | Glass | Yes | Fully transparent | 30 | | Air | Yes | Fully transparent | 31 | | Leaves | No | Diffuses sky light (doesn't reduce light propagation, but triggers heightmap) | 32 | | Cobweb | No | Diffuses sky light (doesn't reduce light propagation, but triggers heightmap) | 33 | | Water | No | Light is reduced by 3 levels when propagating through (instead of usual 1) | 34 | | Stone | No | Fully opaque | 35 | 36 | #### Block light 37 | For block light, you just need to scan the whole chunk and look for blocks with a non-zero light emission. These blocks are your source nodes. 38 | 39 | **Tip:** You can optimise these kinds of scans using the block palette. If a subchunk's block palette doesn't contain any light-emitting blockstates, you can avoid scanning the entire 4096 blocks of that subchunk. 40 | 41 | ### Pass 1: Propagate light inside the bounds of a single chunk column 42 | This pass **must not** influence any other chunks except the source chunk. It's possible, probably practical, to do pass 0 and 1 directly in series. 43 | 44 | #### Requirements 45 | - Pass 0 must have been completed. 46 | 47 | ### Pass 2: Propagate light across chunk borders 48 | For this pass, we take square groups of 4 chunks, and propagate light across their shared borders. 49 | No chunk is special; all 4 chunks in each group are treated the same way. 50 | 51 | Each chunk belongs to 4 groups of 4 chunks: 52 | 53 | - one where it is the top-left chunk 54 | - one where it is the top-right chunk 55 | - one where it is the bottom-left chunk 56 | - one where it is the bottom-right chunk 57 | 58 | Once a chunk has been involved in a pass 2 calculation in all of these positions, it is then fully light-populated. 59 | 60 | #### Why not groups of 9? 61 | Groups of 4, while harder to explain, are significantly more parallel-friendly, easier to code, and in the case of PocketMine-MP, require significantly fewer chunk copies (4 instead of 9), due to the fact that a pass2 using groups of 4 only needs to lock a chunk 4 times. 62 | 63 | #### Example 64 | - A torch is placed in chunk (0,0) at x=14,z=14 65 | - A tunnel crosses into chunk (0,1), turns right, crosses into chunk (1,1), then upwards, and crosses into chunk (1,0). 66 | - The light from the torch must be propagated to all three chunks. 67 | 68 | #### Requirements for each part of the pass 69 | - All chunks involved must be available. 70 | - All chunks involved must have had pass 1 completed. 71 | 72 | ## Notes 73 | - Block and sky light are independent and can be calculated in parallel. 74 | - If pass 1 did nothing for any of the 4 adjacent chunks, pass 2 can be skipped for the current chunk, since it guarantees that none of the adjacent chunks have any border light that can be received by the current chunk. 75 | - It's possible to record whether light reached chunk borders during pass 1, to allow adjacent chunks to quickly decide whether they want to do pass 2 with that chunk or not. 76 | - Pass 0 and 1 can be embarassingly parallel, since they only require a single chunk to execute. 77 | --------------------------------------------------------------------------------