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; ChunkBase section = chunk.GetChunk(coordinates.Y); byte maxSkyLight = currentSkyLight; if (coordinates.Y < 255) { var up = coordinates.BlockUp(); maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, up, currentSkyLight, up: true)); } if (coordinates.Y > 0) { var down = coordinates.BlockDown(); maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, down, currentSkyLight, down: true)); } var west = coordinates.BlockWest(); maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, west, currentSkyLight)); var east = coordinates.BlockEast(); maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, east, currentSkyLight)); var south = coordinates.BlockSouth(); maxSkyLight = Math.Max(maxSkyLight, SetLightLevel(level, chunk, section, sectionIdx, lightBfsQueue, lightBfSet, south, currentSkyLight)); var north = coordinates.BlockNorth(); 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); } } } }
public static byte GetSkyLight(BlockCoordinates blockCoordinates, ChunkBase chunk) { if (chunk == null) { return(15); } int bx = blockCoordinates.X & 0x0f; int by = blockCoordinates.Y & 0xff; int bz = blockCoordinates.Z & 0x0f; return(chunk.GetSkylight(bx, by - 16 * (by >> 4), bz)); }
public static bool IsTransparent(BlockCoordinates blockCoordinates, ChunkBase section) { if (section == null) { return(true); } int bx = blockCoordinates.X & 0x0f; int by = blockCoordinates.Y & 0xff; int bz = blockCoordinates.Z & 0x0f; int bid = section.GetBlock(bx, by - 16 * (by >> 4), bz); return(bid == 0 || BlockFactory.TransparentBlocks[bid] == 1); }
public static int GetDiffuseLevel(BlockCoordinates blockCoordinates, ChunkBase chunk) { if (chunk == null) { return(15); } int bx = blockCoordinates.X & 0x0f; int by = blockCoordinates.Y & 0xff; int bz = blockCoordinates.Z & 0x0f; int bid = chunk.GetBlock(bx, by - 16 * (by >> 4), bz); return(bid == 8 || bid == 9 ? 3 : bid == 18 && bid == 30 ? 2 : 1); }
public static int GetDiffuseLevel(BlockCoordinates blockCoordinates, ChunkBase section) { //TODO: Figure out if this is really correct. Perhaps should be zero. if (section == null) { return(15); } int bx = blockCoordinates.X & 0x0f; int by = blockCoordinates.Y & 0xff; int bz = blockCoordinates.Z & 0x0f; int bid = section.GetBlock(bx, by - 16 * (by >> 4), bz); return(bid == 8 || bid == 9 ? 3 : bid == 18 || bid == 161 || bid == 30 ? 2 : 1); }
private byte SetLightLevel(IBlockAccess level, ChunkColumn chunk, ChunkBase 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 == null /* || 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.GetChunk(coordinates.Y); } 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); }