Пример #1
0
        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);
                    }
                }
            }
        }
Пример #2
0
        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));
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }