Minecraft的世界生成过程(二)生物群系

终于看到生成区块的代码了,接下来比较复杂,分成几篇文章吧

本篇内容是生物群系的算法

生成生物群系总流程

接着上篇文章我们看到这个函数

类名net.minecraft.world.gen.ChunkProviderGenerate

    /**
     * Will return back a chunk, if it doesn't exist and its not a MP client it will generates all the blocks for the
     * specified chunk from the map seed and chunk seed
     */
    public Chunk provideChunk(int x, int z)
    {
        // 根据区块坐标设置随机种子
        this.rand.setSeed((long)x * 341873128712L + (long)z * 132897987541L);
        // 这个是生成区块时临时储存方块数据的对象,后面会转为Chunk对象
        ChunkPrimer chunkprimer = new ChunkPrimer();
        // 生成基本地形(没有洞穴等建筑)
        this.setBlocksInChunk(x, z, chunkprimer);
        // ...
    }

    public void setBlocksInChunk(int x, int z, ChunkPrimer chunkprimer)
    {
        // 决定生物群系,这里把区块坐标*4-2了,而且结果是10*10的
        this.biomesForGeneration = this.worldObj.getWorldChunkManager().getBiomesForGeneration(this.biomesForGeneration, x * 4 - 2, z * 4 - 2, 10, 10);
        // ...
    }

类名net.minecraft.world.biome.WorldChunkManager

    /**
     * Returns an array of biomes for the location input.
     */
    public BiomeGenBase[] getBiomesForGeneration(BiomeGenBase[] result, int x, int z, int width, int height)
    {
        IntCache.resetIntCache();

        if (result == null || result.length < width * height)
        {
            result = new BiomeGenBase[width * height];
        }

        // 生成生物群系ID
        int[] biomeId = this.genBiomes.getInts(x, z, width, height);

        try
        {
            for (int i = 0; i < width * height; ++i)
            {
                // 把生物群系ID转成BiomeGenBase对象
                result[i] = BiomeGenBase.getBiomeFromBiomeList(biomeId[i], BiomeGenBase.field_180279_ad);
            }

            return result;
        }
        catch (Throwable throwable)
        {
            // ...
        }
    }

    public WorldChunkManager(long seed, WorldType p_i45744_3_, String p_i45744_4_)
    {
        this();
        this.field_180301_f = p_i45744_4_;
        GenLayer[] agenlayer = GenLayer.initializeAllBiomeGenerators(seed, p_i45744_3_, p_i45744_4_);
        agenlayer = getModdedBiomeGenerators(p_i45744_3_, seed, agenlayer);
        // 这里初始化了genBiomes
        this.genBiomes = agenlayer[0];
        this.biomeIndexLayer = agenlayer[1];
    }

接下来就非常复杂了,net.minecraft.world.gen.layer这个包里有很多GenLayer,每层都会用上一层的输出生成这一层的输出

Minecraft的世界生成过程(二)生物群系_第1张图片
Minecraft的世界生成过程(二)生物群系_第2张图片

它们的初始化函数如下,最后的genlayerrivermix就是用来生成生物群系的

类名net.minecraft.world.gen.layer.GenLayer

    public static GenLayer[] initializeAllBiomeGenerators(long worldSeed, WorldType worldType, String settings)
    {
        GenLayer genlayer = new GenLayerIsland(1L);
        genlayer = new GenLayerFuzzyZoom(2000L, genlayer);
        GenLayerAddIsland genlayeraddisland = new GenLayerAddIsland(1L, genlayer);
        GenLayerZoom genlayerzoom = new GenLayerZoom(2001L, genlayeraddisland);
        GenLayerAddIsland genlayeraddisland1 = new GenLayerAddIsland(2L, genlayerzoom);
        genlayeraddisland1 = new GenLayerAddIsland(50L, genlayeraddisland1);
        genlayeraddisland1 = new GenLayerAddIsland(70L, genlayeraddisland1);
        GenLayerRemoveTooMuchOcean genlayerremovetoomuchocean = new GenLayerRemoveTooMuchOcean(2L, genlayeraddisland1);
        GenLayerAddSnow genlayeraddsnow = new GenLayerAddSnow(2L, genlayerremovetoomuchocean);
        GenLayerAddIsland genlayeraddisland2 = new GenLayerAddIsland(3L, genlayeraddsnow);
        GenLayerEdge genlayeredge = new GenLayerEdge(2L, genlayeraddisland2, GenLayerEdge.Mode.COOL_WARM);
        genlayeredge = new GenLayerEdge(2L, genlayeredge, GenLayerEdge.Mode.HEAT_ICE);
        genlayeredge = new GenLayerEdge(3L, genlayeredge, GenLayerEdge.Mode.SPECIAL);
        GenLayerZoom genlayerzoom1 = new GenLayerZoom(2002L, genlayeredge);
        genlayerzoom1 = new GenLayerZoom(2003L, genlayerzoom1);
        GenLayerAddIsland genlayeraddisland3 = new GenLayerAddIsland(4L, genlayerzoom1);
        GenLayerAddMushroomIsland genlayeraddmushroomisland = new GenLayerAddMushroomIsland(5L, genlayeraddisland3);
        GenLayerDeepOcean genlayerdeepocean = new GenLayerDeepOcean(4L, genlayeraddmushroomisland);
        GenLayer genlayer4 = GenLayerZoom.magnify(1000L, genlayerdeepocean, 0);
        ChunkProviderSettings chunkprovidersettings = null;
        int biomeSize = 4;
        int riverSize = biomeSize;

        if (worldType == WorldType.CUSTOMIZED && settings.length() > 0)
        {
            chunkprovidersettings = ChunkProviderSettings.Factory.jsonToFactory(settings).func_177864_b();
            biomeSize = chunkprovidersettings.biomeSize;
            riverSize = chunkprovidersettings.riverSize;
        }

        if (worldType == WorldType.LARGE_BIOMES)
        {
            biomeSize = 6;
        }

        biomeSize = getModdedBiomeSize(worldType, biomeSize);

        GenLayer lvt_8_1_ = GenLayerZoom.magnify(1000L, genlayer4, 0);
        GenLayerRiverInit genlayerriverinit = new GenLayerRiverInit(100L, lvt_8_1_);
        GenLayer lvt_10_1_ = GenLayerZoom.magnify(1000L, genlayerriverinit, 2);
        GenLayer genlayerbiomeedge = worldType.getBiomeLayer(worldSeed, genlayer4, settings);
        GenLayer genlayerhills = new GenLayerHills(1000L, genlayerbiomeedge, lvt_10_1_);
        GenLayer genlayer5 = GenLayerZoom.magnify(1000L, genlayerriverinit, 2);
        genlayer5 = GenLayerZoom.magnify(1000L, genlayer5, riverSize);
        GenLayerRiver genlayerriver = new GenLayerRiver(1L, genlayer5);
        GenLayerSmooth genlayersmooth = new GenLayerSmooth(1000L, genlayerriver);
        genlayerhills = new GenLayerRareBiome(1001L, genlayerhills);

        for (int i = 0; i < biomeSize; ++i)
        {
            genlayerhills = new GenLayerZoom((long)(1000 + i), genlayerhills);

            if (i == 0)
            {
                genlayerhills = new GenLayerAddIsland(3L, genlayerhills);
            }

            if (i == 1 || biomeSize == 1)
            {
                genlayerhills = new GenLayerShore(1000L, genlayerhills);
            }
        }

        GenLayerSmooth genlayersmooth1 = new GenLayerSmooth(1000L, genlayerhills);
        GenLayerRiverMix genlayerrivermix = new GenLayerRiverMix(100L, genlayersmooth1, genlayersmooth);
        GenLayer genlayer3 = new GenLayerVoronoiZoom(10L, genlayerrivermix);
        genlayerrivermix.initWorldGenSeed(worldSeed);
        genlayer3.initWorldGenSeed(worldSeed);
        return new GenLayer[] {genlayerrivermix, genlayer3, genlayerrivermix};
    }

各层GenLayer

GenLayer生成的就是生物群系ID,对应的生物群系可以在net.minecraft.world.biome.BiomeGenBase查看。每个GenLayer有3个种子,baseSeed初始化时指定,worldGenSeed世界种子,chunkSeed计算时根据坐标计算。还有一个parent层,初始化时指定

GenLayerIsland

这个是最底层,很简单,随机生成1和0(平原和海洋)

    /**
     * Returns a list of integer values generated by this layer. These may be interpreted as temperatures, rainfall
     * amounts, or biomeList[] indices based on the particular GenLayer subclass.
     */
    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        // IntCache用来避免反复分配内存,提高性能,后面还会看到很多次
        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        for (int y = 0; y < areaHeight; ++y)
        {
            for (int x = 0; x < areaWidth; ++x)
            {
                this.initChunkSeed((long)(areaX + x), (long)(areaY + y));
                // 1/10的概率为1,其他为0
                result[x + y * areaWidth] = this.nextInt(10) == 0 ? 1 : 0;
            }
        }

        if (-areaWidth < areaX && areaX <= 0 && -areaHeight < areaY && areaY <= 0)
        {
            result[-areaX - areaY * areaWidth] = 1;
        }

        return result;
    }

    // 以下两个函数是基类(GenLayer)的,以后会经常用到

    /**
     * Initialize layer's current chunkSeed based on the local worldGenSeed and the (x,z) chunk coordinates.
     */
    public void initChunkSeed(long x, long y)
    {
        this.chunkSeed = this.worldGenSeed;
        this.chunkSeed *= this.chunkSeed * 6364136223846793005L + 1442695040888963407L;
        this.chunkSeed += x;
        this.chunkSeed *= this.chunkSeed * 6364136223846793005L + 1442695040888963407L;
        this.chunkSeed += y;
        this.chunkSeed *= this.chunkSeed * 6364136223846793005L + 1442695040888963407L;
        this.chunkSeed += x;
        this.chunkSeed *= this.chunkSeed * 6364136223846793005L + 1442695040888963407L;
        this.chunkSeed += y;
    }

    /**
     * returns a LCG pseudo random number from [0, x). Args: int x
     */
    protected int nextInt(int upperLimit)
    {
        int i = (int)((this.chunkSeed >> 24) % (long)upperLimit);

        if (i < 0)
        {
            i += upperLimit;
        }

        this.chunkSeed *= this.chunkSeed * 6364136223846793005L + 1442695040888963407L;
        this.chunkSeed += this.worldGenSeed;
        return i;
    }

GenLayerZoom、GenLayerFuzzZoom

这层作用是把上一层结果放大,采样方式是在附近4个点随机采样

    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        // parent尺度是本层的1/2
        int parentAreaX = areaX / 2;
        int parentAreaY = areaY / 2;
        // +2添加边界
        int parentWidth  = areaWidth  / 2 + 2;
        int parentHeight = areaHeight / 2 + 2;
        // parentRes是本层的1/4
        int[] parentRes = this.parent.getInts(parentAreaX, parentAreaY, parentWidth, parentHeight);
        int tmpWidth  = (parentWidth  - 1) * 2;
        int tmpHeight = (parentHeight - 1) * 2;
        // 临时结果
        int[] tmp = IntCache.getIntCache(tmpWidth * tmpHeight);

        for (int parentY = 0; parentY < parentHeight - 1; ++parentY)
        {
            // tmp中当前点索引
            int tmpIndex = (parentY * 2) * tmpWidth;
            // parent当前点的值
            int parentValue   = parentRes[ parentY      * parentWidth];
            // parent当前点y+1点的值
            int parentValueY1 = parentRes[(parentY + 1) * parentWidth];

            for (int parentX = 0; parentX < parentWidth - 1; ++parentX)
            {
                this.initChunkSeed((parentX + parentAreaX) * 2, (parentY + parentAreaY) * 2);
                // parent当前点x+1点的值
                int parentValueX1   = parentRes[parentX + 1 +  parentY      * parentWidth];
                // parent当前点x+1, y+1点的值
                int parentValueX1Y1 = parentRes[parentX + 1 + (parentY + 1) * parentWidth];

                // 当前点值 = parent点值
                tmp[tmpIndex] = parentValue;
                // 当前点y+1值 = 在 parent点、parent点y+1 中随机选
                tmp[tmpIndex + tmpWidth] = this.selectRandom(new int[] {parentValue, parentValueY1});
                // 当前点移动x+1
                ++tmpIndex;

                // 当前点值 = 在 parent点、parent点x+1 中随机选
                tmp[tmpIndex] = this.selectRandom(new int[] {parentValue, parentValueX1});
                // 当前点y+1值 = parent四个点值中的众数或随机选
                tmp[tmpIndex + tmpWidth] = this.selectModeOrRandom(parentValue, parentValueX1, parentValueY1, parentValueX1Y1);
                // 当前点移动x+1
                ++tmpIndex;

                // parent当前点移动x+1
                parentValue = parentValueX1;
                parentValueY1 = parentValueX1Y1;
            }
        }

        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        // tmp和result尺寸可能不同,这里把tmp左上角部分复制到result
        for (int resultY = 0; resultY < areaHeight; ++resultY)
        {
            System.arraycopy(tmp, (resultY + areaY % 2) * tmpWidth + areaX % 2, result, resultY * areaWidth, areaWidth);
        }

        return result;
    }

GenLayerAddIsland

从名字来看貌似是用来添加岛屿的

    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        int parentAreaX = areaX - 1;
        int parentAreaY = areaY - 1;
        int parentWidth = areaWidth + 2;
        int parentHeight = areaHeight + 2;
        int[] parentRes = this.parent.getInts(parentAreaX, parentAreaY, parentWidth, parentHeight);
        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        for (int y = 0; y < areaHeight; ++y)
        {
            for (int x = 0; x < areaWidth; ++x)
            {
                // 以x+1 y+1为中心,X型采样5个点
                int parentValue     = parentRes[x     +  y      * parentWidth];
                int parentValueX2   = parentRes[x + 2 +  y      * parentWidth];
                int parentValueY2   = parentRes[x     + (y + 2) * parentWidth];
                int parentValueX2Y2 = parentRes[x + 2 + (y + 2) * parentWidth];
                int parentValueX1Y1 = parentRes[x + 1 + (y + 1) * parentWidth];
                this.initChunkSeed(x + areaX, y + areaY);

                // 中心不为0 或 周围全是0
                if (parentValueX1Y1 != 0 || (parentValue == 0 && parentValueX2 == 0 && parentValueY2 == 0 && parentValueX2Y2 == 0))
                {
                    // 中心>0 且 周围出现了0
                    if (parentValueX1Y1 > 0 && (parentValue == 0 || parentValueX2 == 0 || parentValueY2 == 0 || parentValueX2Y2 == 0))
                    {
                        // 1/5概率变为海洋
                        if (this.nextInt(5) == 0)
                        {
                            // 中心是森林则不变为海洋
                            if (parentValueX1Y1 == 4)
                            {
                                result[x + y * areaWidth] = 4;
                            }
                            else
                            {
                                result[x + y * areaWidth] = 0;
                            }
                        }
                        else
                        {
                            result[x + y * areaWidth] = parentValueX1Y1;
                        }
                    }
                    else
                    {
                        result[x + y * areaWidth] = parentValueX1Y1;
                    }
                }
                else
                {
                    // 概率中的分母
                    int deno = 1;
                    int value = 1;

                    // 选择一个不为0的值,越往后重新选的概率越小

                    if (parentValue != 0 && this.nextInt(deno++) == 0)
                    {
                        value = parentValue;
                    }

                    if (parentValueX2 != 0 && this.nextInt(deno++) == 0)
                    {
                        value = parentValueX2;
                    }

                    if (parentValueY2 != 0 && this.nextInt(deno++) == 0)
                    {
                        value = parentValueY2;
                    }

                    if (parentValueX2Y2 != 0 && this.nextInt(deno++) == 0)
                    {
                        value = parentValueX2Y2;
                    }

                    // 1/3的概率设置为刚才选的值
                    if (this.nextInt(3) == 0)
                    {
                        result[x + y * areaWidth] = value;
                    }
                    else if (value == 4) // 森林
                    {
                        result[x + y * areaWidth] = 4;
                    }
                    else
                    {
                        result[x + y * areaWidth] = 0;
                    }
                }
            }
        }

        return result;
    }

GenLayerRemoveTooMuchOcean

从名字来看貌似是用来减少海洋的

    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        int parentAreaX = areaX - 1;
        int parentAreaY = areaY - 1;
        int parentWidth = areaWidth + 2;
        int parentHeihgt = areaHeight + 2;
        int[] parentRes = this.parent.getInts(parentAreaX, parentAreaY, parentWidth, parentHeihgt);
        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        for (int y = 0; y < areaHeight; ++y)
        {
            for (int x = 0; x < areaWidth; ++x)
            {
                // 以x+1 y+1为中心,十字型采样5个点
                int parentValueX1   = parentRes[x + 1 +  y      * parentWidth];
                int parentValueX2Y1 = parentRes[x + 2 + (y + 1) * parentWidth];
                int parentValueY1   = parentRes[x     + (y + 1) * parentWidth];
                int parentValueX1Y2 = parentRes[x + 1 + (y + 2) * parentWidth];
                int parentValueX1Y1 = parentRes[x + 1 + (y + 1) * parentWidth];

                // 先取中心的值
                result[x + y * areaWidth] = parentValueX1Y1;
                this.initChunkSeed(x + areaX, y + areaY);
                if (parentValueX1Y1 == 0 && parentValueX1 == 0 && parentValueX2Y1 == 0 && parentValueY1 == 0 && parentValueX1Y2 == 0 && this.nextInt(2) == 0)
                {
                    // 如果5个点全是0,有1/2概率取1
                    result[x + y * areaWidth] = 1;
                }
            }
        }

        return result;
    }

GenLayerAddSnow

从名字来看貌似是用来添加雪的(但是好像没有看到雪原的ID?

    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        int parentAreaX = areaX - 1;
        int parentAreaY = areaY - 1;
        int parentWidth = areaWidth + 2;
        int parentHeight = areaHeight + 2;
        int[] parentRes = this.parent.getInts(parentAreaX, parentAreaY, parentWidth, parentHeight);
        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        for (int y = 0; y < areaHeight; ++y)
        {
            for (int x = 0; x < areaWidth; ++x)
            {
                int parentValueX1Y1 = parentRes[x + 1 + (y + 1) * parentWidth];
                this.initChunkSeed(x + areaX, y + areaY);

                // 是海洋
                if (parentValueX1Y1 == 0)
                {
                    result[x + y * areaWidth] = 0;
                }
                else
                {
                    int value = this.nextInt(6);

                    if (value == 0)
                    {
                        // 0则取森林
                        value = 4;
                    }
                    else if (value <= 1)
                    {
                        // 1则取高山
                        value = 3;
                    }
                    else
                    {
                        // 其他取平原
                        value = 1;
                    }

                    result[x + y * areaWidth] = value;
                }
            }
        }

        return result;
    }

GenLayerEdge

这个有3种算法,初始化时指定(为什么不用3个子类…

    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        switch (this.field_151627_c)
        {
            case COOL_WARM:
            default:
                return this.getIntsCoolWarm(areaX, areaY, areaWidth, areaHeight);
            case HEAT_ICE:
                return this.getIntsHeatIce(areaX, areaY, areaWidth, areaHeight);
            case SPECIAL:
                return this.getIntsSpecial(areaX, areaY, areaWidth, areaHeight);
        }
    }

    private int[] getIntsCoolWarm(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        int parentAreaX = areaX - 1;
        int parentAreaY = areaY - 1;
        int parentWidth = areaWidth + 2;
        int parentHeight = areaHeight + 2;
        int[] parentRes = this.parent.getInts(parentAreaX, parentAreaY, parentWidth, parentHeight);
        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        for (int y = 0; y < areaHeight; ++y)
        {
            for (int x = 0; x < areaWidth; ++x)
            {
                this.initChunkSeed(x + areaX, y + areaY);

                // 以x+1 y+1为中心,十字型采样5个点
                int parentValueX1Y1 = parentRes[x + 1 + (y + 1) * parentWidth];
                // 中心是平原
                if (parentValueX1Y1 == 1)
                {
                    int parentValueX1   = parentRes[x + 1 +  y      * parentWidth];
                    int parentValueX2Y1 = parentRes[x + 2 + (y + 1) * parentWidth];
                    int parentValueY1   = parentRes[x     + (y + 1) * parentWidth];
                    int parentValueX1Y2 = parentRes[x + 1 + (y + 2) * parentWidth];
                    boolean isHill = parentValueX1 == 3 || parentValueX2Y1 == 3 || parentValueY1 == 3 || parentValueX1Y2 == 3;
                    boolean isForest = parentValueX1 == 4 || parentValueX2Y1 == 4 || parentValueY1 == 4 || parentValueX1Y2 == 4;

                    // 周围有高山或森林则取沙漠
                    if (isHill || isForest)
                    {
                        parentValueX1Y1 = 2;
                    }
                }

                result[x + y * areaWidth] = parentValueX1Y1;
            }
        }

        return result;
    }

    private int[] getIntsHeatIce(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        int parentAreaX = areaX - 1;
        int parentAreaY = areaY - 1;
        int parentWidth = areaWidth + 2;
        int parentHeight = areaHeight + 2;
        int[] parentRes = this.parent.getInts(parentAreaX, parentAreaY, parentWidth, parentHeight);
        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        for (int y = 0; y < areaHeight; ++y)
        {
            for (int x = 0; x < areaWidth; ++x)
            {
                // 以x+1 y+1为中心,十字型采样5个点
                int parentValueX1Y1 = parentRes[x + 1 + (y + 1) * parentWidth];
                // 中心是森林
                if (parentValueX1Y1 == 4)
                {
                    int parentValueX1   = parentRes[x + 1 +  y      * parentWidth];
                    int parentValueX2Y1 = parentRes[x + 2 + (y + 1) * parentWidth];
                    int parentValueY1   = parentRes[x     + (y + 1) * parentWidth];
                    int parentValueX1Y2 = parentRes[x + 1 + (y + 2) * parentWidth];
                    boolean isDesert = parentValueX1 == 2 || parentValueX2Y1 == 2 || parentValueY1 == 2 || parentValueX1Y2 == 2;
                    boolean isPlain = parentValueX1 == 1 || parentValueX2Y1 == 1 || parentValueY1 == 1 || parentValueX1Y2 == 1;

                    // 周围有平原或沙漠则取高山
                    if (isPlain || isDesert)
                    {
                        parentValueX1Y1 = 3;
                    }
                }

                result[x + y * areaWidth] = parentValueX1Y1;
            }
        }

        return result;
    }

    private int[] getIntsSpecial(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        int[] parentRes = this.parent.getInts(areaX, areaY, areaWidth, areaHeight);
        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        for (int y = 0; y < areaHeight; ++y)
        {
            for (int x = 0; x < areaWidth; ++x)
            {
                this.initChunkSeed(x + areaX, y + areaY);
                int parentValue = parentRes[x + y * areaWidth];

                if (parentValue != 0 && this.nextInt(13) == 0)
                {
                    // 随机生成1~15,储存在bit8~11,后面GenLayerBiome会用到
                    parentValue |= (1 + this.nextInt(15)) << 8 & 0x0F00;
                }

                result[x + y * areaWidth] = parentValue;
            }
        }

        return result;
    }

GenLayerAddMushroomIsland

从名字来看貌似是用来添加蘑菇岛的

    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        int parentAreaX = areaX - 1;
        int parentAreaY = areaY - 1;
        int parentWidth = areaWidth + 2;
        int parentHeight = areaHeight + 2;
        int[] parentRes = this.parent.getInts(parentAreaX, parentAreaY, parentWidth, parentHeight);
        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        for (int y = 0; y < areaHeight; ++y)
        {
            for (int x = 0; x < areaWidth; ++x)
            {
                // 以x+1 y+1为中心,X型采样5个点
                int parentValue     = parentRes[x     +  y      * parentWidth];
                int parentValueX2   = parentRes[x + 2 +  y      * parentWidth];
                int parentValueY2   = parentRes[x     + (y + 2) * parentWidth];
                int parentValueX2Y2 = parentRes[x + 2 + (y + 2) * parentWidth];
                int parentValueX1Y1 = parentRes[x + 1 + (y + 1) * parentWidth];
                this.initChunkSeed(x + areaX, y + areaY);

                // 如果全是海洋,有1/100概率变成蘑菇岛
                if (parentValueX1Y1 == 0 && parentValue == 0 && parentValueX2 == 0 && parentValueY2 == 0 && parentValueX2Y2 == 0 && this.nextInt(100) == 0)
                {
                    result[x + y * areaWidth] = BiomeGenBase.mushroomIsland.biomeID;
                }
                else
                {
                    result[x + y * areaWidth] = parentValueX1Y1;
                }
            }
        }

        return result;
    }

GenLayerDeepOcean

从名字来看貌似是用来添加深海的

    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        int parentAreaX = areaX - 1;
        int parentAreaY = areaY - 1;
        int parentWidth = areaWidth + 2;
        int parentHeight = areaHeight + 2;
        int[] parentRes = this.parent.getInts(parentAreaX, parentAreaY, parentWidth, parentHeight);
        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        for (int y = 0; y < areaHeight; ++y)
        {
            for (int x = 0; x < areaWidth; ++x)
            {
                // 以x+1 y+1为中心,十字型采样5个点
                int parentValueX1   = parentRes[x + 1 +  y      * parentWidth];
                int parentValueX2Y1 = parentRes[x + 2 + (y + 1) * parentWidth];
                int parentValueY1   = parentRes[x     + (y + 1) * parentWidth];
                int parentValueX1Y2 = parentRes[x + 1 + (y + 2) * parentWidth];
                int parentValueX1Y1 = parentRes[x + 1 + (y + 1) * parentWidth];

                int oceanCount = 0;

                if (parentValueX1 == 0)
                {
                    ++oceanCount;
                }

                if (parentValueX2Y1 == 0)
                {
                    ++oceanCount;
                }

                if (parentValueY1 == 0)
                {
                    ++oceanCount;
                }

                if (parentValueX1Y2 == 0)
                {
                    ++oceanCount;
                }

                // 全是海洋则生成深海
                if (parentValueX1Y1 == 0 && oceanCount > 3)
                {
                    result[x + y * areaWidth] = BiomeGenBase.deepOcean.biomeID;
                }
                else
                {
                    result[x + y * areaWidth] = parentValueX1Y1;
                }
            }
        }

        return result;
    }

GenLayerBiome

这个貌似是把基本群系扩展成更多群系

    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        int[] parentRes = this.parent.getInts(areaX, areaY, areaWidth, areaHeight);
        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        for (int y = 0; y < areaHeight; ++y)
        {
            for (int x = 0; x < areaWidth; ++x)
            {
                this.initChunkSeed(x + areaX, y + areaY);
                int parentValue = parentRes[x + y * areaWidth];
                // 取bit8~11储存的信息,由GenLayerEdge.getIntsSpecial生成
                int info = (parentValue & 0x0F00) >> 8;
                // 去掉bit8~11储存的信息
                parentValue = parentValue & ~0x0F00;

                // field_175973_g是区块设置,只有自定义世界时不为null
                if (this.field_175973_g != null && this.field_175973_g.fixedBiome >= 0)
                {
                    result[x + y * areaWidth] = this.field_175973_g.fixedBiome;
                }
                else if (isBiomeOceanic(parentValue)) // 海洋
                {
                    result[x + y * areaWidth] = parentValue;
                }
                else if (parentValue == BiomeGenBase.mushroomIsland.biomeID) // 蘑菇岛
                {
                    result[x + y * areaWidth] = parentValue;
                }
                else if (parentValue == 1) // 平原
                {
                    if (info > 0)
                    {
                        // 生成高原
                        if (this.nextInt(3) == 0)
                        {
                            result[x + y * areaWidth] = BiomeGenBase.mesaPlateau.biomeID;
                        }
                        else
                        {
                            result[x + y * areaWidth] = BiomeGenBase.mesaPlateau_F.biomeID;
                        }
                    }
                    else
                    {
                        // 这个是加权随机取,权重见GenLayerBiome构造函数
                        result[x + y * areaWidth] = getWeightedBiomeEntry(net.minecraftforge.common.BiomeManager.BiomeType.DESERT).biome.biomeID;
                    }
                }
                else if (parentValue == 2) // 沙漠
                {
                    if (info > 0)
                    {
                        // 生成丛林
                        result[x + y * areaWidth] = BiomeGenBase.jungle.biomeID;
                    }
                    else
                    {
                        result[x + y * areaWidth] = getWeightedBiomeEntry(net.minecraftforge.common.BiomeManager.BiomeType.WARM).biome.biomeID;
                    }
                }
                else if (parentValue == 3) // 高山
                {
                    if (info > 0)
                    {
                        // 生成针叶林
                        result[x + y * areaWidth] = BiomeGenBase.megaTaiga.biomeID;
                    }
                    else
                    {
                        result[x + y * areaWidth] = getWeightedBiomeEntry(net.minecraftforge.common.BiomeManager.BiomeType.COOL).biome.biomeID;
                    }
                }
                else if (parentValue == 4) // 森林
                {
                    result[x + y * areaWidth] = getWeightedBiomeEntry(net.minecraftforge.common.BiomeManager.BiomeType.ICY).biome.biomeID;
                }
                else
                {
                    result[x + y * areaWidth] = BiomeGenBase.mushroomIsland.biomeID;
                }
            }
        }

        return result;
    }

GenLayerBiomeEdge

用来给生物群系加上边界和过渡

    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        int[] parentRes = this.parent.getInts(areaX - 1, areaY - 1, areaWidth + 2, areaHeight + 2);
        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        for (int y = 0; y < areaHeight; ++y)
        {
            for (int x = 0; x < areaWidth; ++x)
            {
                this.initChunkSeed(x + areaX, y + areaY);
                int parentValueX1Y1 = parentRes[x + 1 + (y + 1) * (areaWidth + 2)];

                if (   !this.replaceBiomeEdgeIfNecessary(parentRes, result, x, y, areaWidth, parentValueX1Y1, BiomeGenBase.extremeHills.biomeID, BiomeGenBase.extremeHillsEdge.biomeID)
                    && !this.replaceBiomeEdge(parentRes, result, x, y, areaWidth, parentValueX1Y1, BiomeGenBase.mesaPlateau_F.biomeID, BiomeGenBase.mesa.biomeID)
                    && !this.replaceBiomeEdge(parentRes, result, x, y, areaWidth, parentValueX1Y1, BiomeGenBase.mesaPlateau.biomeID, BiomeGenBase.mesa.biomeID)
                    && !this.replaceBiomeEdge(parentRes, result, x, y, areaWidth, parentValueX1Y1, BiomeGenBase.megaTaiga.biomeID, BiomeGenBase.taiga.biomeID))
                {
                    if (parentValueX1Y1 == BiomeGenBase.desert.biomeID)
                    {
                        // 以x+1 y+1为中心,十字型采样5个点
                        int parentValueX1   = parentRes[x + 1 +  y      * (areaWidth + 2)];
                        int parentValueX2Y1 = parentRes[x + 2 + (y + 1) * (areaWidth + 2)];
                        int parentValueY1   = parentRes[x     + (y + 1) * (areaWidth + 2)];
                        int parentValueX1Y2 = parentRes[x + 1 + (y + 2) * (areaWidth + 2)];

                        if (   parentValueX1   != BiomeGenBase.icePlains.biomeID
                            && parentValueX2Y1 != BiomeGenBase.icePlains.biomeID
                            && parentValueY1   != BiomeGenBase.icePlains.biomeID
                            && parentValueX1Y2 != BiomeGenBase.icePlains.biomeID)
                        {
                            result[x + y * areaWidth] = parentValueX1Y1;
                        }
                        else
                        {
                            result[x + y * areaWidth] = BiomeGenBase.extremeHillsPlus.biomeID;
                        }
                    }
                    else if (parentValueX1Y1 == BiomeGenBase.swampland.biomeID)
                    {
                        // 以x+1 y+1为中心,十字型采样5个点
                        int parentValueX1   = parentRes[x + 1 +  y      * (areaWidth + 2)];
                        int parentValueX2Y1 = parentRes[x + 2 + (y + 1) * (areaWidth + 2)];
                        int parentValueY1   = parentRes[x     + (y + 1) * (areaWidth + 2)];
                        int parentValueX1Y2 = parentRes[x + 1 + (y + 2) * (areaWidth + 2)];

                        if (   parentValueX1   != BiomeGenBase.desert.biomeID
                            && parentValueX2Y1 != BiomeGenBase.desert.biomeID
                            && parentValueY1   != BiomeGenBase.desert.biomeID
                            && parentValueX1Y2 != BiomeGenBase.desert.biomeID
                            && parentValueX1   != BiomeGenBase.coldTaiga.biomeID
                            && parentValueX2Y1 != BiomeGenBase.coldTaiga.biomeID
                            && parentValueY1   != BiomeGenBase.coldTaiga.biomeID
                            && parentValueX1Y2 != BiomeGenBase.coldTaiga.biomeID
                            && parentValueX1   != BiomeGenBase.icePlains.biomeID
                            && parentValueX2Y1 != BiomeGenBase.icePlains.biomeID
                            && parentValueY1   != BiomeGenBase.icePlains.biomeID
                            && parentValueX1Y2 != BiomeGenBase.icePlains.biomeID)
                        {
                            if (   parentValueX1   != BiomeGenBase.jungle.biomeID
                                && parentValueX1Y2 != BiomeGenBase.jungle.biomeID
                                && parentValueX2Y1 != BiomeGenBase.jungle.biomeID
                                && parentValueY1   != BiomeGenBase.jungle.biomeID)
                            {
                                result[x + y * areaWidth] = parentValueX1Y1;
                            }
                            else
                            {
                                result[x + y * areaWidth] = BiomeGenBase.jungleEdge.biomeID;
                            }
                        }
                        else
                        {
                            result[x + y * areaWidth] = BiomeGenBase.plains.biomeID;
                        }
                    }
                    else
                    {
                        result[x + y * areaWidth] = parentValueX1Y1;
                    }
                }
            }
        }

        return result;
    }

    /**
     * Creates a border around a biome if necessary, e.g. A transition from hot to cold climates would otherwise occur.
     */
    private boolean replaceBiomeEdgeIfNecessary(int[] parentRes, int[] result, int x, int y, int areaWidth, int parentValueX1Y1, int oldBiome, int newBiome)
    {
        // 两生物群系相等或都是高原(高原有两种)则返回true
        if (!biomesEqualOrMesaPlateau(parentValueX1Y1, oldBiome))
        {
            // 返回生物群系是否相等
            return false;
        }
        else
        {
            int parentValueX1   = parentRes[x + 1 +  y      * (areaWidth + 2)];
            int parentValueX2Y1 = parentRes[x + 2 + (y + 1) * (areaWidth + 2)];
            int parentValueY1   = parentRes[x     + (y + 1) * (areaWidth + 2)];
            int parentValueX1Y2 = parentRes[x + 1 + (y + 2) * (areaWidth + 2)];

            if (   this.canBiomesBeNeighbors(parentValueX1, oldBiome)
                && this.canBiomesBeNeighbors(parentValueX2Y1, oldBiome)
                && this.canBiomesBeNeighbors(parentValueY1, oldBiome)
                && this.canBiomesBeNeighbors(parentValueX1Y2, oldBiome))
            {
                // 不需要过渡
                result[x + y * areaWidth] = parentValueX1Y1;
            }
            else
            {
                // 如果这个生物群系和周围的不能相邻则替换为newBiome(给边界做个过渡)
                result[x + y * areaWidth] = newBiome;
            }

            return true;
        }
    }

    /**
     * Creates a border around a biome.
     */
    private boolean replaceBiomeEdge(int[] parentRes, int[] result, int x, int y, int areaWidth, int parentValueX1Y1, int oldBiome, int newBiome)
    {
        if (parentValueX1Y1 != oldBiome)
        {
            // 返回生物群系是否相等
            return false;
        }
        else
        {
            int parentValueX1   = parentRes[x + 1 +  y      * (areaWidth + 2)];
            int parentValueX2Y1 = parentRes[x + 2 + (y + 1) * (areaWidth + 2)];
            int parentValueY1   = parentRes[x     + (y + 1) * (areaWidth + 2)];
            int parentValueX1Y2 = parentRes[x + 1 + (y + 2) * (areaWidth + 2)];

            if (   biomesEqualOrMesaPlateau(parentValueX1, oldBiome)
                && biomesEqualOrMesaPlateau(parentValueX2Y1, oldBiome)
                && biomesEqualOrMesaPlateau(parentValueY1, oldBiome)
                && biomesEqualOrMesaPlateau(parentValueX1Y2, oldBiome))
            {
                // 如果周围和中心相等则不变
                result[x + y * areaWidth] = parentValueX1Y1;
            }
            else
            {
                // 否则中心是边界上的点,替换为newBiome
                result[x + y * areaWidth] = newBiome;
            }

            return true;
        }
    }

    /**
     * Returns if two biomes can logically be neighbors. If one is hot and the other cold, for example, it returns
     * false.
     */
    private boolean canBiomesBeNeighbors(int biomeId1, int biomeId2)
    {
        if (biomesEqualOrMesaPlateau(biomeId1, biomeId2))
        {
            // 相等的生物群系当然可以相邻
            return true;
        }
        else
        {
            BiomeGenBase biome1 = BiomeGenBase.getBiome(biomeId1);
            BiomeGenBase biome2 = BiomeGenBase.getBiome(biomeId2);

            if (biome1 != null && biome2 != null)
            {
                BiomeGenBase.TempCategory biome1Temp = biome1.getTempCategory();
                BiomeGenBase.TempCategory biome2Temp = biome2.getTempCategory();
                // 温度相等或其中一个温度为中等才可以相邻
                return    biome1Temp == biome2Temp
                       || biome1Temp == BiomeGenBase.TempCategory.MEDIUM
                       || biome2Temp == BiomeGenBase.TempCategory.MEDIUM;
            }
            else
            {
                return false;
            }
        }
    }

GenLayerRiverInit

这个生成的不是生物群系ID,而是2~300000的随机数

    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        // parent是GenLayerDeepOcean
        int[] parentRes = this.parent.getInts(areaX, areaY, areaWidth, areaHeight);
        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        for (int y = 0; y < areaHeight; ++y)
        {
            for (int x = 0; x < areaWidth; ++x)
            {
                this.initChunkSeed(x + areaX, y + areaY);
                // parent不是海洋则生成2~300000的随机数
                result[x + y * areaWidth] = parentRes[x + y * areaWidth] > 0 ? this.nextInt(299999) + 2 : 0;
            }
        }

        return result;
    }

GenLayerHills

从名字来看貌似是用来添加山的

    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        int[] parentRes1 = this.parent.getInts(areaX - 1, areaY - 1, areaWidth + 2, areaHeight + 2);
        // field_151628_d是经过放大的GenLayerRiverInit
        int[] parentRes2 = this.field_151628_d.getInts(areaX - 1, areaY - 1, areaWidth + 2, areaHeight + 2);
        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        for (int y = 0; y < areaHeight; ++y)
        {
            for (int x = 0; x < areaWidth; ++x)
            {
                this.initChunkSeed(x + areaX, y + areaY);
                int parentValue1X1Y1 = parentRes1[x + 1 + (y + 1) * (areaWidth + 2)];
                int parentValue2X1Y1 = parentRes2[x + 1 + (y + 1) * (areaWidth + 2)];
                boolean flag = (parentValue2X1Y1 - 2) % 29 == 0; // 1/29的概率

                if (parentValue1X1Y1 > 255) // 旧版本?
                {
                    logger.debug("old! " + parentValue1X1Y1);
                }

                if (   parentValue1X1Y1 != 0 // parent1不是海洋
                    && parentValue2X1Y1 >= 2 // parent2是2~300000的随机数
                    && (parentValue2X1Y1 - 2) % 29 == 1 // 1/29的概率
                    && parentValue1X1Y1 < 128)
                {
                    // 生物群系ID+128是它的突变版,初始化见net.minecraft.world.biome.BiomeGenBase
                    // 658行开始的一堆createMutation()
                    if (BiomeGenBase.getBiome(parentValue1X1Y1 + 128) != null)
                    {
                        result[x + y * areaWidth] = parentValue1X1Y1 + 128;
                    }
                    else
                    {
                        result[x + y * areaWidth] = parentValue1X1Y1;
                    }
                }
                else if (this.nextInt(3) != 0 && !flag)
                {
                    // 1/3 * 1/29的概率不替换
                    result[x + y * areaWidth] = parentValue1X1Y1;
                }
                else
                {
                    int value = parentValue1X1Y1;

                    // 替换成对应生物群系的山

                    if (parentValue1X1Y1 == BiomeGenBase.desert.biomeID)
                    {
                        value = BiomeGenBase.desertHills.biomeID;
                    }
                    else if (parentValue1X1Y1 == BiomeGenBase.forest.biomeID)
                    {
                        value = BiomeGenBase.forestHills.biomeID;
                    }
                    else if (parentValue1X1Y1 == BiomeGenBase.birchForest.biomeID)
                    {
                        value = BiomeGenBase.birchForestHills.biomeID;
                    }
                    else if (parentValue1X1Y1 == BiomeGenBase.roofedForest.biomeID)
                    {
                        value = BiomeGenBase.plains.biomeID;
                    }
                    else if (parentValue1X1Y1 == BiomeGenBase.taiga.biomeID)
                    {
                        value = BiomeGenBase.taigaHills.biomeID;
                    }
                    else if (parentValue1X1Y1 == BiomeGenBase.megaTaiga.biomeID)
                    {
                        value = BiomeGenBase.megaTaigaHills.biomeID;
                    }
                    else if (parentValue1X1Y1 == BiomeGenBase.coldTaiga.biomeID)
                    {
                        value = BiomeGenBase.coldTaigaHills.biomeID;
                    }
                    else if (parentValue1X1Y1 == BiomeGenBase.plains.biomeID)
                    {
                        if (this.nextInt(3) == 0)
                        {
                            value = BiomeGenBase.forestHills.biomeID;
                        }
                        else
                        {
                            value = BiomeGenBase.forest.biomeID;
                        }
                    }
                    else if (parentValue1X1Y1 == BiomeGenBase.icePlains.biomeID)
                    {
                        value = BiomeGenBase.iceMountains.biomeID;
                    }
                    else if (parentValue1X1Y1 == BiomeGenBase.jungle.biomeID)
                    {
                        value = BiomeGenBase.jungleHills.biomeID;
                    }
                    else if (parentValue1X1Y1 == BiomeGenBase.ocean.biomeID)
                    {
                        value = BiomeGenBase.deepOcean.biomeID;
                    }
                    else if (parentValue1X1Y1 == BiomeGenBase.extremeHills.biomeID)
                    {
                        value = BiomeGenBase.extremeHillsPlus.biomeID;
                    }
                    else if (parentValue1X1Y1 == BiomeGenBase.savanna.biomeID)
                    {
                        value = BiomeGenBase.savannaPlateau.biomeID;
                    }
                    else if (biomesEqualOrMesaPlateau(parentValue1X1Y1, BiomeGenBase.mesaPlateau_F.biomeID))
                    {
                        value = BiomeGenBase.mesa.biomeID;
                    }
                    else if (parentValue1X1Y1 == BiomeGenBase.deepOcean.biomeID && this.nextInt(3) == 0)
                    {
                        if (this.nextInt(2) == 0)
                        {
                            value = BiomeGenBase.plains.biomeID;
                        }
                        else
                        {
                            value = BiomeGenBase.forest.biomeID;
                        }
                    }

                    if (flag && value != parentValue1X1Y1)
                    {
                        if (BiomeGenBase.getBiome(value + 128) != null)
                        {
                            value += 128;
                        }
                        else
                        {
                            value = parentValue1X1Y1;
                        }
                    }

                    if (value == parentValue1X1Y1)
                    {
                        result[x + y * areaWidth] = parentValue1X1Y1;
                    }
                    else
                    {
                        int parentValue1X1   = parentRes1[x + 1 +  y      * (areaWidth + 2)];
                        int parentValue1X2Y1 = parentRes1[x + 2 + (y + 1) * (areaWidth + 2)];
                        int parentValue1Y1   = parentRes1[x     + (y + 1) * (areaWidth + 2)];
                        int parentValue1X1Y2 = parentRes1[x + 1 + (y + 2) * (areaWidth + 2)];
                        int equalCount = 0;

                        if (biomesEqualOrMesaPlateau(parentValue1X1, parentValue1X1Y1))
                        {
                            ++equalCount;
                        }

                        if (biomesEqualOrMesaPlateau(parentValue1X2Y1, parentValue1X1Y1))
                        {
                            ++equalCount;
                        }

                        if (biomesEqualOrMesaPlateau(parentValue1Y1, parentValue1X1Y1))
                        {
                            ++equalCount;
                        }

                        if (biomesEqualOrMesaPlateau(parentValue1X1Y2, parentValue1X1Y1))
                        {
                            ++equalCount;
                        }

                        if (equalCount >= 3)
                        {
                            result[x + y * areaWidth] = value;
                        }
                        else
                        {
                            result[x + y * areaWidth] = parentValue1X1Y1;
                        }
                    }
                }
            }
        }

        return result;
    }

GenLayerRareBiome

这个用来生成突变版平原(看名字好像是太阳花平原?

    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        int[] parentRes = this.parent.getInts(areaX - 1, areaY - 1, areaWidth + 2, areaHeight + 2);
        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        for (int y = 0; y < areaHeight; ++y)
        {
            for (int x = 0; x < areaWidth; ++x)
            {
                this.initChunkSeed(x + areaX, y + areaY);
                int parentValueX1Y1 = parentRes[x + 1 + (y + 1) * (areaWidth + 2)];

                if (this.nextInt(57) == 0)
                {
                    if (parentValueX1Y1 == BiomeGenBase.plains.biomeID)
                    {
                        // 1/57的概率把平原变成突变版
                        result[x + y * areaWidth] = BiomeGenBase.plains.biomeID + 128;
                    }
                    else
                    {
                        result[x + y * areaWidth] = parentValueX1Y1;
                    }
                }
                else
                {
                    result[x + y * areaWidth] = parentValueX1Y1;
                }
            }
        }

        return result;
    }

GenLayerShore

用来生成陆地和海洋之间的沙滩

    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        int[] parentRes = this.parent.getInts(areaX - 1, areaY - 1, areaWidth + 2, areaHeight + 2);
        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        for (int y = 0; y < areaHeight; ++y)
        {
            for (int x = 0; x < areaWidth; ++x)
            {
                this.initChunkSeed(x + areaX, y + areaY);
                int parentValueX1Y1 = parentRes[x + 1 + (y + 1) * (areaWidth + 2)];
                BiomeGenBase biome = BiomeGenBase.getBiome(parentValueX1Y1);

                if (parentValueX1Y1 == BiomeGenBase.mushroomIsland.biomeID) // 蘑菇岛
                {
                    int parentValueX1   = parentRes[x + 1 +  y      * (areaWidth + 2)];
                    int parentValueX2Y1 = parentRes[x + 2 + (y + 1) * (areaWidth + 2)];
                    int parentValueY1   = parentRes[x     + (y + 1) * (areaWidth + 2)];
                    int parentValueX1Y2 = parentRes[x + 1 + (y + 2) * (areaWidth + 2)];

                    if (   parentValueX1   != BiomeGenBase.ocean.biomeID
                        && parentValueX2Y1 != BiomeGenBase.ocean.biomeID
                        && parentValueY1   != BiomeGenBase.ocean.biomeID
                        && parentValueX1Y2 != BiomeGenBase.ocean.biomeID)
                    {
                        result[x + y * areaWidth] = parentValueX1Y1;
                    }
                    else
                    {
                        // 如果是陆地和海洋边界则换为海滨,后同
                        result[x + y * areaWidth] = BiomeGenBase.mushroomIslandShore.biomeID;
                    }
                }
                else if (biome != null && biome.getBiomeClass() == BiomeGenJungle.class) // 丛林
                {
                    int parentValueX1   = parentRes[x + 1 +  y      * (areaWidth + 2)];
                    int parentValueX2Y1 = parentRes[x + 2 + (y + 1) * (areaWidth + 2)];
                    int parentValueY1   = parentRes[x     + (y + 1) * (areaWidth + 2)];
                    int parentValueX1Y2 = parentRes[x + 1 + (y + 2) * (areaWidth + 2)];

                    if (   this.func_151631_c(parentValueX1)
                        && this.func_151631_c(parentValueX2Y1)
                        && this.func_151631_c(parentValueY1)
                        && this.func_151631_c(parentValueX1Y2))
                    {
                        if (   !isBiomeOceanic(parentValueX1)
                            && !isBiomeOceanic(parentValueX2Y1)
                            && !isBiomeOceanic(parentValueY1)
                            && !isBiomeOceanic(parentValueX1Y2))
                        {
                            result[x + y * areaWidth] = parentValueX1Y1;
                        }
                        else
                        {
                            result[x + y * areaWidth] = BiomeGenBase.beach.biomeID;
                        }
                    }
                    else
                    {
                        result[x + y * areaWidth] = BiomeGenBase.jungleEdge.biomeID;
                    }
                }
                else if (   parentValueX1Y1 != BiomeGenBase.extremeHills.biomeID
                         && parentValueX1Y1 != BiomeGenBase.extremeHillsPlus.biomeID
                         && parentValueX1Y1 != BiomeGenBase.extremeHillsEdge.biomeID) // 不是高山
                {
                    if (biome != null && biome.isSnowyBiome()) // 会下雪
                    {
                        this.func_151632_a(parentRes, result, x, y, areaWidth, parentValueX1Y1, BiomeGenBase.coldBeach.biomeID);
                    }
                    else if (   parentValueX1Y1 != BiomeGenBase.mesa.biomeID
                             && parentValueX1Y1 != BiomeGenBase.mesaPlateau_F.biomeID) // 不是高原
                    {
                        if (parentValueX1Y1    != BiomeGenBase.ocean.biomeID
                            && parentValueX1Y1 != BiomeGenBase.deepOcean.biomeID
                            && parentValueX1Y1 != BiomeGenBase.river.biomeID
                            && parentValueX1Y1 != BiomeGenBase.swampland.biomeID) // 不是海、河、沼泽
                        {
                            int parentValueX1   = parentRes[x + 1 +  y      * (areaWidth + 2)];
                            int parentValueX2Y1 = parentRes[x + 2 + (y + 1) * (areaWidth + 2)];
                            int parentValueY1   = parentRes[x     + (y + 1) * (areaWidth + 2)];
                            int parentValueX1Y2 = parentRes[x + 1 + (y + 2) * (areaWidth + 2)];

                            if (   !isBiomeOceanic(parentValueX1)
                                && !isBiomeOceanic(parentValueX2Y1)
                                && !isBiomeOceanic(parentValueY1)
                                && !isBiomeOceanic(parentValueX1Y2))
                            {
                                result[x + y * areaWidth] = parentValueX1Y1;
                            }
                            else
                            {
                                result[x + y * areaWidth] = BiomeGenBase.beach.biomeID;
                            }
                        }
                        else
                        {
                            result[x + y * areaWidth] = parentValueX1Y1;
                        }
                    }
                    else
                    {
                        int parentValueX1   = parentRes[x + 1 +  y      * (areaWidth + 2)];
                        int parentValueX2Y1 = parentRes[x + 2 + (y + 1) * (areaWidth + 2)];
                        int parentValueY1   = parentRes[x     + (y + 1) * (areaWidth + 2)];
                        int parentValueX1Y2 = parentRes[x + 1 + (y + 2) * (areaWidth + 2)];

                        if (   !isBiomeOceanic(parentValueX1)
                            && !isBiomeOceanic(parentValueX2Y1)
                            && !isBiomeOceanic(parentValueY1)
                            && !isBiomeOceanic(parentValueX1Y2))
                        {
                            if (   this.func_151633_d(parentValueX1)
                                && this.func_151633_d(parentValueX2Y1)
                                && this.func_151633_d(parentValueY1)
                                && this.func_151633_d(parentValueX1Y2))
                            {
                                result[x + y * areaWidth] = parentValueX1Y1;
                            }
                            else
                            {
                                result[x + y * areaWidth] = BiomeGenBase.desert.biomeID;
                            }
                        }
                        else
                        {
                            result[x + y * areaWidth] = parentValueX1Y1;
                        }
                    }
                }
                else
                {
                    this.func_151632_a(parentRes, result, x, y, areaWidth, parentValueX1Y1, BiomeGenBase.stoneBeach.biomeID);
                }
            }
        }

        return result;
    }

    // 如果是陆地和海洋边界则换为newBiome
    private void func_151632_a(int[] parentRes, int[] result, int x, int y, int areaWidth, int parentValueX1Y1, int newBiome)
    {
        if (isBiomeOceanic(parentValueX1Y1))
        {
            result[x + y * areaWidth] = parentValueX1Y1;
        }
        else
        {
            int parentValueX1   = parentRes[x + 1 +  y      * (areaWidth + 2)];
            int parentValueX2Y1 = parentRes[x + 2 + (y + 1) * (areaWidth + 2)];
            int parentValueY1   = parentRes[x     + (y + 1) * (areaWidth + 2)];
            int parentValueX1Y2 = parentRes[x + 1 + (y + 2) * (areaWidth + 2)];

            if (   !isBiomeOceanic(parentValueX1)
                && !isBiomeOceanic(parentValueX2Y1)
                && !isBiomeOceanic(parentValueY1)
                && !isBiomeOceanic(parentValueX1Y2))
            {
                result[x + y * areaWidth] = parentValueX1Y1;
            }
            else
            {
                result[x + y * areaWidth] = newBiome;
            }
        }
    }

    // 判断是不是森林
    private boolean func_151631_c(int biomeId)
    {
        return    BiomeGenBase.getBiome(biomeId) != null
               && BiomeGenBase.getBiome(biomeId).getBiomeClass() == BiomeGenJungle.class ?
                      true : 
                         biomeId == BiomeGenBase.jungleEdge.biomeID
                      || biomeId == BiomeGenBase.jungle.biomeID
                      || biomeId == BiomeGenBase.jungleHills.biomeID
                      || biomeId == BiomeGenBase.forest.biomeID
                      || biomeId == BiomeGenBase.taiga.biomeID
                      || isBiomeOceanic(biomeId);
    }

    // 判断是不是高原
    private boolean func_151633_d(int biomeId)
    {
        return BiomeGenBase.getBiome(biomeId) instanceof BiomeGenMesa;
    }

GenLayerSmooth

用来使上一层的结果更平滑

    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        int parentAreaX = areaX - 1;
        int parentAreaY = areaY - 1;
        int parentWidth = areaWidth + 2;
        int parentHeight = areaHeight + 2;
        int[] parentRes = this.parent.getInts(parentAreaX, parentAreaY, parentWidth, parentHeight);
        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        for (int y = 0; y < areaHeight; ++y)
        {
            for (int x = 0; x < areaWidth; ++x)
            {
                // 以x+1 y+1为中心,十字型采样5个点
                int parentValueY1   = parentRes[x     + (y + 1) * parentWidth];
                int parentValueX2Y1 = parentRes[x + 2 + (y + 1) * parentWidth];
                int parentValueX1   = parentRes[x + 1 +  y      * parentWidth];
                int parentValueX1Y2 = parentRes[x + 1 + (y + 2) * parentWidth];
                int parentValueX1Y1 = parentRes[x + 1 + (y + 1) * parentWidth];

                if (   parentValueY1 == parentValueX2Y1
                    && parentValueX1 == parentValueX1Y2)
                {
                    this.initChunkSeed(x + areaX, y + areaY);

                    // 如果横、竖相对点各自相等则随机取一个
                    if (this.nextInt(2) == 0)
                    {
                        parentValueX1Y1 = parentValueY1;
                    }
                    else
                    {
                        parentValueX1Y1 = parentValueX1;
                    }
                }
                else
                {
                    if (parentValueY1 == parentValueX2Y1)
                    {
                        // 如果横相对两点相等则取其值
                        parentValueX1Y1 = parentValueY1;
                    }

                    if (parentValueX1 == parentValueX1Y2)
                    {
                        // 如果竖相对两点相等则取其值
                        parentValueX1Y1 = parentValueX1;
                    }
                } // 其他情况则不变

                result[x + y * areaWidth] = parentValueX1Y1;
            }
        }

        return result;
    }

GenLayerRiver

用来生成河流

    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        int parentAreaX = areaX - 1;
        int parentAreaY = areaY - 1;
        int parentWidth = areaWidth + 2;
        int parentHeight = areaHeight + 2;
        // parent是经过放大的GenLayerRiverInit
        int[] parentRes = this.parent.getInts(parentAreaX, parentAreaY, parentWidth, parentHeight);
        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        for (int y = 0; y < areaHeight; ++y)
        {
            for (int x = 0; x < areaWidth; ++x)
            {
                // 由上层决定的0、2、3随机数
                int randomValueY1   = this.func_151630_c(parentRes[x     + (y + 1) * parentWidth]);
                int randomValueX2Y1 = this.func_151630_c(parentRes[x + 2 + (y + 1) * parentWidth]);
                int randomValueX1   = this.func_151630_c(parentRes[x + 1 +  y      * parentWidth]);
                int randomValueX1Y2 = this.func_151630_c(parentRes[x + 1 + (y + 2) * parentWidth]);
                int randomValueX1Y1 = this.func_151630_c(parentRes[x + 1 + (y + 1) * parentWidth]);

                if (   randomValueX1Y1 == randomValueY1
                    && randomValueX1Y1 == randomValueX1
                    && randomValueX1Y1 == randomValueX2Y1
                    && randomValueX1Y1 == randomValueX1Y2)
                {
                    // 中心和周围相等则取-1
                    result[x + y * areaWidth] = -1;
                }
                else
                {
                    // 河流
                    result[x + y * areaWidth] = BiomeGenBase.river.biomeID;
                }
            }
        }

        return result;
    }

    // value >= 2则返回2~3的随机数,否则返回value
    private int func_151630_c(int value)
    {
        return value >= 2 ? 2 + value % 2 : value;
    }

GenLayerRiverMix

用来把原有的生物群系和河流混合

    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight)
    {
        // 上层是平滑和放大的GenLayerShore
        int[] biomeRes = this.biomePatternGeneratorChain.getInts(areaX, areaY, areaWidth, areaHeight);
        // 上层是平滑的GenLayerRiver
        int[] riverRes = this.riverPatternGeneratorChain.getInts(areaX, areaY, areaWidth, areaHeight);
        int[] result = IntCache.getIntCache(areaWidth * areaHeight);

        for (int i = 0; i < areaWidth * areaHeight; ++i)
        {
            // biomeRes不是海洋
            if (biomeRes[i] != BiomeGenBase.ocean.biomeID && biomeRes[i] != BiomeGenBase.deepOcean.biomeID)
            {
                // riverRes是河流
                if (riverRes[i] == BiomeGenBase.river.biomeID)
                {
                    // biomeRes是冰原
                    if (biomeRes[i] == BiomeGenBase.icePlains.biomeID)
                    {
                        // 生成冰冻的河流
                        result[i] = BiomeGenBase.frozenRiver.biomeID;
                    }
                    else if (biomeRes[i] != BiomeGenBase.mushroomIsland.biomeID && biomeRes[i] != BiomeGenBase.mushroomIslandShore.biomeID) // biomeRes不是蘑菇岛
                    {
                        // 生成河流
                        result[i] = riverRes[i] & 0xFF;
                    }
                    else
                    {
                        // 生成蘑菇岛海滨(所以蘑菇岛上没有河流...
                        result[i] = BiomeGenBase.mushroomIslandShore.biomeID;
                    }
                }
                else
                {
                    // riverRes不是河流则取原来的生物群系ID
                    result[i] = biomeRes[i];
                }
            }
            else
            {
                result[i] = biomeRes[i];
            }
        }

        return result;
    }

你可能感兴趣的:(逆向工程,Minecraft)