private void ProcessNode(IBlockAccess level, ChunkColumn chunk, BlockCoordinates coordinates, Queue <BlockCoordinates> lightBfsQueue, HashSet <BlockCoordinates> lightBfSet) { //if (section.IsAllAir()) byte currentSkyLight = GetSkyLight(coordinates, chunk); int sectionIdx = coordinates.Y >> 4; ChunkSection subChunk = (ChunkSection)chunk.GetSection(coordinates.Y); byte maxSkyLight = currentSkyLight; if (coordinates.Y < 255) { var up = coordinates.BlockUp(); maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, subChunk, sectionIdx, lightBfsQueue, lightBfSet, up, currentSkyLight, up: true)); } if (coordinates.Y > 0) { var down = coordinates.BlockDown(); maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, subChunk, sectionIdx, lightBfsQueue, lightBfSet, down, currentSkyLight, down: true)); } var west = coordinates.BlockWest(); maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, subChunk, sectionIdx, lightBfsQueue, lightBfSet, west, currentSkyLight)); var east = coordinates.BlockEast(); maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, subChunk, sectionIdx, lightBfsQueue, lightBfSet, east, currentSkyLight)); var south = coordinates.BlockSouth(); maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, subChunk, sectionIdx, lightBfsQueue, lightBfSet, south, currentSkyLight)); var north = coordinates.BlockNorth(); maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, subChunk, sectionIdx, lightBfsQueue, lightBfSet, north, currentSkyLight)); if (IsTransparent(coordinates, subChunk) && currentSkyLight != 15) { int diffuseLevel = GetDiffuseLevel(coordinates, subChunk); maxSkyLight = (byte)Math.Max(currentSkyLight, maxSkyLight - diffuseLevel); if (maxSkyLight > currentSkyLight) { level.SetSkyLight(coordinates, maxSkyLight); if (!lightBfSet.Contains(coordinates)) { lightBfsQueue.Enqueue(coordinates); lightBfSet.Add(coordinates); } } } }
public void ResetLight(World level, Queue <BlockCoordinates> resetQueue, Queue <BlockCoordinates> sourceQueue, BlockCoordinates coordinates) { int currentLight = level.GetSkyLight(coordinates); if (coordinates.Y < 255) { TestForSource(level, resetQueue, sourceQueue, coordinates.BlockUp(), currentLight); } if (coordinates.Y > 0) { TestForSource(level, resetQueue, sourceQueue, coordinates.BlockDown(), currentLight, true); } TestForSource(level, resetQueue, sourceQueue, coordinates.BlockWest(), currentLight); TestForSource(level, resetQueue, sourceQueue, coordinates.BlockEast(), currentLight); TestForSource(level, resetQueue, sourceQueue, coordinates.BlockNorth(), currentLight); TestForSource(level, resetQueue, sourceQueue, coordinates.BlockSouth(), currentLight); }
public void Calculate(World level, BlockCoordinates coordinates) { int currentLight = level.GetSkyLight(coordinates); var cc = new ChunkCoordinates(coordinates); ChunkColumn chunk = (ChunkColumn)level.GetChunkColumn(cc.X, cc.Z); var height = chunk.GetRecalculatedHeight(coordinates.X & 0x0f, coordinates.Z & 0x0f); Queue <BlockCoordinates> sourceQueue = new Queue <BlockCoordinates>(); sourceQueue.Enqueue(coordinates); if (currentLight != 0) { Queue <BlockCoordinates> resetQueue = new Queue <BlockCoordinates>(); HashSet <BlockCoordinates> visits = new HashSet <BlockCoordinates>(); // Reset all lights that potentially derive from this resetQueue.Enqueue(coordinates); Queue <BlockCoordinates> deleteQueue = new Queue <BlockCoordinates>(); while (resetQueue.Count > 0) { var coord = resetQueue.Dequeue(); if (visits.Contains(coord)) { continue; } visits.Add(coord); if (coord.DistanceTo(coordinates) > 16) { continue; } ResetLight(level, resetQueue, sourceQueue, coord); if (!sourceQueue.Contains(coord)) { deleteQueue.Enqueue(coord); } } level.SetSkyLight(coordinates, 0); foreach (var delete in deleteQueue) { level.SetSkyLight(delete, 0); } } else { sourceQueue.Enqueue(coordinates); sourceQueue.Enqueue(coordinates.BlockUp()); sourceQueue.Enqueue(coordinates.BlockDown()); sourceQueue.Enqueue(coordinates.BlockWest()); sourceQueue.Enqueue(coordinates.BlockEast()); sourceQueue.Enqueue(coordinates.BlockNorth()); sourceQueue.Enqueue(coordinates.BlockSouth()); } chunk.SetHeight(coordinates.X & 0x0f, coordinates.Z & 0x0f, (short)height); // Recalc Queue <BlockCoordinates> lightBfQueue = new Queue <BlockCoordinates>(sourceQueue); HashSet <BlockCoordinates> lightBfSet = new HashSet <BlockCoordinates>(sourceQueue); SkyLightBlockAccess blockAccess = new SkyLightBlockAccess(level.ChunkManager); Calculate(blockAccess, lightBfQueue, lightBfSet); }