private void LightBlocks(Stack <Vector3Int> queue, ref int limit, ModificationSource source)
        {
            while (limit-- > 0 && queue.Count > 0)
            {
                Vector3Int blockPos = queue.Pop();

                if (blockPos.y < 0 || blockPos.y >= ChunkHeight)
                {
                    continue;
                }

                if (!ChunkManager.GetChunk(ChunkPos.GetFromAny(blockPos.x, blockPos.z), false, out _))
                {
                    // 我不想管这个了,如果有人有好的算法请告诉我!
                    // m_BlocksToLightQueue.Push(blockPos);
                    // break;
                    continue;
                }

                int x = blockPos.x;
                int y = blockPos.y;
                int z = blockPos.z;

                BlockData block      = RWAccessor.GetBlock(x, y, z);
                int       opacity    = Mathf.Max(block.LightOpacity, 1);
                int       finalLight = 0;

                if (opacity < MaxLight || block.LightValue > 0) // 不然就是0
                {
                    int max = RWAccessor.GetAmbientLight(x + 1, y, z);
                    int temp;

                    if ((temp = RWAccessor.GetAmbientLight(x - 1, y, z)) > max)
                    {
                        max = temp;
                    }

                    if ((temp = RWAccessor.GetAmbientLight(x, y + 1, z)) > max)
                    {
                        max = temp;
                    }

                    if ((temp = RWAccessor.GetAmbientLight(x, y - 1, z)) > max)
                    {
                        max = temp;
                    }

                    if ((temp = RWAccessor.GetAmbientLight(x, y, z + 1)) > max)
                    {
                        max = temp;
                    }

                    if ((temp = RWAccessor.GetAmbientLight(x, y, z - 1)) > max)
                    {
                        max = temp;
                    }

                    finalLight = max - opacity;

                    if (block.LightValue > finalLight)
                    {
                        finalLight = block.LightValue; // 假设这个值一定是合法的(不过确实应该是合法的)
                    }
                    else if (finalLight < 0)
                    {
                        finalLight = 0;
                    }
                    //else if (finalLight > MaxLight)
                    //{
                    //    finalLight = MaxLight;
                    //}
                }

                if (RWAccessor.SetAmbientLightLevel(x, y, z, finalLight, source))
                {
                    queue.Push(new Vector3Int(x - 1, y, z));
                    queue.Push(new Vector3Int(x, y - 1, z));
                    queue.Push(new Vector3Int(x, y, z - 1));
                    queue.Push(new Vector3Int(x + 1, y, z));
                    queue.Push(new Vector3Int(x, y + 1, z));
                    queue.Push(new Vector3Int(x, y, z + 1));
                }
            }
        }
        public bool SetBlockType(int worldX, int y, int worldZ, BlockType value, byte state = 0, bool lightBlocks = true, bool tickBlocks = true, bool updateNeighborSections = true)
        {
            if (y >= WorldHeight || y < 0)
            {
                return(false);
            }

            int localX = worldX - PositionX;
            int localZ = worldZ - PositionZ;

            if (!m_Data.SetBlockType(localX, y, localZ, value, out BlockType previousBlockType))
            {
                return(false);
            }

            m_Data.SetBlockState(localX, y, localZ, state);
            UpdateHeightMapAndSkyLight(localX, y, localZ);


            WorldManager world       = WorldManager.Active;
            ChunkManager manager     = world.ChunkManager;
            DataManager  dataManager = world.DataManager;

            Block previousBlock = dataManager.GetBlockByType(previousBlockType);
            Block block         = dataManager.GetBlockByType(value);

            int sectionIndex = Mathf.FloorToInt(y * OverSectionHeight);
            int yInSection   = y - sectionIndex * SectionHeight;

            if (previousBlock.HasAnyFlag(BlockFlags.NeedsRandomTick))
            {
                m_Data.DecreaseTickRefCount(sectionIndex);
            }

            if (block.HasAnyFlag(BlockFlags.NeedsRandomTick))
            {
                m_Data.IncreaseTickRefCount(sectionIndex);
            }

            if (previousBlock.VertexType != BlockVertexType.None)
            {
                if (previousBlock.HasAnyFlag(BlockFlags.Liquid))
                {
                    m_Data.DecreaseRenderableLiquidCount(sectionIndex);
                }
                else
                {
                    m_Data.DecreaseRenderableSolidCount(sectionIndex);
                }
            }

            if (block.VertexType != BlockVertexType.None)
            {
                if (block.HasAnyFlag(BlockFlags.Liquid))
                {
                    m_Data.IncreaseRenderableLiquidCount(sectionIndex);
                }
                else
                {
                    m_Data.IncreaseRenderableSolidCount(sectionIndex);
                }
            }

            SetMeshDirty(sectionIndex, GetDirtyFlags(previousBlock, block));

            if (lightBlocks)
            {
                manager.LightBlock(worldX, y, worldZ);
            }

            if (tickBlocks)
            {
                manager.TickBlock(worldX, y, worldZ);
            }

            if (updateNeighborSections)
            {
                if (localX == 0)
                {
                    Chunk chunk = manager.GetChunk(PositionX - ChunkWidth, PositionZ);
                    chunk?.SetMeshDirty(sectionIndex, MeshDirtyFlags.Both);
                }
                else if (localX == ChunkWidth - 1)
                {
                    Chunk chunk = manager.GetChunk(PositionX + ChunkWidth, PositionZ);
                    chunk?.SetMeshDirty(sectionIndex, MeshDirtyFlags.Both);
                }

                if (yInSection == 0 && sectionIndex > 0)
                {
                    SetMeshDirty(sectionIndex - 1, MeshDirtyFlags.Both);
                }
                else if (yInSection == SectionHeight - 1 && sectionIndex < SectionCountInChunk - 1)
                {
                    SetMeshDirty(sectionIndex + 1, MeshDirtyFlags.Both);
                }

                if (localZ == 0)
                {
                    Chunk chunk = manager.GetChunk(PositionX, PositionZ - ChunkWidth);
                    chunk?.SetMeshDirty(sectionIndex, MeshDirtyFlags.Both);
                }
                else if (localZ == ChunkWidth - 1)
                {
                    Chunk chunk = manager.GetChunk(PositionX, PositionZ + ChunkWidth);
                    chunk?.SetMeshDirty(sectionIndex, MeshDirtyFlags.Both);
                }
            }

            return(m_IsModified = true);
        }
        public byte GetBlockLight(int x, int y, int z)
        {
            Chunk chunk = ChunkManager.GetChunk(x, z);

            return(chunk == null ? WorldConsts.MaxLight : chunk.GetBlockLight(x, y, z));
        }
        public void SetBlockLight(int x, int y, int z, byte value)
        {
            Chunk chunk = ChunkManager.GetChunk(x, z);

            chunk?.SetBlockLight(x, y, z, value);
        }
        public byte GetFinalLightLevel(int x, int y, int z)
        {
            Chunk chunk = ChunkManager.GetChunk(x, z);

            return(chunk == null ? WorldConsts.MaxLight : chunk.GetFinalLightLevel(x, y, z));
        }
        public byte GetBlockState(int x, int y, int z)
        {
            Chunk chunk = ChunkManager.GetChunk(x, z);

            return(chunk.GetBlockState(x, y, z));
        }
        public void SetBlockState(int x, int y, int z, byte value)
        {
            Chunk chunk = ChunkManager.GetChunk(x, z);

            chunk.SetBlockState(x, y, z, value);
        }
        public BlockType GetBlockType(int x, int y, int z)
        {
            Chunk chunk = ChunkManager.GetChunk(x, z);

            return(chunk == null ? BlockType.Air : chunk.GetBlockType(x, y, z));
        }
        public bool SetBlockType(int x, int y, int z, BlockType block, byte state = 0, bool lightBlocks = true, bool tickBlocks = true, bool updateNeighborSections = true)
        {
            Chunk chunk = ChunkManager.GetChunk(x, z);

            return(chunk.SetBlockType(x, y, z, block, state, lightBlocks, tickBlocks, updateNeighborSections));
        }