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