Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Returns pair of min and max height values for skylight update, or null for no update.
- *
- * Getting light Y update bounds when generating cubes isn't as trivial as it may seem to be.
- *
- * If there was some free space below that cube - it may need a skylight update.
- * If there are only fully opaque blocks below (opacity >= 15) - nothing below was updated.
- *
- * So in this case here is what happens (2d example):
- *
- * ===
- * ### - block
- * ===
- * ...
- * ... - air
- * ...
- * ;;;
- * ;;; - dark air
- * ;;;
- *
- * x-1 x x+1
- * ...===...
- * ...###...
- * ...===...
- * ...;;;...
- * ...;;;...
- * ...;;;...
- * ===;;;...
- * ###;;;...
- * ===;;;...
- * =========
- * #########
- * =========
- *
- * In this case light should spread from lit areas from x-1 and x+1 to x
- * and from above top block at x if it's semi-transparent.
- * The minimum Y that light can directly spread to is at [min(heightAt(x-1), heightAt(x+1)) + 1]
- * And the maximum Y that light can directly spread to is [heightAt(x) - 1].
- * But it can also spread from above, so heightAt(x) also needs update.
- * (assuming heightAt returns height of the top opaque block).
- * When all surrounding heights are higher, light can't spread here, so nothing happens.
- *
- * We don't need to care about cases when light spreads to current block indirectly,
- * It needs to spread to some other block directly for that to happen, and world.checkLightFor()
- * recalculates full light spread.
- *
- * Note that world.checkLightFor() doesn't cause light to spread to/from (x, y, z) if light value
- * in this block is already correct. It only updates if light value isn't equal to raw light value
- * which is max of light at (x, y, z), and [light values from surrounding blocks - 1].
- *
- * In this state all non-lit blocks that may need update should have light values 0,
- * so we need to care only about blocks light can spread to directly from surrounding blocks.
- */
- private Pair<Integer, Integer> getMinMaxLightUpdateY(ICubeCache cache, Cube cube, int blockX, int blockZ) {
- //getHeightmapValue(x, y, z) = heightOfTopBlock+1
- int heightMax = getHeightmapValue(cache, blockX, blockZ) - 1;//==Y of the top block
- int cubeY = cube.getY();
- //if the top block is below current cube - this cube couldn't change anything
- //because there are no opaque blocks
- if (blockToCube(heightMax) < cubeY) {
- return null;
- }
- int heightmapZpos = getHeightmapValue(cache, blockX, blockZ + 1);
- int heightmapZneg = getHeightmapValue(cache, blockX, blockZ - 1);
- int heightmapXpos = getHeightmapValue(cache, blockX + 1, blockZ);
- int heightmapXneg = getHeightmapValue(cache, blockX - 1, blockZ);
- //heightmap is already block above top block, don't add 1
- int heightMin = min(heightmapZpos, heightmapZneg, heightmapXpos, heightmapXneg);
- //if the top block is above - the top block didn't change. Calculate light only in this cube
- if(blockToCube(heightMax) > cubeY) {
- if (heightMin > heightMax) {
- return null;
- }
- int cubeBottomY = cubeToMinBlock(cubeY);
- int cubeTopY = cubeToMaxBlock(cubeY);
- //if heightMin is also above that cube - no reason to update at all.
- //It must be dark or light will get there from cube edge.
- if(blockToCube(heightMin) > cube.getY()) {
- return null;
- }
- heightMin = Math.max(heightMin, cubeBottomY);
- heightMax = Math.min(heightMax, cubeTopY);
- assert heightMin <= heightMax : "heightMin > heightMax (" + heightMin + ">" + heightMax + ")";
- return new ImmutablePair<>(heightMin, heightMax);
- }
- int cubeBottomY = cubeToMinBlock(cubeY);
- //add one to get block just above
- int heightBelowCube = getHeightmapBelowCubeY(
- cube.getColumn(), blockToLocal(blockX), blockToLocal(blockZ), cubeY) + 1;
- mutablePos.set(blockX, cubeBottomY, blockZ);
- assert heightBelowCube <= cubeBottomY : "heightBelowCube <= cubeBottomY (" + heightBelowCube + " > " + cubeBottomY + ")";
- boolean isBlockBelowCubeBottomOpaque = heightBelowCube == cubeBottomY;
- if(!isBlockBelowCubeBottomOpaque) {
- //extend skylight refresh to the top block below current cube
- //it needs relight because it's set to full darkness, and light may reach it from somewhere else
- heightMin = heightBelowCube;
- }
- if (heightMin > heightMax) {
- return null;
- }
- return new ImmutablePair<>(heightMin, heightMax);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement