终于看到生成区块的代码了,接下来比较复杂,分成几篇文章吧
本篇内容是生物群系的算法
接着上篇文章我们看到这个函数
类名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,每层都会用上一层的输出生成这一层的输出
它们的初始化函数如下,最后的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生成的就是生物群系ID,对应的生物群系可以在net.minecraft.world.biome.BiomeGenBase
查看。每个GenLayer有3个种子,baseSeed初始化时指定,worldGenSeed世界种子,chunkSeed计算时根据坐标计算。还有一个parent层,初始化时指定
这个是最底层,很简单,随机生成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;
}
这层作用是把上一层结果放大,采样方式是在附近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;
}
从名字来看貌似是用来添加岛屿的
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;
}
从名字来看貌似是用来减少海洋的
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;
}
从名字来看貌似是用来添加雪的(但是好像没有看到雪原的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;
}
这个有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;
}
从名字来看貌似是用来添加蘑菇岛的
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;
}
从名字来看貌似是用来添加深海的
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;
}
这个貌似是把基本群系扩展成更多群系
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;
}
用来给生物群系加上边界和过渡
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;
}
}
}
这个生成的不是生物群系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;
}
从名字来看貌似是用来添加山的
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;
}
这个用来生成突变版平原(看名字好像是太阳花平原?
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;
}
用来生成陆地和海洋之间的沙滩
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;
}
用来使上一层的结果更平滑
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;
}
用来生成河流
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;
}
用来把原有的生物群系和河流混合
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;
}