目前的世界是不是還少了點什麼——沒有樹、礦石怎麼致富!
本篇應該是最後一篇了,研究下樹和礦石之類的點綴的生成
populate函數
上一篇提到的,在provideChunk之後調用
/**
* Populates chunk with ores etc etc
*/
public void populate(IChunkProvider chunkProvider, int chunkX, int chunkZ)
{
// 如果生成了可掉落方塊則立即掉落
BlockFalling.fallInstantly = true;
int minBlockX = chunkX * 16;
int minBlockZ = chunkZ * 16;
BlockPos minBlockPos = new BlockPos(minBlockX, 0, minBlockZ);
// 4個區塊中心點生物羣系
BiomeGenBase biome = this.worldObj.getBiomeGenForCoords(minBlockPos.add(16, 0, 16));
this.rand.setSeed(this.worldObj.getSeed());
long k = this.rand.nextLong() / 2L * 2L + 1L;
long l = this.rand.nextLong() / 2L * 2L + 1L;
this.rand.setSeed((long)chunkX * k + (long)chunkZ * l ^ this.worldObj.getSeed());
boolean hasVillage = false;
ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(chunkX, chunkZ);
net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.terraingen.PopulateChunkEvent.Pre(chunkProvider, worldObj, rand, chunkX, chunkZ, hasVillage));
// 生成建築
if (this.settings.useMineShafts && this.mapFeaturesEnabled)
{
this.mineshaftGenerator.generateStructure(this.worldObj, this.rand, chunkcoordintpair);
}
if (this.settings.useVillages && this.mapFeaturesEnabled)
{
hasVillage = this.villageGenerator.generateStructure(this.worldObj, this.rand, chunkcoordintpair);
}
if (this.settings.useStrongholds && this.mapFeaturesEnabled)
{
this.strongholdGenerator.generateStructure(this.worldObj, this.rand, chunkcoordintpair);
}
if (this.settings.useTemples && this.mapFeaturesEnabled)
{
this.scatteredFeatureGenerator.generateStructure(this.worldObj, this.rand, chunkcoordintpair);
}
if (this.settings.useMonuments && this.mapFeaturesEnabled)
{
this.oceanMonumentGenerator.generateStructure(this.worldObj, this.rand, chunkcoordintpair);
}
// 生成湖
if ( biome != BiomeGenBase.desert
&& biome != BiomeGenBase.desertHills
&& this.settings.useWaterLakes
&& !hasVillage
&& this.rand.nextInt(this.settings.waterLakeChance) == 0
&& net.minecraftforge.event.terraingen.TerrainGen.populate(chunkProvider, worldObj, rand, chunkX, chunkZ, hasVillage, net.minecraftforge.event.terraingen.PopulateChunkEvent.Populate.EventType.LAKE))
{
int i1 = this.rand.nextInt(16) + 8;
int j1 = this.rand.nextInt(256);
int k1 = this.rand.nextInt(16) + 8;
(new WorldGenLakes(Blocks.water)).generate(this.worldObj, this.rand, minBlockPos.add(i1, j1, k1));
}
// 生成岩漿湖
if ( !hasVillage
&& this.rand.nextInt(this.settings.lavaLakeChance / 10) == 0
&& this.settings.useLavaLakes
&& net.minecraftforge.event.terraingen.TerrainGen.populate(chunkProvider, worldObj, rand, chunkX, chunkZ, hasVillage, net.minecraftforge.event.terraingen.PopulateChunkEvent.Populate.EventType.LAVA))
{
int i2 = this.rand.nextInt(16) + 8;
int l2 = this.rand.nextInt(this.rand.nextInt(248) + 8);
int k3 = this.rand.nextInt(16) + 8;
if (l2 < this.worldObj.getSeaLevel() || this.rand.nextInt(this.settings.lavaLakeChance / 8) == 0)
{
(new WorldGenLakes(Blocks.lava)).generate(this.worldObj, this.rand, minBlockPos.add(i2, l2, k3));
}
}
// 生成地牢(刷怪籠)
if (this.settings.useDungeons)
{
boolean doGen = net.minecraftforge.event.terraingen.TerrainGen.populate(chunkProvider, worldObj, rand, chunkX, chunkZ, hasVillage, net.minecraftforge.event.terraingen.PopulateChunkEvent.Populate.EventType.DUNGEON);
for (int j2 = 0; doGen && j2 < this.settings.dungeonChance; ++j2)
{
int i3 = this.rand.nextInt(16) + 8;
int l3 = this.rand.nextInt(256);
int l1 = this.rand.nextInt(16) + 8;
(new WorldGenDungeons()).generate(this.worldObj, this.rand, minBlockPos.add(i3, l3, l1));
}
}
// 生成樹和礦石等
biome.decorate(this.worldObj, this.rand, new BlockPos(minBlockX, 0, minBlockZ));
// 生成動物
if (net.minecraftforge.event.terraingen.TerrainGen.populate(chunkProvider, worldObj, rand, chunkX, chunkZ, hasVillage, net.minecraftforge.event.terraingen.PopulateChunkEvent.Populate.EventType.ANIMALS))
{
SpawnerAnimals.performWorldGenSpawning(this.worldObj, biome, minBlockX + 8, minBlockZ + 8, 16, 16, this.rand);
}
minBlockPos = minBlockPos.add(8, 0, 8);
// 生成冰和雪
boolean doGen = net.minecraftforge.event.terraingen.TerrainGen.populate(chunkProvider, worldObj, rand, chunkX, chunkZ, hasVillage, net.minecraftforge.event.terraingen.PopulateChunkEvent.Populate.EventType.ICE);
for (int x = 0; doGen && x < 16; ++x)
{
for (int z = 0; z < 16; ++z)
{
BlockPos topBlock = this.worldObj.getPrecipitationHeight(minBlockPos.add(x, 0, z));
BlockPos downBlock = topBlock.down();
if (this.worldObj.canBlockFreezeWater(downBlock))
{
this.worldObj.setBlockState(downBlock, Blocks.ice.getDefaultState(), 2);
}
if (this.worldObj.canSnowAt(topBlock, true))
{
this.worldObj.setBlockState(topBlock, Blocks.snow_layer.getDefaultState(), 2);
}
}
}
net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.terraingen.PopulateChunkEvent.Post(chunkProvider, worldObj, rand, chunkX, chunkZ, hasVillage));
BlockFalling.fallInstantly = false;
}
類名net.minecraft.world.biome.BiomeDecorator
public void decorate(World worldIn, Random random, BiomeGenBase biome, BlockPos minBlockPos)
{
if (this.currentWorld != null)
{
throw new RuntimeException("Already decorating");
}
else
{
// 讀取世界設置
this.currentWorld = worldIn;
String s = worldIn.getWorldInfo().getGeneratorOptions();
if (s != null)
{
this.chunkProviderSettings = ChunkProviderSettings.Factory.jsonToFactory(s).func_177864_b();
}
else
{
this.chunkProviderSettings = ChunkProviderSettings.Factory.jsonToFactory("").func_177864_b();
}
this.randomGenerator = random;
this.field_180294_c = minBlockPos;
// 構造礦物、泥土、砂礫等數據
this.dirtGen = new WorldGenMinable(Blocks.dirt.getDefaultState(), this.chunkProviderSettings.dirtSize);
this.gravelGen = new WorldGenMinable(Blocks.gravel.getDefaultState(), this.chunkProviderSettings.gravelSize);
this.graniteGen = new WorldGenMinable(Blocks.stone.getDefaultState().withProperty(BlockStone.VARIANT, BlockStone.EnumType.GRANITE), this.chunkProviderSettings.graniteSize);
this.dioriteGen = new WorldGenMinable(Blocks.stone.getDefaultState().withProperty(BlockStone.VARIANT, BlockStone.EnumType.DIORITE), this.chunkProviderSettings.dioriteSize);
this.andesiteGen = new WorldGenMinable(Blocks.stone.getDefaultState().withProperty(BlockStone.VARIANT, BlockStone.EnumType.ANDESITE), this.chunkProviderSettings.andesiteSize);
this.coalGen = new WorldGenMinable(Blocks.coal_ore.getDefaultState(), this.chunkProviderSettings.coalSize);
this.ironGen = new WorldGenMinable(Blocks.iron_ore.getDefaultState(), this.chunkProviderSettings.ironSize);
this.goldGen = new WorldGenMinable(Blocks.gold_ore.getDefaultState(), this.chunkProviderSettings.goldSize);
this.redstoneGen = new WorldGenMinable(Blocks.redstone_ore.getDefaultState(), this.chunkProviderSettings.redstoneSize);
this.diamondGen = new WorldGenMinable(Blocks.diamond_ore.getDefaultState(), this.chunkProviderSettings.diamondSize);
this.lapisGen = new WorldGenMinable(Blocks.lapis_ore.getDefaultState(), this.chunkProviderSettings.lapisSize);
// 生成
this.genDecorations(biome);
this.currentWorld = null;
this.randomGenerator = null;
}
}
protected void genDecorations(BiomeGenBase biomeGenBaseIn)
{
net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.terraingen.DecorateBiomeEvent.Pre(currentWorld, randomGenerator, field_180294_c));
// 生成礦物
this.generateOres();
// ...
int treeCount = this.treesPerChunk;
if (this.randomGenerator.nextInt(10) == 0)
{
++treeCount;
}
if(net.minecraftforge.event.terraingen.TerrainGen.decorate(currentWorld, randomGenerator, field_180294_c, net.minecraftforge.event.terraingen.DecorateBiomeEvent.Decorate.EventType.TREE))
for (int i = 0; i < treeCount; ++i)
{
int x = this.randomGenerator.nextInt(16) + 8;
int z = this.randomGenerator.nextInt(16) + 8;
// 1/10概率生成大樹
WorldGenAbstractTree genTree = biomeGenBaseIn.genBigTreeChance(this.randomGenerator);
// 只有大樹實現了,設置葉子最遠距離
genTree.func_175904_e();
BlockPos blockpos = this.currentWorld.getHeight(this.field_180294_c.add(x, 0, z));
// 生成樹
if (genTree.generate(this.currentWorld, this.randomGenerator, blockpos))
{
// 只有巨型菠蘿樹實現了
genTree.func_180711_a(this.currentWorld, this.randomGenerator, blockpos);
}
}
// ...
net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.terraingen.DecorateBiomeEvent.Post(currentWorld, randomGenerator, field_180294_c));
}
/**
* Generates ores in the current chunk
*/
protected void generateOres()
{
net.minecraftforge.common.MinecraftForge.ORE_GEN_BUS.post(new net.minecraftforge.event.terraingen.OreGenEvent.Pre(currentWorld, randomGenerator, field_180294_c));
if (net.minecraftforge.event.terraingen.TerrainGen.generateOre(currentWorld, randomGenerator, dirtGen, field_180294_c, net.minecraftforge.event.terraingen.OreGenEvent.GenerateMinable.EventType.DIRT))
this.genStandardOre1(this.chunkProviderSettings.dirtCount, this.dirtGen, this.chunkProviderSettings.dirtMinHeight, this.chunkProviderSettings.dirtMaxHeight);
if (net.minecraftforge.event.terraingen.TerrainGen.generateOre(currentWorld, randomGenerator, gravelGen, field_180294_c, net.minecraftforge.event.terraingen.OreGenEvent.GenerateMinable.EventType.GRAVEL))
this.genStandardOre1(this.chunkProviderSettings.gravelCount, this.gravelGen, this.chunkProviderSettings.gravelMinHeight, this.chunkProviderSettings.gravelMaxHeight);
if (net.minecraftforge.event.terraingen.TerrainGen.generateOre(currentWorld, randomGenerator, dioriteGen, field_180294_c, net.minecraftforge.event.terraingen.OreGenEvent.GenerateMinable.EventType.DIORITE))
this.genStandardOre1(this.chunkProviderSettings.dioriteCount, this.dioriteGen, this.chunkProviderSettings.dioriteMinHeight, this.chunkProviderSettings.dioriteMaxHeight);
if (net.minecraftforge.event.terraingen.TerrainGen.generateOre(currentWorld, randomGenerator, graniteGen, field_180294_c, net.minecraftforge.event.terraingen.OreGenEvent.GenerateMinable.EventType.GRANITE))
this.genStandardOre1(this.chunkProviderSettings.graniteCount, this.graniteGen, this.chunkProviderSettings.graniteMinHeight, this.chunkProviderSettings.graniteMaxHeight);
if (net.minecraftforge.event.terraingen.TerrainGen.generateOre(currentWorld, randomGenerator, andesiteGen, field_180294_c, net.minecraftforge.event.terraingen.OreGenEvent.GenerateMinable.EventType.ANDESITE))
this.genStandardOre1(this.chunkProviderSettings.andesiteCount, this.andesiteGen, this.chunkProviderSettings.andesiteMinHeight, this.chunkProviderSettings.andesiteMaxHeight);
if (net.minecraftforge.event.terraingen.TerrainGen.generateOre(currentWorld, randomGenerator, coalGen, field_180294_c, net.minecraftforge.event.terraingen.OreGenEvent.GenerateMinable.EventType.COAL))
this.genStandardOre1(this.chunkProviderSettings.coalCount, this.coalGen, this.chunkProviderSettings.coalMinHeight, this.chunkProviderSettings.coalMaxHeight);
if (net.minecraftforge.event.terraingen.TerrainGen.generateOre(currentWorld, randomGenerator, ironGen, field_180294_c, net.minecraftforge.event.terraingen.OreGenEvent.GenerateMinable.EventType.IRON))
this.genStandardOre1(this.chunkProviderSettings.ironCount, this.ironGen, this.chunkProviderSettings.ironMinHeight, this.chunkProviderSettings.ironMaxHeight);
if (net.minecraftforge.event.terraingen.TerrainGen.generateOre(currentWorld, randomGenerator, goldGen, field_180294_c, net.minecraftforge.event.terraingen.OreGenEvent.GenerateMinable.EventType.GOLD))
this.genStandardOre1(this.chunkProviderSettings.goldCount, this.goldGen, this.chunkProviderSettings.goldMinHeight, this.chunkProviderSettings.goldMaxHeight);
if (net.minecraftforge.event.terraingen.TerrainGen.generateOre(currentWorld, randomGenerator, redstoneGen, field_180294_c, net.minecraftforge.event.terraingen.OreGenEvent.GenerateMinable.EventType.REDSTONE))
this.genStandardOre1(this.chunkProviderSettings.redstoneCount, this.redstoneGen, this.chunkProviderSettings.redstoneMinHeight, this.chunkProviderSettings.redstoneMaxHeight);
if (net.minecraftforge.event.terraingen.TerrainGen.generateOre(currentWorld, randomGenerator, diamondGen, field_180294_c, net.minecraftforge.event.terraingen.OreGenEvent.GenerateMinable.EventType.DIAMOND))
this.genStandardOre1(this.chunkProviderSettings.diamondCount, this.diamondGen, this.chunkProviderSettings.diamondMinHeight, this.chunkProviderSettings.diamondMaxHeight);
if (net.minecraftforge.event.terraingen.TerrainGen.generateOre(currentWorld, randomGenerator, lapisGen, field_180294_c, net.minecraftforge.event.terraingen.OreGenEvent.GenerateMinable.EventType.LAPIS))
this.genStandardOre2(this.chunkProviderSettings.lapisCount, this.lapisGen, this.chunkProviderSettings.lapisCenterHeight, this.chunkProviderSettings.lapisSpread);
net.minecraftforge.common.MinecraftForge.ORE_GEN_BUS.post(new net.minecraftforge.event.terraingen.OreGenEvent.Post(currentWorld, randomGenerator, field_180294_c));
}
/**
* Standard ore generation helper. Generates most ores.
*/
protected void genStandardOre1(int blockCount, WorldGenerator generator, int minHeight, int maxHeight)
{
if (maxHeight < minHeight)
{
int t = minHeight;
minHeight = maxHeight;
maxHeight = t;
}
else if (maxHeight == minHeight)
{
if (minHeight < 255)
{
++maxHeight;
}
else
{
--minHeight;
}
}
// 生成blockCount堆礦石
for (int i = 0; i < blockCount; ++i)
{
BlockPos blockpos = this.field_180294_c.add(this.randomGenerator.nextInt(16), this.randomGenerator.nextInt(maxHeight - minHeight) + minHeight, this.randomGenerator.nextInt(16));
generator.generate(this.currentWorld, this.randomGenerator, blockpos);
}
}
生成礦物
劃一條線,然後沿着線上生成numberOfBlocks個橢球,把橢球內的方塊替換爲礦石
類名net.minecraft.world.gen.feature.WorldGenMinable
public boolean generate(World worldIn, Random rand, BlockPos position)
{
// 在xz平面上的方向
float angle = rand.nextFloat() * (float)Math.PI;
// 起始點和結束點
double startX = (double)((float)(position.getX() + 8) + MathHelper.sin(angle) * (float)this.numberOfBlocks / 8.0F);
double endX = (double)((float)(position.getX() + 8) - MathHelper.sin(angle) * (float)this.numberOfBlocks / 8.0F);
double startZ = (double)((float)(position.getZ() + 8) + MathHelper.cos(angle) * (float)this.numberOfBlocks / 8.0F);
double endZ = (double)((float)(position.getZ() + 8) - MathHelper.cos(angle) * (float)this.numberOfBlocks / 8.0F);
double startY = (double)(position.getY() + rand.nextInt(3) - 2);
double endY = (double)(position.getY() + rand.nextInt(3) - 2);
// numberOfBlocks是反混淆錯誤,應該是幾個橢球的意思
for (int i = 0; i < this.numberOfBlocks; ++i)
{
// 插值參數
float t = (float)i / (float)this.numberOfBlocks;
// 橢球中心
double centerX = startX + (endX - startX) * (double)t;
double centerY = startY + (endY - startY) * (double)t;
double centerZ = startZ + (endZ - startZ) * (double)t;
// 橢球尺寸(可以看出XZ和Y尺寸一樣,應該是球)
double scale = rand.nextDouble() * (double)this.numberOfBlocks / 16.0D;
double diameterXZ = (double)(MathHelper.sin((float)Math.PI * t) + 1.0F) * scale + 1.0D;
double diameterY = (double)(MathHelper.sin((float)Math.PI * t) + 1.0F) * scale + 1.0D;
// 橢球包圍盒
int minX = MathHelper.floor_double(centerX - diameterXZ / 2.0D);
int minY = MathHelper.floor_double(centerY - diameterY / 2.0D);
int minZ = MathHelper.floor_double(centerZ - diameterXZ / 2.0D);
int maxX = MathHelper.floor_double(centerX + diameterXZ / 2.0D);
int maxY = MathHelper.floor_double(centerY + diameterY / 2.0D);
int maxZ = MathHelper.floor_double(centerZ + diameterXZ / 2.0D);
// 把這個橢球裏的方塊替換爲礦石
for (int x = minX; x <= maxX; ++x)
{
double xDist = ((double)x + 0.5D - centerX) / (diameterXZ / 2.0D);
if (xDist * xDist < 1.0D) // 參考橢球方程
{
for (int y = minY; y <= maxY; ++y)
{
double yDist = ((double)y + 0.5D - centerY) / (diameterY / 2.0D);
if (xDist * xDist + yDist * yDist < 1.0D) // 參考橢球方程
{
for (int z = minZ; z <= maxZ; ++z)
{
double zDist = ((double)z + 0.5D - centerZ) / (diameterXZ / 2.0D);
if (xDist * xDist + yDist * yDist + zDist * zDist < 1.0D) // 參考橢球方程
{
BlockPos blockpos = new BlockPos(x, y, z);
// 可以替換這個方塊
if (worldIn.getBlockState(blockpos).getBlock().isReplaceableOreGen(worldIn, blockpos, this.predicate))
{
// 替換爲礦石
worldIn.setBlockState(blockpos, this.oreBlock, 2);
}
}
}
}
}
}
}
}
return true;
}
生成樹
隨便找了一個可可豆樹的類,類名net.minecraft.world.gen.feature.WorldGenTrees
public boolean generate(World worldIn, Random rand, BlockPos position)
{
int height = rand.nextInt(3) + this.minTreeHeight;
boolean isReplaceable = true;
if (position.getY() >= 1 && position.getY() + height + 1 <= 256)
{
// 檢查所有方塊可替換
for (int y = position.getY(); y <= position.getY() + 1 + height; ++y)
{
int xzSize = 1;
// 底端
if (y == position.getY())
{
xzSize = 0;
}
// 頂端
if (y >= position.getY() + height - 1)
{
xzSize = 2;
}
// 檢查這個平面所有方塊可替換
BlockPos.MutableBlockPos tmpPos = new BlockPos.MutableBlockPos();
for (int x = position.getX() - xzSize; x <= position.getX() + xzSize && isReplaceable; ++x)
{
for (int z = position.getZ() - xzSize; z <= position.getZ() + xzSize && isReplaceable; ++z)
{
if (y >= 0 && y < 256)
{
if (!this.isReplaceable(worldIn, tmpPos.set(x, y, z)))
{
isReplaceable = false;
}
}
else
{
isReplaceable = false;
}
}
}
}
if (!isReplaceable)
{
return false;
}
else
{
BlockPos downPos = position.downPos();
Block downBlock = worldIn.getBlockState(downPos).getBlock();
// 是可生成樹的土壤
boolean isSoil = downBlock.canSustainPlant(worldIn, downPos, net.minecraft.util.EnumFacing.UP, (net.minecraft.block.BlockSapling)Blocks.sapling);
if (isSoil && position.getY() < 256 - height - 1)
{
downBlock.onPlantGrow(worldIn, downPos, position);
// 生成葉子
for (int y = position.getY() + height - 3; y <= position.getY() + height; ++y)
{
int restHeight = y - (position.getY() + height);
int xzSize = 1 - restHeight / 2;
for (int x = position.getX() - xzSize; x <= position.getX() + xzSize; ++x)
{
int xOffset = x - position.getX();
for (int z = position.getZ() - xzSize; z <= position.getZ() + xzSize; ++z)
{
int zOffset = z - position.getZ();
if ( Math.abs(xOffset) != xzSize
|| Math.abs(zOffset) != xzSize // 不在邊緣4個點
|| rand.nextInt(2) != 0
&& restHeight != 0)
{
BlockPos blockpos = new BlockPos(x, y, z);
Block block = worldIn.getBlockState(blockpos).getBlock();
if ( block.isAir(worldIn, blockpos)
|| block.isLeaves(worldIn, blockpos)
|| block.getMaterial() == Material.vine)
{
this.setBlockAndNotifyAdequately(worldIn, blockpos, this.metaLeaves);
}
}
}
}
}
// 生成木頭
for (int y = 0; y < height; ++y)
{
BlockPos upPos = position.up(y);
Block upBlock = worldIn.getBlockState(upPos).getBlock();
if ( upBlock.isAir(worldIn, upPos)
|| upBlock.isLeaves(worldIn, upPos)
|| upBlock.getMaterial() == Material.vine)
{
this.setBlockAndNotifyAdequately(worldIn, position.up(y), this.metaWood);
// 生成藤蔓
if (this.vinesGrow && y > 0)
{
if (rand.nextInt(3) > 0 && worldIn.isAirBlock(position.add(-1, y, 0)))
{
this.func_181651_a(worldIn, position.add(-1, y, 0), BlockVine.EAST);
}
if (rand.nextInt(3) > 0 && worldIn.isAirBlock(position.add(1, y, 0)))
{
this.func_181651_a(worldIn, position.add(1, y, 0), BlockVine.WEST);
}
if (rand.nextInt(3) > 0 && worldIn.isAirBlock(position.add(0, y, -1)))
{
this.func_181651_a(worldIn, position.add(0, y, -1), BlockVine.SOUTH);
}
if (rand.nextInt(3) > 0 && worldIn.isAirBlock(position.add(0, y, 1)))
{
this.func_181651_a(worldIn, position.add(0, y, 1), BlockVine.NORTH);
}
}
}
}
// 生成藤蔓
if (this.vinesGrow)
{
for (int y = position.getY() + height - 3; y <= position.getY() + height; ++y)
{
int restHeight = y - (position.getY() + height);
int xzSize = 2 - restHeight / 2;
BlockPos.MutableBlockPos tmpPos = new BlockPos.MutableBlockPos();
for (int x = position.getX() - xzSize; x <= position.getX() + xzSize; ++x)
{
for (int z = position.getZ() - xzSize; z <= position.getZ() + xzSize; ++z)
{
tmpPos.set(x, y, z);
if (worldIn.getBlockState(tmpPos).getBlock().isLeaves(worldIn,tmpPos))
{
BlockPos blockpos2 = tmpPos.west();
BlockPos blockpos3 = tmpPos.east();
BlockPos blockpos4 = tmpPos.north();
BlockPos blockpos1 = tmpPos.south();
if (rand.nextInt(4) == 0 && worldIn.getBlockState(blockpos2).getBlock().isAir(worldIn,blockpos2))
{
this.func_181650_b(worldIn, blockpos2, BlockVine.EAST);
}
if (rand.nextInt(4) == 0 && worldIn.getBlockState(blockpos3).getBlock().isAir(worldIn,blockpos3))
{
this.func_181650_b(worldIn, blockpos3, BlockVine.WEST);
}
if (rand.nextInt(4) == 0 && worldIn.getBlockState(blockpos4).getBlock().isAir(worldIn,blockpos4))
{
this.func_181650_b(worldIn, blockpos4, BlockVine.SOUTH);
}
if (rand.nextInt(4) == 0 && worldIn.getBlockState(blockpos1).getBlock().isAir(worldIn,blockpos1))
{
this.func_181650_b(worldIn, blockpos1, BlockVine.NORTH);
}
}
}
}
}
// 生成可可豆
if (rand.nextInt(5) == 0 && height > 5)
{
for (int yOffset = 0; yOffset < 2; ++yOffset)
{
for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL)
{
if (rand.nextInt(4 - yOffset) == 0)
{
EnumFacing enumfacing1 = enumfacing.getOpposite();
this.func_181652_a(worldIn, rand.nextInt(3), position.add(enumfacing1.getFrontOffsetX(), height - 5 + yOffset, enumfacing1.getFrontOffsetZ()), enumfacing);
}
}
}
}
}
return true;
}
else
{
return false;
}
}
}
else
{
return false;
}
}
生成動物
雖然生成方塊研究完了,姑且研究下動物
類名net.minecraft.world.SpawnerAnimals
/**
* Called during chunk generation to spawn initial creatures.
*
* @param biomeIn The biome to use for the weighted entity creatureList
* @param randomIn The random to use for mob spawning
*/
public static void performWorldGenSpawning(World worldIn, BiomeGenBase biomeIn, int x, int z, int xSize, int zSize, Random randomIn)
{
// 這個生物羣系可生成的生物
List<BiomeGenBase.SpawnListEntry> creatureList = biomeIn.getSpawnableList(EnumCreatureType.CREATURE);
if (!creatureList.isEmpty())
{
while (randomIn.nextFloat() < biomeIn.getSpawningChance())
{
BiomeGenBase.SpawnListEntry spawn = (BiomeGenBase.SpawnListEntry)WeightedRandom.getRandomItem(worldIn.rand, creatureList);
int entityCount = spawn.minGroupCount + randomIn.nextInt(1 + spawn.maxGroupCount - spawn.minGroupCount);
IEntityLivingData data = null;
int spawnX = x + randomIn.nextInt(xSize);
int spawnZ = z + randomIn.nextInt(zSize);
int centerX = spawnX;
int centerZ = spawnZ;
for (int i = 0; i < entityCount; ++i)
{
boolean hasSpawned = false;
// 嘗試生成4次
for (int j = 0; !hasSpawned && j < 4; ++j)
{
BlockPos topPos = worldIn.getTopSolidOrLiquidBlock(new BlockPos(spawnX, 0, spawnZ));
// 能生成在這個方塊上
if (canCreatureTypeSpawnAtLocation(EntityLiving.SpawnPlacementType.ON_GROUND, worldIn, topPos))
{
EntityLiving entity;
try
{
entity = (EntityLiving)spawn.entityClass.getConstructor(new Class[] {World.class}).newInstance(new Object[] {worldIn});
}
catch (Exception exception)
{
exception.printStackTrace();
continue;
}
// 設置位置和方向
entity.setLocationAndAngles((double)((float)spawnX + 0.5F), (double)topPos.getY(), (double)((float)spawnZ + 0.5F), randomIn.nextFloat() * 360.0F, 0.0F);
// 生成
worldIn.spawnEntityInWorld(entity);
data = entity.onInitialSpawn(worldIn.getDifficultyForLocation(new BlockPos(entity)), data);
hasSpawned = true;
}
spawnX += randomIn.nextInt(5) - randomIn.nextInt(5);
for (spawnZ += randomIn.nextInt(5) - randomIn.nextInt(5); spawnX < x || spawnX >= x + xSize || spawnZ < z || spawnZ >= z + xSize; spawnZ = centerZ + randomIn.nextInt(5) - randomIn.nextInt(5))
{
spawnX = centerX + randomIn.nextInt(5) - randomIn.nextInt(5);
}
}
}
}
}
}