Minecraft的世界生成过程(七)矿物和树

来源:互联网 发布:北京住宅成交数据 编辑:程序博客网 时间:2024/04/29 13:08

目前的世界是不是还少了点什么——没有树、矿石怎么致富!

本篇应该是最后一篇了,研究下树和矿石之类的点缀的生成

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);                        }                    }                }            }        }    }
0 0