private void SpreadInChunk(Chunk chunk)
        {
            int sunLightLevel;

            for (int x = 0; x < Chunk.chunkWidth; x++)
            {
                bool isXInRange = (x != 0 && x != Chunk.chunkWidth - 1);
                for (int z = 0; z < Chunk.chunkDepth; z++)
                {
                    bool isZInRange  = (z != 0 && z != Chunk.chunkDepth - 1);
                    int  height      = chunk.GetHeight(x, z, true);
                    int  leftHeight  = chunk.GetHeight(x - 1, z, isXInRange);
                    int  rightHeight = chunk.GetHeight(x + 1, z, isXInRange);
                    int  frontHeight = chunk.GetHeight(x, z + 1, isZInRange);
                    int  backHeight  = chunk.GetHeight(x, z - 1, isZInRange);
                    int  maxHeight   = GetMax(height, leftHeight, rightHeight, frontHeight, backHeight);
                    for (int y = Chunk.chunkHeight - 1; y >= 0; y--)
                    {
                        if (y <= maxHeight)
                        {
                            sunLightLevel = chunk.GetSunLight(x, y, z, true);
                            if (sunLightLevel <= 0)
                            {
                                break;
                            }
                            int             index = (x * Chunk.chunkDepth + z) * Chunk.chunkHeight + y;
                            LightSpreadNode node  = NodeCache.Instance.GetSpreadNode(index, sunLightLevel, chunk);
                            _lightSpread.AddSpreadNode(node);
                        }
                    }
                }
            }
        }
Example #2
0
 public void SaveSpreadNode(LightSpreadNode node)
 {
     lock (_lockObj)
     {
         node.index      = 0;
         node.lightLevel = 0;
         node.chunk      = null;
         spreadNodes.Enqueue(node);
         if (maxSpread < spreadNodes.Count)
         {
             maxSpread = spreadNodes.Count;
         }
     }
 }
Example #3
0
        public LightSpreadNode GetSpreadNode(int index, int level, Chunk chunk)
        {
            LightSpreadNode node;

            lock (_lockObj)
            {
                if (spreadNodes.Count > 0)
                {
                    node            = spreadNodes.Dequeue();
                    node.index      = index;
                    node.lightLevel = level;
                    node.chunk      = chunk;
                }
                else
                {
                    node = new LightSpreadNode(index, level, chunk);
                }
            }
            return(node);
        }
        private List <Chunk> GetBlockLightChangeChunks(Chunk chunk, int x, int y, int z, Block b, List <Chunk> list)
        {
            BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(b.BlockType);
            int curBlockLightLevel = calculator.LightLevel(b.ExtendId);
            int blockLightLevel    = chunk.GetBlockLight(x, y, z, true);

            if (curBlockLightLevel > blockLightLevel)
            {
                int             index = (x * Chunk.chunkDepth + z) * Chunk.chunkHeight + y;
                LightSpreadNode node  = NodeCache.Instance.GetSpreadNode(index, curBlockLightLevel, chunk);
                _blockLightSpread.AddSpreadNode(node);
                chunk.SetBlockLight(x, y, z, curBlockLightLevel, true);
            }
            else if (curBlockLightLevel < blockLightLevel)
            {
                int             index = (x * Chunk.chunkDepth + z) * Chunk.chunkHeight + y;
                LightShrinkNode node  = NodeCache.Instance.GetShrinkNode(index, blockLightLevel, curBlockLightLevel, chunk);
                _blockLightShrink.AddShrinkNode(node);
                chunk.SetBlockLight(x, y, z, curBlockLightLevel, true);
            }
            List <Chunk> spreadList = _blockLightSpread.SpreadInChunk(chunk);
            List <Chunk> shrinkList = _blockLightShrink.ShrinkInChunk(chunk);

            for (int i = 0; i < spreadList.Count; i++)
            {
                if (!list.Contains(spreadList[i]))
                {
                    list.Add(spreadList[i]);
                }
            }
            for (int i = 0; i < shrinkList.Count; i++)
            {
                if (!list.Contains(shrinkList[i]))
                {
                    list.Add(shrinkList[i]);
                }
            }
            return(list);
        }
        public List <Chunk> SpreadInChunk(Chunk chunk)
        {
            int   nextX;
            int   nextY;
            int   nextZ;
            Chunk nextChunk;

            _changedList.Clear();
            while (_lightBfsQueue.Count > 0)
            {
                LightSpreadNode node = _lightBfsQueue.Dequeue();
                int             y    = node.index % Chunk.chunkHeight;
                int             temp = node.index / Chunk.chunkHeight;
                int             z    = temp % Chunk.chunkDepth;
                int             x    = temp / Chunk.chunkDepth;

                Chunk nodeChunk = node.chunk;

                int curLightLevel = node.lightLevel;

                NodeCache.Instance.SaveSpreadNode(node);

                //y - 1
                nextY = y - 1;
                if (nextY >= 0)
                {
                    SpreadVerticalInPos(x, nextY, z, nodeChunk, curLightLevel);
                }

                //x - 1
                nextX     = x - 1;
                nextChunk = nodeChunk;
                if (nextX < 0)
                {
                    nextChunk = _world.GetChunk(nextX + nodeChunk.worldPos.x, y + nodeChunk.worldPos.y, z + nodeChunk.worldPos.z);
                    nextX     = Chunk.chunkWidth - 1;
                }

                if (nextChunk != null && (nextChunk.isLightDataPrepared || nextChunk.worldPos.EqualOther(chunk.worldPos)))
                {
                    SpreadNormalInPos(nextX, y, z, nextChunk, curLightLevel);
                }

                //x + 1
                nextX     = x + 1;
                nextChunk = nodeChunk;
                if (nextX >= Chunk.chunkWidth)
                {
                    nextChunk = _world.GetChunk(nextX + nodeChunk.worldPos.x, y + nodeChunk.worldPos.y, z + nodeChunk.worldPos.z);
                    nextX     = 0;
                }

                if (nextChunk != null && (nextChunk.isLightDataPrepared || nextChunk.worldPos.EqualOther(chunk.worldPos)))
                {
                    SpreadNormalInPos(nextX, y, z, nextChunk, curLightLevel);
                }

                //z - 1
                nextZ     = z - 1;
                nextChunk = nodeChunk;
                if (nextZ < 0)
                {
                    nextChunk = _world.GetChunk(x + nodeChunk.worldPos.x, y + nodeChunk.worldPos.y, nextZ + nodeChunk.worldPos.z);
                    nextZ     = Chunk.chunkDepth - 1;
                }
                if (nextChunk != null && (nextChunk.isLightDataPrepared || nextChunk.worldPos.EqualOther(chunk.worldPos)))
                {
                    SpreadNormalInPos(x, y, nextZ, nextChunk, curLightLevel);
                }

                //z + 1
                nextZ     = z + 1;
                nextChunk = nodeChunk;
                if (nextZ >= Chunk.chunkDepth)
                {
                    nextChunk = _world.GetChunk(x + nodeChunk.worldPos.x, y + nodeChunk.worldPos.y, nextZ + nodeChunk.worldPos.z);
                    nextZ     = 0;
                }
                if (nextChunk != null && (nextChunk.isLightDataPrepared || nextChunk.worldPos.EqualOther(chunk.worldPos)))
                {
                    SpreadNormalInPos(x, y, nextZ, nextChunk, curLightLevel);
                }



                // y + 1
                nextY = y + 1;
                if (nextY < Chunk.chunkHeight)
                {
                    SpreadNormalInPos(x, nextY, z, nodeChunk, curLightLevel);
                }
            }
            return(_changedList);
        }
 public void AddSpreadNode(LightSpreadNode node)
 {
     _lightBfsQueue.Enqueue(node);
 }
        private List <Chunk> GetSunLightChangeChunks(Chunk chunk, int x, int y, int z, Block b, List <Chunk> list)
        {
            List <Chunk>             spreadList = null;
            List <Chunk>             shrinkList = null;
            BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(b.BlockType);
            int lightDamp  = calculator.LightDamp(b.ExtendId);
            int height     = chunk.GetHeight(x, z);
            int lightLevel = chunk.GetSunLight(x, y, z, true);
            int curLightLevel;

            if (y >= height - 1)
            {
                for (int ty = y; ty >= height; ty--)
                {
                    Block nextBlock = chunk.GetBlock(x, ty, z);
                    BlockAttributeCalculator nextCalculator = BlockAttributeCalculatorFactory.GetCalculator(nextBlock.BlockType);
                    int nextLightDamp = nextCalculator.LightDamp(nextBlock.ExtendId);
                    if (nextLightDamp > 0)
                    {
                        height = ty + 1;
                        //更新高度
                        chunk.SetHeight(x, z, height, true);
                        break;
                    }
                }
                curLightLevel = WorldConfig.Instance.maxLightLevel - lightDamp;
                if (curLightLevel < 0)
                {
                    curLightLevel = 0;
                }
            }
            else
            {
                int leftSunLight   = chunk.GetSunLight(x - 1, y, z);
                int rightSunLight  = chunk.GetSunLight(x + 1, y, z);
                int topSunLight    = chunk.GetSunLight(x, y + 1, z);
                int bottomSunLight = chunk.GetSunLight(x, y - 1, z);
                int frontSunLight  = chunk.GetSunLight(x, y, z + 1);
                int backSunLight   = chunk.GetSunLight(x, y, z - 1);

                int maxSunLight = GetMax(leftSunLight, rightSunLight, topSunLight, bottomSunLight,
                                         frontSunLight, backSunLight);
                curLightLevel = maxSunLight - lightDamp - 1;
                if (curLightLevel < 0)
                {
                    curLightLevel = 0;
                }
            }

            if (curLightLevel < lightLevel)
            {
                chunk.SetSunLight(x, y, z, curLightLevel, true);
                int             index = (x * Chunk.chunkDepth + z) * Chunk.chunkHeight + y;
                LightShrinkNode node  = NodeCache.Instance.GetShrinkNode(index, lightLevel, curLightLevel, chunk);
                _sunLightShrink.AddShrinkNode(node);
                shrinkList = _sunLightShrink.ShrinkInChunk(chunk);
            }
            else if (curLightLevel > lightLevel)
            {
                chunk.SetSunLight(x, y, z, curLightLevel, true);
                int             index = (x * Chunk.chunkDepth + z) * Chunk.chunkHeight + y;
                LightSpreadNode node  = NodeCache.Instance.GetSpreadNode(index, curLightLevel, chunk);
                _sunLightSpread.AddSpreadNode(node);
                spreadList = _sunLightSpread.SpreadInChunk(chunk);
            }

            if (spreadList != null)
            {
                for (int i = 0; i < spreadList.Count; i++)
                {
                    if (!list.Contains(spreadList[i]))
                    {
                        list.Add(spreadList[i]);
                    }
                }
            }
            if (shrinkList != null)
            {
                for (int i = 0; i < shrinkList.Count; i++)
                {
                    if (!list.Contains(shrinkList[i]))
                    {
                        list.Add(shrinkList[i]);
                    }
                }
            }
            return(list);
        }