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 static byte GetSkyLight(BlockCoordinates blockCoordinates, ChunkColumn chunk) { if (chunk == null) { return(15); } return(chunk.GetSkylight(blockCoordinates.X & 0x0f, blockCoordinates.Y & 0xff, blockCoordinates.Z & 0x0f)); }
public static int GetHeight(BlockCoordinates blockCoordinates, ChunkColumn chunk) { if (chunk == null) { return(256); } return(chunk.GetHeight(blockCoordinates.X & 0x0f, blockCoordinates.Z & 0x0f)); }
public int GetHeight(BlockCoordinates coordinates) { ChunkColumn chunk = GetChunk(coordinates, true); if (chunk == null) { return(_heightForUnloadedChunk); } return(chunk.GetHeight(coordinates.X & 0x0f, coordinates.Z & 0x0f)); }
public static bool IsNotBlockingSkylight(BlockCoordinates blockCoordinates, ChunkColumn chunk) { if (chunk == null) { return(true); } var b = chunk.GetBlockState(blockCoordinates.X & 0x0f, blockCoordinates.Y & 0xff, blockCoordinates.Z & 0x0f).Block; return(b is Air || !b.BlockMaterial.BlocksLight()); // (b.Transparent && !(b is Leaves)); // int bid = chunk.GetBlockId(blockCoordinates.X & 0x0f, blockCoordinates.Y & 0xff, blockCoordinates.Z & 0x0f); // return bid == 0 || (BlockFactory.TransparentBlocks[bid] == 1 && bid != 18 && bid != 161 && bid != 30 && bid != 8 && bid != 9); }
public static byte GetSkyLight(BlockCoordinates blockCoordinates, ChunkSection 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)); }
private void MakeVisit(BlockCoordinates inc) { BlockCoordinates coordinates = new BlockCoordinates(inc.X, 0, inc.Z); if (Visits.ContainsKey(coordinates)) { Visits[coordinates] = Visits[coordinates] + 1; } else { Visits.TryAdd(coordinates, 1); } }
private static int GetHeighestSurrounding(int x, int z, ChunkColumn chunk, IBlockAccess level) { int h = chunk.GetHeight(x, z); if (h == 255) { return(h); } if (x == 0 || x == 15 || z == 0 || z == 15) { var coords = new BlockCoordinates(x + (chunk.X * 16), h, z + (chunk.Z * 16)); //h = Math.Max(h, level.GetHeight(coords + BlockCoordinates.Up)); h = Math.Max(h, level.GetHeight(coords + BlockCoordinates.West)); h = Math.Max(h, level.GetHeight(coords + BlockCoordinates.East)); h = Math.Max(h, level.GetHeight(coords + BlockCoordinates.North)); h = Math.Max(h, level.GetHeight(coords + BlockCoordinates.South)); if (h > 255) { h = 255; } if (h < 0) { h = 0; } return(h); } //if (z < 15) h = Math.Max(h, chunk.GetHeight(x, z + 1)); //if (z > 0) h = Math.Max(h, chunk.GetHeight(x, z - 1)); //if (x < 15) h = Math.Max(h, chunk.GetHeight(x + 1, z)); //if (x < 15 && z > 0) h = Math.Max(h, chunk.GetHeight(x + 1, z - 1)); //if (x < 15 && z < 15) h = Math.Max(h, chunk.GetHeight(x + 1, z + 1)); //if (x > 0) h = Math.Max(h, chunk.GetHeight(x - 1, z)); //if (x > 0 && z > 0) h = Math.Max(h, chunk.GetHeight(x - 1, z - 1)); //if (x > 0 && z < 15) h = Math.Max(h, chunk.GetHeight(x - 1, z + 1)); h = Math.Max(h, chunk.GetHeight(x, z + 1)); h = Math.Max(h, chunk.GetHeight(x, z - 1)); h = Math.Max(h, chunk.GetHeight(x + 1, z)); //h = Math.Max(h, chunk.GetHeight(x + 1, z - 1)); //h = Math.Max(h, chunk.GetHeight(x + 1, z + 1)); h = Math.Max(h, chunk.GetHeight(x - 1, z)); //h = Math.Max(h, chunk.GetHeight(x - 1, z - 1)); //h = Math.Max(h, chunk.GetHeight(x - 1, z + 1)); return(h); }
private static bool IsTransparent(BlockCoordinates blockCoordinates, ChunkSection section) { if (section == null) { return(true); } int bx = blockCoordinates.X & 0x0f; int by = blockCoordinates.Y & 0xff; int bz = blockCoordinates.Z & 0x0f; var state = section.Get(bx, by - 16 * (by >> 4), bz); return(state.Block is Air || state.Block.Transparent); // return bid == 0 || BlockFactory.TransparentBlocks[bid] == 1; }
public static int GetDiffuseLevel(BlockCoordinates blockCoordinates, ChunkSection 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; var state = section.Get(bx, by - 16 * (by >> 4), bz); return(state.Block.LightOpacity); //return bid == 8 || bid == 9 ? 3 : bid == 18 || bid == 161 || bid == 30 ? 2 : 1; }
public bool RecalcSkyLight(ChunkColumn chunk, IBlockAccess level) { if (chunk == null) { return(false); } var lightBfQueue = new Queue <BlockCoordinates>(); var lightBfSet = new HashSet <BlockCoordinates>(); for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { if (!IsOnChunkBorder(x, z)) { continue; } int height = GetHeighestSurrounding(x, z, chunk, level); if (height == 0) { continue; } //var skyLight = chunk.GetSkylight(x, height, z); //if (skyLight == 15) { //Block block = level.GetBlockId(new BlockCoordinates(x + (chunk.x*16), height, z + (chunk.z*16)), chunk); //Calculate(level, block); //Calculate(level, new BlockCoordinates(x + (chunk.x*16), height, z + (chunk.z*16)), lightBfQueue); var coordinates = new BlockCoordinates(x + (chunk.X * 16), height, z + (chunk.Z * 16)); lightBfQueue.Enqueue(coordinates); lightBfSet.Add(coordinates); } //else //{ // Log.Error($"Block with wrong light level. Expected 15 but was {skyLight}"); //} } } Calculate(level, lightBfQueue, lightBfSet); return(true); }
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); }
public Block GetBlock(BlockCoordinates coord, ChunkColumn tryChunk = null) { return(null); }
public ChunkColumn GetChunk(BlockCoordinates coordinates, bool cacheOnly = false) { return(GetChunk((ChunkCoordinates)coordinates, cacheOnly)); }
public void SetSkyLight(BlockCoordinates coordinates, byte skyLight) { ChunkColumn chunk = GetChunk(coordinates, true); chunk?.SetSkyLight(coordinates.X & 0x0f, coordinates.Y & 0xff, coordinates.Z & 0x0f, skyLight); }
public static void SetSkyLight(BlockCoordinates coordinates, byte skyLight, ChunkColumn chunk) { chunk?.SetSkyLight(coordinates.X & 0x0f, coordinates.Y & 0xff, coordinates.Z & 0x0f, skyLight); }
private byte SetLightLevel(IBlockAccess level, ChunkColumn chunk, ChunkSection subChunk, 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); } var chunkCoords = (ChunkCoordinates)coordinates; if (!(up || down) && (chunk.X != coordinates.X >> 4 || chunk.Z != coordinates.Z >> 4)) { chunk = (ChunkColumn)level.GetChunk(chunkCoords); subChunk = null; } else { if ((up || down) && coordinates.Y >> 4 != sectionIdx) { subChunk = null; } } if (chunk == null /* || chunk.chunks == null*/) { return(lightLevel); } if (!down && !up && coordinates.Y >= GetHeight(coordinates, chunk)) { if (GetSkyLight(coordinates, subChunk) != 15) { SetSkyLight(coordinates, 15, chunk); if (!lightBfSet.Contains(coordinates)) { lightBfsQueue.Enqueue(coordinates); lightBfSet.Add(coordinates); } } return(15); } if (subChunk == null) { subChunk = (ChunkSection)chunk.Sections[coordinates.Y >> 4]; } bool isTransparent = IsTransparent(coordinates, subChunk); byte skyLight = GetSkyLight(coordinates, subChunk); 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, subChunk); 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); }
private static void SetSkyLight(IBlockAccess world, BlockCoordinates coordinates, byte skyLight) { world?.SetSkyLight(coordinates, skyLight); //chunk?.SetSkyLight(coordinates.X & 0x0f, coordinates.Y & 0xff, coordinates.Z & 0x0f, skyLight); }
private void TestForSource(World level, Queue <BlockCoordinates> resetQueue, Queue <BlockCoordinates> sourceQueue, BlockCoordinates coordinates, int currentLight, bool down = false) { int light = level.GetSkyLight(coordinates); if (light == 0) { return; } if (light > currentLight || (light == 15 && !down)) { if (!sourceQueue.Contains(coordinates)) { sourceQueue.Enqueue(coordinates); } return; } if (!resetQueue.Contains(coordinates)) { resetQueue.Enqueue(coordinates); } }
public byte GetBlockLight(BlockCoordinates coordinates) { return(0); }
private static void SetSkyLight(IBlockAccess world, BlockCoordinates coordinates, byte skyLight, ChunkColumn chunk) { chunk?.SetSkyLight(coordinates.X & 0x0f, coordinates.Y & 0xff, coordinates.Z & 0x0f, skyLight); }
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 byte GetSkyLight(BlockCoordinates coordinates) { return(15); }