public void Calculate(Level level, Queue <BlockCoordinates> lightBfQueue, HashSet <BlockCoordinates> lightBfSet) { try { //if (block.SkyLight != 15) //{ // Log.Error($"Block at {block.Coordinates} had unexpected light level. Expected 15 but was {block.SkyLight}"); //} while (lightBfQueue.Count > 0) { var coordinates = lightBfQueue.Dequeue(); lightBfSet.Remove(coordinates); ChunkColumn chunk = level.GetChunk(coordinates); var newChunkCoord = (ChunkCoordinates)coordinates; if (chunk.x != newChunkCoord.X || chunk.z != newChunkCoord.Z) { chunk = level.GetChunk(newChunkCoord); } ProcessNode(level, chunk, coordinates, lightBfQueue, lightBfSet); } } catch (Exception e) { Log.Error("Calculation", e); } }
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); }
private byte SetLightLevel(Level level, ChunkColumn chunk, Chunk section, int sectionIdx, Queue <BlockCoordinates> lightBfsQueue, HashSet <BlockCoordinates> lightBfSet, BlockCoordinates coordinates, byte lightLevel, bool down = false, bool up = false) { //Interlocked.Add(ref visits, 1); if (TrackResults) { MakeVisit(coordinates); } if (!(up || down) && (chunk.x != coordinates.X >> 4 || chunk.z != coordinates.Z >> 4)) { chunk = level.GetChunk((ChunkCoordinates)coordinates); section = null; } else { if ((up || down) && coordinates.Y >> 4 != sectionIdx) { section = null; } } if (chunk?.chunks == null) { return(lightLevel); } if (!down && !up && coordinates.Y >= GetHeight(coordinates, chunk)) { if (GetSkyLight(coordinates, section) != 15) { SetSkyLight(coordinates, 15, chunk); if (!lightBfSet.Contains(coordinates)) { lightBfsQueue.Enqueue(coordinates); lightBfSet.Add(coordinates); } } return(15); } if (section == null) { section = chunk.chunks[coordinates.Y >> 4]; } bool isTransparent = IsTransparent(coordinates, section); byte skyLight = GetSkyLight(coordinates, section); if (down && isTransparent && lightLevel == 15) { if (IsNotBlockingSkylight(coordinates, chunk)) { if (skyLight != 15) { SetSkyLight(coordinates, 15, chunk); } if (!lightBfSet.Contains(coordinates)) { lightBfsQueue.Enqueue(coordinates); lightBfSet.Add(coordinates); } return(15); } } if (isTransparent) { int diffuseLevel = GetDiffuseLevel(coordinates, section); if (skyLight + 1 + diffuseLevel <= lightLevel) { byte newLevel = (byte)(lightLevel - diffuseLevel); SetSkyLight(coordinates, newLevel, chunk); if (!lightBfSet.Contains(coordinates)) { lightBfsQueue.Enqueue(coordinates); lightBfSet.Add(coordinates); } return(newLevel); } } return(skyLight); }