private void ProcessNode(Level level, ChunkColumn chunk, BlockCoordinates coordinates, Queue <BlockCoordinates> lightBfsQueue, HashSet <BlockCoordinates> lightBfSet) { //if (section.IsAllAir()) byte currentSkyLight = GetSkyLight(coordinates, chunk); int sectionIdx = coordinates.Y >> 4; Chunk section = chunk.chunks[sectionIdx]; byte maxSkyLight = currentSkyLight; if (coordinates.Y < 255) { var up = coordinates + BlockCoordinates.Up; maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, up, currentSkyLight, up: true)); } if (coordinates.Y > 0) { var down = coordinates + BlockCoordinates.Down; maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, down, currentSkyLight, down: true)); } var west = coordinates + BlockCoordinates.West; maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, west, currentSkyLight)); var east = coordinates + BlockCoordinates.East; maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, east, currentSkyLight)); var south = coordinates + BlockCoordinates.South; maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, south, currentSkyLight)); var north = coordinates + BlockCoordinates.North; maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, north, currentSkyLight)); if (IsTransparent(coordinates, section) && currentSkyLight != 15) { int diffuseLevel = GetDiffuseLevel(coordinates, section); maxSkyLight = (byte)Math.Max(currentSkyLight, maxSkyLight - diffuseLevel); if (maxSkyLight > currentSkyLight) { level.SetSkyLight(coordinates, maxSkyLight); if (!lightBfSet.Contains(coordinates)) { lightBfsQueue.Enqueue(coordinates); lightBfSet.Add(coordinates); } } } }
private byte SetLightLevel(Level level, Queue <BlockCoordinates> lightBfsQueue, BlockCoordinates coordinates, byte lightLevel, bool down = false, bool up = false) { if (_trackResults) { MakeVisit(coordinates); } if (!down && !up && coordinates.Y >= level.GetHeight(coordinates)) { level.SetSkyLight(coordinates, 15); return(15); } bool isTransparent = level.IsTransparent(coordinates); byte skyLight = level.GetSkyLight(coordinates); if (down && isTransparent && lightLevel == 15) { if (skyLight != 15) { level.SetSkyLight(coordinates, 15); } /*if (!lightBfsQueue.Contains(coordinates)) */ lightBfsQueue.Enqueue(coordinates); return(15); } if (isTransparent && skyLight + 2 <= lightLevel) { byte newLevel = (byte)(lightLevel - 1); level.SetSkyLight(coordinates, newLevel); /*if (!lightBfsQueue.Contains(coordinates)) */ lightBfsQueue.Enqueue(coordinates); return(newLevel); } return(skyLight); }
private void ProcessNode(Level level, BlockCoordinates coordinates, Queue <BlockCoordinates> lightBfsQueue) { byte currentSkyLight = level.GetSkyLight(coordinates); byte maxSkyLight = currentSkyLight; if (coordinates.Y < 255) { var up = coordinates + BlockCoordinates.Up; maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, lightBfsQueue, up, currentSkyLight, up: true)); } if (coordinates.Y > 0) { var down = coordinates + BlockCoordinates.Down; maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, lightBfsQueue, down, currentSkyLight, down: true)); } var west = coordinates + BlockCoordinates.West; maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, lightBfsQueue, west, currentSkyLight)); var east = coordinates + BlockCoordinates.East; maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, lightBfsQueue, east, currentSkyLight)); var south = coordinates + BlockCoordinates.South; maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, lightBfsQueue, south, currentSkyLight)); var north = coordinates + BlockCoordinates.North; maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, lightBfsQueue, north, currentSkyLight)); if (level.IsAir(coordinates) && currentSkyLight != 15) { maxSkyLight = (byte)Math.Max(currentSkyLight, maxSkyLight - 1); if (maxSkyLight > currentSkyLight) { level.SetSkyLight(coordinates, maxSkyLight); /*if (!lightBfsQueue.Contains(coordinates)) */ lightBfsQueue.Enqueue(coordinates); } } }
public void Calculate(Level level, BlockCoordinates coordinates) { int currentLight = level.GetSkyLight(coordinates); var chunk = level.GetChunk(coordinates); var height = chunk.GetRecalatedHeight(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); 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 + BlockCoordinates.Up); sourceQueue.Enqueue(coordinates + BlockCoordinates.Down); sourceQueue.Enqueue(coordinates + BlockCoordinates.West); sourceQueue.Enqueue(coordinates + BlockCoordinates.East); sourceQueue.Enqueue(coordinates + BlockCoordinates.North); sourceQueue.Enqueue(coordinates + BlockCoordinates.South); } 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); Calculate(level, lightBfQueue, lightBfSet); }
public void Calculate(Level level, BlockCoordinates coordinates) { int currentLight = level.GetSkyLight(coordinates); var chunk = level.GetChunk(coordinates); var height = chunk.GetRecalatedHeight(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.WorldProvider); Calculate(blockAccess, lightBfQueue, lightBfSet); }