protected void RecycleGenerationContext(GenerationContext context)
 {
     m_GenContextPool.Add(context);
 }
        private void GenerateBasicTerrain(IWorld world, ChunkPos pos, BlockData[,,] blocks, GenerationHelper helper, GenerationContext context)
        {
            int x = pos.X / 16;
            int z = pos.Z / 16;

            // 产生高度图
            GenerateDensityMap(new Vector3Int(x * 4, 0, z * 4), helper, context);

            BlockData airBlock   = world.BlockDataTable.GetBlock(AirBlock);
            BlockData stoneBlock = world.BlockDataTable.GetBlock(StoneBlock);
            BlockData waterBlock = world.BlockDataTable.GetBlock(WaterBlock);

            // 进行线性插值
            for (int xHigh = 0; xHigh < 4; xHigh++)
            {
                for (int zHigh = 0; zHigh < 4; zHigh++)
                {
                    for (int yHigh = 0; yHigh < 32; yHigh++)
                    {
                        float yPart111       = context.DensityMap[xHigh, yHigh, zHigh];
                        float yPart121       = context.DensityMap[xHigh, yHigh, zHigh + 1];
                        float yPart211       = context.DensityMap[xHigh + 1, yHigh, zHigh];
                        float yPart221       = context.DensityMap[xHigh + 1, yHigh, zHigh + 1];
                        float yDensityStep11 = (context.DensityMap[xHigh, yHigh + 1, zHigh] - yPart111) * 0.125f;
                        float yDensityStep12 = (context.DensityMap[xHigh, yHigh + 1, zHigh + 1] - yPart121) * 0.125f;
                        float yDensityStep21 = (context.DensityMap[xHigh + 1, yHigh + 1, zHigh] - yPart211) * 0.125f;
                        float yDensityStep22 = (context.DensityMap[xHigh + 1, yHigh + 1, zHigh + 1] - yPart221) * 0.125f;

                        for (int yLow = 0; yLow < 8; yLow++)
                        {
                            float density111     = yPart111;
                            float density121     = yPart121;
                            float xDensityStep11 = (yPart211 - yPart111) * 0.25f;
                            float xDensityStep21 = (yPart221 - yPart121) * 0.25f;

                            for (int xLow = 0; xLow < 4; xLow++)
                            {
                                float zDensityStep11 = (density121 - density111) * 0.25f;
                                float blockValue     = density111 - zDensityStep11;

                                for (int zLow = 0; zLow < 4; zLow++)
                                {
                                    int posX = xHigh * 4 + xLow;
                                    int posY = yHigh * 8 + yLow;
                                    int posZ = zHigh * 4 + zLow;

                                    if ((blockValue += zDensityStep11) > 0)
                                    {
                                        blocks[posX, posY, posZ] = stoneBlock;
                                    }
                                    else if (posY < SeaLevel)
                                    {
                                        blocks[posX, posY, posZ] = waterBlock;
                                    }
                                    else
                                    {
                                        blocks[posX, posY, posZ] = airBlock;
                                    }
                                }

                                density111 += xDensityStep11;
                                density121 += xDensityStep21;
                            }

                            yPart111 += yDensityStep11;
                            yPart121 += yDensityStep12;
                            yPart211 += yDensityStep21;
                            yPart221 += yDensityStep22;
                        }
                    }
                }
            }
        }
        public override void Generate(IWorld world, ChunkPos pos, BlockData[,,] blocks, Quaternion[,,] rotations, byte[,] heightMap, GenerationHelper helper, GenerationContext context)
        {
            // 生物群系生成
            NativeInt2DArray biomeIds = helper.GenLayers.GetInts(pos.X - 8, pos.Z - 8, 32, 32, Allocator.TempJob);

            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    context.Biomes[j, i] = world.BiomeDataTable.GetBiome(biomeIds[(int)(0.861111f * j * 4), (int)(0.861111f * i * 4)]);
                }
            }

            biomeIds.Dispose();

            // 基本地形生成
            GenerateBasicTerrain(world, pos, blocks, helper, context);

            // 获取生物群系
            biomeIds = helper.GenLayers.GetInts(pos.X, pos.Z, 16, 16, Allocator.TempJob);

            for (int i = 0; i < 16; i++)
            {
                for (int j = 0; j < 16; j++)
                {
                    context.Biomes[j, i] = world.BiomeDataTable.GetBiome(biomeIds[j, i]);
                }
            }

            biomeIds.Dispose();

            // 设置生物群系
            // for (int height = 0; height < 64; ++height)
            // {
            //     for (int i = 0; i < 4; ++i)
            //     {
            //         for (int j = 0; j < 4; ++j)
            //         {
            //             columns[(height * 4 + i) * 4 + j].BiomeConfigData = (int)_biomesForGeneration[j * 4, i * 4].GetBiomeId();
            //         }
            //     }
            // }

            // 添加生物群系特有方块
            ReplaceBiomeBlocks(world, pos, blocks, helper, context);
        }
        private void GenerateBiomeTerrain(int columnX, int columnZ, IWorld world, BlockData[,,] blocks, GenerationContext context)
        {
            float     noise = (context.SurfaceMap[columnX, 0, columnZ] - 0.5f) * 2;
            BiomeData biome = context.Biomes[columnZ, columnX];

            BlockData topBlock     = world.BlockDataTable.GetBlock(biome.TopBlock);
            BlockData fillerBlock  = world.BlockDataTable.GetBlock(biome.FillerBlock);
            BlockData airBlock     = world.BlockDataTable.GetBlock(AirBlock);
            BlockData stoneBlock   = world.BlockDataTable.GetBlock(StoneBlock);
            BlockData gravelBlock  = world.BlockDataTable.GetBlock(GravelBlock);
            BlockData bedrockBlock = world.BlockDataTable.GetBlock(BedrockBlock);

            BlockData currentTopBlock    = topBlock;
            BlockData currentFillerBlock = fillerBlock;

            int surfaceFlag  = -1;
            int surfaceDepth = (int)(noise / 3.0f + 3.0f + (float)context.Rand.NextDouble() * 0.25f);

            for (int y = ChunkHeight - 1; y >= 0; y--)
            {
                if (y <= context.Rand.Next(5))
                {
                    blocks[columnX, y, columnZ] = bedrockBlock;
                }
                else
                {
                    BlockData block = blocks[columnX, y, columnZ];

                    if (block.InternalName == AirBlock)
                    {
                        surfaceFlag = -1;
                    }
                    else if (block.InternalName == StoneBlock)
                    {
                        if (surfaceFlag == -1)
                        {
                            if (surfaceDepth <= 0)
                            {
                                currentTopBlock    = airBlock;
                                currentFillerBlock = stoneBlock;
                            }
                            else if (y >= SeaLevel - 4 && y <= SeaLevel + 1)
                            {
                                currentTopBlock    = topBlock;
                                currentFillerBlock = fillerBlock;
                            }

                            surfaceFlag = surfaceDepth;

                            if (y >= SeaLevel - 1)
                            {
                                blocks[columnX, y, columnZ] = currentTopBlock;
                            }
                            else if (y < SeaLevel - 7 - surfaceDepth)
                            {
                                currentTopBlock             = airBlock;
                                currentFillerBlock          = stoneBlock;
                                blocks[columnX, y, columnZ] = gravelBlock;
                            }
                            else
                            {
                                blocks[columnX, y, columnZ] = currentFillerBlock;
                            }
                        }
                        else if (surfaceFlag > 0)
                        {
                            --surfaceFlag;
                            blocks[columnX, y, columnZ] = currentFillerBlock;
                        }
                    }
                }
            }
        }
        private void ReplaceBiomeBlocks(IWorld world, ChunkPos pos, BlockData[,,] blocks, GenerationHelper helper, GenerationContext context)
        {
            helper.SurfaceNoise.Noise(context.SurfaceMap, new Vector3(pos.X + 0.1f, 0, pos.Z + 0.1f), new Vector3(0.0625f, 1f, 0.0625f));

            for (int x1 = 0; x1 < 16; x1++)
            {
                for (int z1 = 0; z1 < 16; z1++)
                {
                    GenerateBiomeTerrain(x1, z1, world, blocks, context);
                }
            }
        }
        private void GenerateDensityMap(Vector3Int noiseOffset, GenerationHelper helper, GenerationContext context)
        {
            Vector3 depthOffset = new Vector3(noiseOffset.x + 0.1f, 0.0f, noiseOffset.z + 0.1f);
            Vector3 depthScale  = new Vector3(DepthNoiseScale.x, 1.0f, DepthNoiseScale.z);

            helper.DepthNoise.Noise(context.DepthMap, depthOffset, depthScale);

            Vector3 noiseScale = new Vector3(CoordinateScale, HeightScale, CoordinateScale);

            // 生成 3 个 5 * 5 * 33 的噪声
            helper.MainNoise.Noise(context.MainNoiseMap, noiseOffset, Vector3.Scale(noiseScale, MainNoiseScale));
            helper.MinNoise.Noise(context.MinLimitMap, noiseOffset, noiseScale);
            helper.MaxNoise.Noise(context.MaxLimitMap, noiseOffset, noiseScale);

            // chunk遍历
            for (int x1 = 0; x1 < 5; x1++)
            {
                for (int z1 = 0; z1 < 5; z1++)
                {
                    float scale         = 0;
                    float groundYOffset = 0;
                    float totalWeight   = 0;

                    // 中心点生物群系
                    BiomeData centerBiome = context.Biomes[z1 + 2, x1 + 2];

                    // 求 scale 和 groundYOffset 的加权平均值
                    for (int x2 = 0; x2 < 5; x2++)
                    {
                        for (int z2 = 0; z2 < 5; z2++)
                        {
                            BiomeData biome            = context.Biomes[z1 + z2, x1 + x2];
                            float     curGroundYOffset = BiomeDepthOffset + biome.BaseHeight * BiomeDepthWeight;      // biomeDepthOffSet = 0
                            float     curScale         = BiomeScaleOffset + biome.HeightVariation * BiomeScaleWeight; // biomeScaleOffset = 0

                            // parabolicField 为 10 / √(该点到中心点的距离^2 + 0.2)
                            float weight = helper.BiomeWeights[z2, x2] / (curGroundYOffset + 2.0f);

                            if (biome.BaseHeight > centerBiome.BaseHeight)
                            {
                                weight *= 0.5f;
                            }

                            scale         += curScale * weight;
                            groundYOffset += curGroundYOffset * weight;
                            totalWeight   += weight;
                        }
                    }

                    scale         = scale / totalWeight;
                    groundYOffset = groundYOffset / totalWeight;
                    scale         = scale * 0.9f + 0.1f;
                    groundYOffset = (groundYOffset * 4.0f - 1.0f) / 8.0f;

                    // 取一个 -0.36 ~ 0.125 的随机数,这个随机数决定了起伏的地表
                    float random = (context.DepthMap[x1, 0, z1] - 0.5f) * 2 / 8000f;

                    if (random < 0)
                    {
                        random *= -0.3f;
                    }

                    random = random * 3.0f - 2.0f;

                    if (random < 0)
                    {
                        random *= 0.5f;

                        if (random < -1)
                        {
                            random = -1f;
                        }

                        random /= 1.4f;
                        random /= 2.0f;
                    }
                    else
                    {
                        if (random > 1)
                        {
                            random = 1f;
                        }

                        random *= 0.125f;
                    }

                    float groundYOffset1 = groundYOffset;
                    float scale1         = scale;

                    // groundYOffset 有 -0.072 ~ 0.025 的变动量
                    groundYOffset1 = groundYOffset1 + random * 0.2f;
                    groundYOffset1 = groundYOffset1 * BaseSize / 8.0f;

                    // 这个是大概的地面 y 坐标
                    float groundY = BaseSize + groundYOffset1 * 4.0f; // baseSize = 8.5,应该代表了平均地表高度 68

                    // 注意这个 y * 8 才是最终的y坐标
                    for (int y = 0; y < 33; y++)
                    {
                        // result 偏移量,这个是负数则趋向固体,是正数则趋向液体和空气
                        float offset = (y - groundY) * StretchY * 128.0f / 256.0f / scale1; // scale 大概在 0.1 ~ 0.2 这样...

                        if (offset < 0)
                        {
                            offset *= 4f;
                        }

                        // 并不保证 lowerLimit < upperLimit,不过没有影响
                        float lowerLimit = (context.MinLimitMap[x1, y, z1] - 0.5f) * 160000 / LowerLimitScale; // lowerLimitScale = 512
                        float upperLimit = (context.MaxLimitMap[x1, y, z1] - 0.5f) * 160000 / UpperLimitScale; // upperLimitScale = 512
                        float t          = ((context.MainNoiseMap[x1, y, z1] - 0.5f) * 160000 / 10.0f + 1.0f) / 2.0f;

                        // 这个函数 t < 0 则取 lowerLimit,t > 1 则取 upperLimit,否则以 t 为参数在上下限间线性插值
                        float result = Mathf.Lerp(lowerLimit, upperLimit, t) - offset;

                        // y = 30 ~ 32
                        if (y > 29)
                        {
                            // 在原 result 和 -10 之间线性插值,这样 y > 240 的方块就会越来越少,最后全变成空气
                            float t2 = (float)(y - 29) / 3f;
                            result = result * (1f - t2) + -10f * t2;
                        }

                        context.DensityMap[x1, y, z1] = (float)result;
                    }
                }
            }
        }