Exemplo n.º 1
0
        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);
                    }
                }
            }
        }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        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);
                }
            }
        }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 5
0
        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);
        }