From 56e5fbfaa8f705703481f29f3517987db72c3068 Mon Sep 17 00:00:00 2001 From: Cheeserolls Date: Thu, 11 Jun 2015 22:03:52 +0100 Subject: [PATCH] Add Bayou biome, GeneratorBayouTree and some adjustments to other generators --- .../biomesoplenty/api/biome/BOPBiomes.java | 1 + .../biomesoplenty/api/block/BlockQueries.java | 2 + .../biome/overworld/BiomeGenBambooForest.java | 5 +- .../common/biome/overworld/BiomeGenBayou.java | 126 ++++++ .../biome/overworld/BiomeGenGrassland.java | 4 +- .../common/biome/overworld/BiomeGenMarsh.java | 2 +- .../common/biome/overworld/BiomeGenMoor.java | 3 +- .../common/block/BlockBOPDoublePlant.java | 2 +- .../common/block/BlockBOPPlant.java | 4 +- .../biomesoplenty/common/init/ModBiomes.java | 1 + .../common/init/ModBlockQueries.java | 4 +- .../common/init/ModGenerators.java | 1 + .../common/util/biome/GeneratorUtils.java | 37 +- .../common/world/feature/GeneratorBlobs.java | 2 +- .../world/feature/GeneratorDoubleFlora.java | 2 +- .../common/world/feature/GeneratorFlora.java | 18 +- .../common/world/feature/GeneratorGrass.java | 9 +- .../world/feature/GeneratorSplotches.java | 2 +- .../feature/tree/GeneratorBayouTree.java | 381 ++++++++++++++++++ .../world/feature/tree/GeneratorBulbTree.java | 8 +- 20 files changed, 570 insertions(+), 44 deletions(-) create mode 100644 src/main/java/biomesoplenty/common/biome/overworld/BiomeGenBayou.java create mode 100644 src/main/java/biomesoplenty/common/world/feature/tree/GeneratorBayouTree.java diff --git a/src/main/java/biomesoplenty/api/biome/BOPBiomes.java b/src/main/java/biomesoplenty/api/biome/BOPBiomes.java index 955e360ad..41df8746e 100644 --- a/src/main/java/biomesoplenty/api/biome/BOPBiomes.java +++ b/src/main/java/biomesoplenty/api/biome/BOPBiomes.java @@ -18,6 +18,7 @@ public class BOPBiomes public static Optional alps = Optional.absent(); public static Optional arctic = Optional.absent(); public static Optional bamboo_forest = Optional.absent(); + public static Optional bayou = Optional.absent(); public static Optional crag = Optional.absent(); public static Optional chaparral = Optional.absent(); public static Optional denseForest = Optional.absent(); diff --git a/src/main/java/biomesoplenty/api/block/BlockQueries.java b/src/main/java/biomesoplenty/api/block/BlockQueries.java index a645b5e0f..bf29e0eac 100644 --- a/src/main/java/biomesoplenty/api/block/BlockQueries.java +++ b/src/main/java/biomesoplenty/api/block/BlockQueries.java @@ -28,6 +28,7 @@ public class BlockQueries public static IBlockPosQuery hellish; public static IBlockPosQuery litFertile; public static IBlockPosQuery litBeach; + public static IBlockPosQuery litFertileWaterside; public static IBlockPosQuery litSand; public static IBlockPosQuery litDry; public static IBlockPosQuery litFertileOrDry; @@ -35,5 +36,6 @@ public class BlockQueries public static IBlockPosQuery fertileSeaBed; public static IBlockPosQuery underwater; public static IBlockPosQuery suitableForReed; + public static IBlockPosQuery rootsCanDigThrough; } \ No newline at end of file diff --git a/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenBambooForest.java b/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenBambooForest.java index 065e548ad..aa62c0758 100644 --- a/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenBambooForest.java +++ b/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenBambooForest.java @@ -29,6 +29,7 @@ import biomesoplenty.common.block.BlockBOPCoral; import biomesoplenty.common.enums.BOPGems; import biomesoplenty.common.enums.BOPPlants; import biomesoplenty.common.enums.BOPTrees; +import biomesoplenty.common.util.biome.GeneratorUtils.ScatterYMethod; import biomesoplenty.common.util.config.BOPConfig.IConfigObj; import biomesoplenty.common.world.feature.GeneratorColumns; import biomesoplenty.common.world.feature.GeneratorDoubleFlora; @@ -79,8 +80,8 @@ public class BiomeGenBambooForest extends BOPBiome // other plants this.addGenerator("leaf_piles", GeneratorStage.FLOWERS,(new GeneratorFlora.Builder()).amountPerChunk(3.0F).with(BOPPlants.LEAFPILE).create()); this.addGenerator("ferns", GeneratorStage.FLOWERS,(new GeneratorFlora.Builder()).amountPerChunk(4.0F).with(BlockTallGrass.EnumType.FERN).create()); - this.addGenerator("river_cane", GeneratorStage.FLOWERS,(new GeneratorColumns.Builder()).amountPerChunk(5.0F).generationAttempts(24).placeOn(BlockQueries.litBeach).with(BlockBOPPlant.paging.getVariantState(BOPPlants.RIVERCANE)).minHeight(1).maxHeight(3).create()); - this.addGenerator("algae", GeneratorStage.LILYPAD, (new GeneratorFlora.Builder()).amountPerChunk(10.0F).replace(Blocks.water).with(BOPBlocks.coral.getDefaultState().withProperty(BlockBOPCoral.VARIANT, BlockBOPCoral.CoralType.ALGAE)).generationAttempts(32).create()); + this.addGenerator("river_cane", GeneratorStage.FLOWERS,(new GeneratorColumns.Builder()).amountPerChunk(5.0F).generationAttempts(24).placeOn(BlockQueries.litFertileWaterside).with(BlockBOPPlant.paging.getVariantState(BOPPlants.RIVERCANE)).minHeight(1).maxHeight(3).create()); + this.addGenerator("algae", GeneratorStage.LILYPAD, (new GeneratorFlora.Builder()).amountPerChunk(4.0F).replace(Blocks.water).with(BOPBlocks.coral.getDefaultState().withProperty(BlockBOPCoral.VARIANT, BlockBOPCoral.CoralType.ALGAE)).scatterYMethod(ScatterYMethod.AT_GROUND).create()); this.addGenerator("bushes", GeneratorStage.FLOWERS,(new GeneratorFlora.Builder()).amountPerChunk(0.5F).with(BOPPlants.BUSH).create()); // gem diff --git a/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenBayou.java b/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenBayou.java new file mode 100644 index 000000000..16201fd58 --- /dev/null +++ b/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenBayou.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * Copyright 2015, the Biomes O' Plenty Team + * + * This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License. + * + * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/. + ******************************************************************************/ + +package biomesoplenty.common.biome.overworld; + +import net.minecraft.block.BlockDoublePlant; +import net.minecraft.block.BlockTallGrass; +import net.minecraft.entity.monster.EntitySlime; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraftforge.common.BiomeManager.BiomeType; +import biomesoplenty.api.biome.BOPBiome; +import biomesoplenty.api.biome.generation.GeneratorStage; +import biomesoplenty.api.biome.generation.GeneratorWeighted; +import biomesoplenty.api.block.BOPBlocks; +import biomesoplenty.api.block.BlockQueries; +import biomesoplenty.common.block.BlockBOPCoral; +import biomesoplenty.common.block.BlockBOPDoublePlant; +import biomesoplenty.common.block.BlockBOPLilypad; +import biomesoplenty.common.enums.BOPPlants; +import biomesoplenty.common.enums.BOPTrees; +import biomesoplenty.common.enums.BOPWoods; +import biomesoplenty.common.util.biome.GeneratorUtils.ScatterYMethod; +import biomesoplenty.common.util.block.BlockQuery; +import biomesoplenty.common.util.block.BlockQuery.IBlockPosQuery; +import biomesoplenty.common.world.feature.GeneratorColumns; +import biomesoplenty.common.world.feature.GeneratorDoubleFlora; +import biomesoplenty.common.world.feature.GeneratorFlora; +import biomesoplenty.common.world.feature.GeneratorGrass; +import biomesoplenty.common.world.feature.GeneratorSplatter; +import biomesoplenty.common.world.feature.GeneratorWaterside; +import biomesoplenty.common.world.feature.tree.GeneratorBayouTree; + +public class BiomeGenBayou extends BOPBiome +{ + + public BiomeGenBayou() + { + // terrain + this.bopMinHeight = 54; + this.bopMaxHeight = 65; + this.sidewaysNoiseAmount = 0.0F; + this.setOctaveWeights(1, 1, 1, 1, 0, 0); + + this.setColor(0x8BAF6B); + this.setTemperatureRainfall(0.8F, 0.9F); + this.waterColorMultiplier = 0xFFD932; + this.skyColor = 0xACC4BC; + this.seaFloorBlock = BOPBlocks.mud.getDefaultState(); + + this.addWeight(BiomeType.WARM, 10); + + this.spawnableWaterCreatureList.clear(); + this.spawnableMonsterList.add(new SpawnListEntry(EntitySlime.class, 10, 1, 3)); + + // mud + IBlockPosQuery emptyGrassOrDirt = BlockQuery.buildAnd().withAirAbove().states(this.topBlock, this.fillerBlock).create(); + this.addGenerator("mud", GeneratorStage.SAND_PASS2, (new GeneratorWaterside.Builder()).amountPerChunk(8).maxRadius(7).with(BOPBlocks.mud.getDefaultState()).create()); + this.addGenerator("mud_splatter", GeneratorStage.SAND, (new GeneratorSplatter.Builder()).amountPerChunk(4.0F).replace(emptyGrassOrDirt).with(BOPBlocks.mud.getDefaultState()).create()); + + // trees & logs + GeneratorWeighted treeGenerator = new GeneratorWeighted(8); + this.addGenerator("trees", GeneratorStage.TREE, treeGenerator); + treeGenerator.add("willow", 3, (new GeneratorBayouTree.Builder()).log(BOPWoods.WILLOW).leaves(BOPTrees.WILLOW).minHeight(6).maxHeight(12).minLeavesRadius(1).leavesGradient(2).create()); + treeGenerator.add("willow_large", 1, (new GeneratorBayouTree.Builder()).log(BOPWoods.WILLOW).leaves(BOPTrees.WILLOW).minHeight(10).maxHeight(18).minLeavesRadius(2).leavesGradient(3).create()); + + // grasses + GeneratorWeighted grassGenerator = new GeneratorWeighted(10.0F); + this.addGenerator("grass", GeneratorStage.GRASS, grassGenerator); + grassGenerator.add("wheatgrass", 1, (new GeneratorGrass.Builder()).with(BOPPlants.WHEATGRASS).create()); + grassGenerator.add("dampgrass", 1, (new GeneratorGrass.Builder()).with(BOPPlants.DAMPGRASS).create()); + grassGenerator.add("tallgrass", 2, (new GeneratorGrass.Builder()).with(BlockTallGrass.EnumType.GRASS).create()); + grassGenerator.add("doublegrass", 1, (new GeneratorDoubleFlora.Builder()).with(BlockDoublePlant.EnumPlantType.GRASS).create()); + + // other plants + this.addGenerator("koru", GeneratorStage.FLOWERS,(new GeneratorFlora.Builder()).amountPerChunk(0.3F).with(BOPPlants.KORU).create()); + this.addGenerator("cattail", GeneratorStage.FLOWERS,(new GeneratorFlora.Builder()).amountPerChunk(3.0F).with(BOPPlants.CATTAIL).create()); + this.addGenerator("double_cattail", GeneratorStage.FLOWERS, (new GeneratorDoubleFlora.Builder()).amountPerChunk(3.0F).with(BlockBOPDoublePlant.DoublePlantType.TALL_CATTAIL).create()); + this.addGenerator("leaf_piles", GeneratorStage.FLOWERS,(new GeneratorFlora.Builder()).amountPerChunk(3.0F).with(BOPPlants.LEAFPILE).create()); + this.addGenerator("sugar_cane", GeneratorStage.FLOWERS,(new GeneratorColumns.Builder()).amountPerChunk(3.0F).generationAttempts(24).placeOn(BlockQueries.litFertileWaterside).with(Blocks.reeds.getDefaultState()).minHeight(1).maxHeight(3).create()); + + // water plants + this.addGenerator("duckweed", GeneratorStage.LILYPAD, (new GeneratorFlora.Builder()).amountPerChunk(1.5F).with(BlockBOPLilypad.LilypadType.DUCKWEED).create()); + this.addGenerator("lily", GeneratorStage.LILYPAD, (new GeneratorFlora.Builder()).amountPerChunk(2.5F).with(Blocks.waterlily.getDefaultState()).create()); + this.addGenerator("medium_lily", GeneratorStage.LILYPAD, (new GeneratorFlora.Builder()).amountPerChunk(2.0F).with(BlockBOPLilypad.LilypadType.MEDIUM).create()); + this.addGenerator("small_lily", GeneratorStage.LILYPAD, (new GeneratorFlora.Builder()).amountPerChunk(1.5F).with(BlockBOPLilypad.LilypadType.SMALL).create()); + this.addGenerator("tiny_lily", GeneratorStage.LILYPAD, (new GeneratorFlora.Builder()).amountPerChunk(1.5F).with(BlockBOPLilypad.LilypadType.TINY).create()); + this.addGenerator("algae", GeneratorStage.LILYPAD, (new GeneratorFlora.Builder()).amountPerChunk(4.0F).replace(Blocks.water).with(BOPBlocks.coral.getDefaultState().withProperty(BlockBOPCoral.VARIANT, BlockBOPCoral.CoralType.ALGAE)).scatterYMethod(ScatterYMethod.AT_GROUND).create()); + this.addGenerator("water_reeds", GeneratorStage.LILYPAD, (new GeneratorFlora.Builder()).amountPerChunk(4.0F).with(BOPPlants.REED).generationAttempts(32).create()); + + // shrooms + this.addGenerator("red_mushrooms", GeneratorStage.SHROOM,(new GeneratorFlora.Builder()).amountPerChunk(0.3F).with(Blocks.red_mushroom.getDefaultState()).create()); + this.addGenerator("brown_mushrooms", GeneratorStage.SHROOM,(new GeneratorFlora.Builder()).amountPerChunk(0.3F).with(Blocks.brown_mushroom.getDefaultState()).create()); + + + } + + @Override + public int getGrassColorAtPos(BlockPos pos) + { + return 0x8BAF6B; + } + + @Override + public int getFoliageColorAtPos(BlockPos pos) + { + return 0xB0E088; + } + + // TODO: These 2 are copied from 1.7 - but are they used ever? + public int getFogColour(BlockPos pos) + { + return 0x90AF95; + } + public float getFogDensity(BlockPos pos) + { + return 0.99F; + } + + +} diff --git a/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenGrassland.java b/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenGrassland.java index 6b83a9a71..8a5b42e4b 100644 --- a/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenGrassland.java +++ b/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenGrassland.java @@ -54,8 +54,8 @@ public class BiomeGenGrassland extends BOPBiome { this.addGenerator("gravel", GeneratorStage.SAND_PASS2, (new GeneratorWaterside.Builder()).amountPerChunk(4).maxRadius(7).with(Blocks.gravel.getDefaultState()).create()); // other plants - this.addGenerator("river_cane", GeneratorStage.FLOWERS,(new GeneratorColumns.Builder()).amountPerChunk(1.0F).generationAttempts(24).placeOn(BlockQueries.litBeach).with(BlockBOPPlant.paging.getVariantState(BOPPlants.RIVERCANE)).minHeight(1).maxHeight(3).create()); - this.addGenerator("sugar_cane", GeneratorStage.FLOWERS,(new GeneratorColumns.Builder()).amountPerChunk(4.0F).generationAttempts(24).placeOn(BlockQueries.litBeach).with(Blocks.reeds.getDefaultState()).minHeight(1).maxHeight(3).create()); + this.addGenerator("river_cane", GeneratorStage.FLOWERS,(new GeneratorColumns.Builder()).amountPerChunk(1.0F).generationAttempts(24).placeOn(BlockQueries.litFertileWaterside).with(BlockBOPPlant.paging.getVariantState(BOPPlants.RIVERCANE)).minHeight(1).maxHeight(3).create()); + this.addGenerator("sugar_cane", GeneratorStage.FLOWERS,(new GeneratorColumns.Builder()).amountPerChunk(4.0F).generationAttempts(24).placeOn(BlockQueries.litFertileWaterside).with(Blocks.reeds.getDefaultState()).minHeight(1).maxHeight(3).create()); this.addGenerator("flax", GeneratorStage.FLOWERS,(new GeneratorDoubleFlora.Builder()).amountPerChunk(0.1F).with(BlockBOPDoublePlant.DoublePlantType.FLAX).generationAttempts(6).create()); // water plants diff --git a/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenMarsh.java b/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenMarsh.java index 0975d706f..ab8c7e8a6 100644 --- a/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenMarsh.java +++ b/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenMarsh.java @@ -69,7 +69,7 @@ public class BiomeGenMarsh extends BOPBiome // water plants this.addGenerator("duckweed", GeneratorStage.LILYPAD, (new GeneratorFlora.Builder()).amountPerChunk(0.5F).with(BlockBOPLilypad.LilypadType.DUCKWEED).generationAttempts(32).create()); - this.addGenerator("algae", GeneratorStage.LILYPAD, (new GeneratorFlora.Builder()).amountPerChunk(10.0F).replace(Blocks.water).with(BOPBlocks.coral.getDefaultState().withProperty(BlockBOPCoral.VARIANT, BlockBOPCoral.CoralType.ALGAE)).generationAttempts(32).create()); + this.addGenerator("algae", GeneratorStage.LILYPAD, (new GeneratorFlora.Builder()).amountPerChunk(10.0F).replace(Blocks.water).with(BOPBlocks.coral.getDefaultState().withProperty(BlockBOPCoral.VARIANT, BlockBOPCoral.CoralType.ALGAE)).generationAttempts(32).scatterYMethod(ScatterYMethod.AT_GROUND).create()); this.addGenerator("water_reeds", GeneratorStage.LILYPAD, (new GeneratorFlora.Builder()).amountPerChunk(5.0F).with(BOPPlants.REED).generationAttempts(32).create()); // grasses diff --git a/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenMoor.java b/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenMoor.java index fff90490b..e0f8da9b4 100644 --- a/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenMoor.java +++ b/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenMoor.java @@ -23,6 +23,7 @@ import biomesoplenty.common.block.BlockBOPCoral; import biomesoplenty.common.enums.BOPFlowers; import biomesoplenty.common.enums.BOPGems; import biomesoplenty.common.enums.BOPPlants; +import biomesoplenty.common.util.biome.GeneratorUtils.ScatterYMethod; import biomesoplenty.common.world.feature.*; public class BiomeGenMoor extends BOPBiome @@ -75,7 +76,7 @@ public class BiomeGenMoor extends BOPBiome // other plants this.addGenerator("koru", GeneratorStage.FLOWERS,(new GeneratorFlora.Builder()).amountPerChunk(0.6F).with(BOPPlants.KORU).create()); this.addGenerator("flax", GeneratorStage.FLOWERS,(new GeneratorDoubleFlora.Builder()).amountPerChunk(0.1F).with(BlockBOPDoublePlant.DoublePlantType.FLAX).generationAttempts(6).create()); - this.addGenerator("algae", GeneratorStage.LILYPAD, (new GeneratorFlora.Builder()).amountPerChunk(10.0F).replace(Blocks.water).with(BOPBlocks.coral.getDefaultState().withProperty(BlockBOPCoral.VARIANT, BlockBOPCoral.CoralType.ALGAE)).generationAttempts(32).create()); + this.addGenerator("algae", GeneratorStage.LILYPAD, (new GeneratorFlora.Builder()).amountPerChunk(5.0F).replace(Blocks.water).with(BOPBlocks.coral.getDefaultState().withProperty(BlockBOPCoral.VARIANT, BlockBOPCoral.CoralType.ALGAE)).scatterYMethod(ScatterYMethod.AT_GROUND).create()); // gem this.addGenerator("malachite", GeneratorStage.SAND, (new GeneratorOreSingle.Builder()).amountPerChunk(12).with(BOPGems.MALACHITE).create()); diff --git a/src/main/java/biomesoplenty/common/block/BlockBOPDoublePlant.java b/src/main/java/biomesoplenty/common/block/BlockBOPDoublePlant.java index ece1ac92f..8bcbf38d5 100644 --- a/src/main/java/biomesoplenty/common/block/BlockBOPDoublePlant.java +++ b/src/main/java/biomesoplenty/common/block/BlockBOPDoublePlant.java @@ -171,7 +171,7 @@ public class BlockBOPDoublePlant extends BlockBOPDoubleDecoration implements ISh switch (plant) { case TALL_CATTAIL: - return BlockQueries.litBeach.matches(world, lowerPos.down()); + return BlockQueries.litFertileWaterside.matches(world, lowerPos.down()); case EYEBULB: return BlockQueries.hellish.matches(world, lowerPos.down()); case FLAX: default: diff --git a/src/main/java/biomesoplenty/common/block/BlockBOPPlant.java b/src/main/java/biomesoplenty/common/block/BlockBOPPlant.java index 3858fd6f0..4ca171a78 100644 --- a/src/main/java/biomesoplenty/common/block/BlockBOPPlant.java +++ b/src/main/java/biomesoplenty/common/block/BlockBOPPlant.java @@ -371,10 +371,10 @@ public class BlockBOPPlant extends BlockBOPDecoration implements IShearable case THORN: return BlockQueries.litFertileOrDry.matches(world, pos.down()); case CATTAIL: - return BlockQueries.litBeach.matches(world, pos.down()); + return BlockQueries.litFertileWaterside.matches(world, pos.down()); case RIVERCANE: // river cane can also be placed on top of itself - return BlockQueries.litBeach.matches(world, pos.down()) || (world.getBlockState(pos.down()) == state); + return BlockQueries.litFertileWaterside.matches(world, pos.down()) || (world.getBlockState(pos.down()) == state); case WITHERWART: return BlockQueries.sustainsNether.matches(world, pos.down()); case REED: diff --git a/src/main/java/biomesoplenty/common/init/ModBiomes.java b/src/main/java/biomesoplenty/common/init/ModBiomes.java index c91748ff4..9a7517cee 100644 --- a/src/main/java/biomesoplenty/common/init/ModBiomes.java +++ b/src/main/java/biomesoplenty/common/init/ModBiomes.java @@ -143,6 +143,7 @@ public class ModBiomes alps = registerBOPBiome(new BiomeGenAlps(), "Alps"); arctic = registerBOPBiome(new BiomeGenArctic(), "Arctic"); bamboo_forest = registerBOPBiome(new BiomeGenBambooForest(), "Bamboo Forest"); + bayou = registerBOPBiome(new BiomeGenBayou(), "Bayou"); crag = registerBOPBiome(new BiomeGenCrag(), "Crag"); chaparral = registerBOPBiome(new BiomeGenChaparral(), "Chaparral"); denseForest = registerBOPBiome(new BiomeGenDenseForest(), "Dense Forest"); diff --git a/src/main/java/biomesoplenty/common/init/ModBlockQueries.java b/src/main/java/biomesoplenty/common/init/ModBlockQueries.java index bafe77d8e..e0bc4c802 100644 --- a/src/main/java/biomesoplenty/common/init/ModBlockQueries.java +++ b/src/main/java/biomesoplenty/common/init/ModBlockQueries.java @@ -69,6 +69,7 @@ public class ModBlockQueries endish = BlockQuery.buildOr().blocks(Blocks.end_stone).states(BOPBlocks.grass.getDefaultState().withProperty(BlockBOPGrass.VARIANT, BlockBOPGrass.BOPGrassType.SPECTRAL_MOSS)).create(); hellish = BlockQuery.buildOr().blocks(Blocks.netherrack, BOPBlocks.flesh).states(BOPBlocks.grass.getDefaultState().withProperty(BlockBOPGrass.VARIANT, BlockBOPGrass.BOPGrassType.OVERGROWN_NETHERRACK)).create(); litBeach = BlockQuery.buildAnd().sustainsPlant(EnumPlantType.Beach).withLightAtLeast(8).create(); + litFertileWaterside = BlockQuery.buildAnd().sustainsPlant(EnumPlantType.Plains).byWater().create(); litFertile = BlockQuery.buildAnd().sustainsPlant(EnumPlantType.Plains).withLightAtLeast(8).create(); litSand = BlockQuery.buildAnd().materials(Material.sand).withLightAtLeast(8).create(); litDry = BlockQuery.buildAnd().sustainsPlant(EnumPlantType.Desert).withLightAtLeast(8).create(); @@ -81,7 +82,8 @@ public class ModBlockQueries @Override public boolean matches(World world, BlockPos pos) { return world.getBlockState(pos).getBlock() == Blocks.water && world.getBlockState(pos.down()).getBlock() != Blocks.water; } - }).withLightAtLeast(8).create(); + }).withLightAtLeast(8).create(); + rootsCanDigThrough = new BlockQueryMaterial(Material.air, Material.water, Material.ground, Material.grass, Material.sand, Material.clay); } } \ No newline at end of file diff --git a/src/main/java/biomesoplenty/common/init/ModGenerators.java b/src/main/java/biomesoplenty/common/init/ModGenerators.java index 5081e08bd..9e3be651a 100644 --- a/src/main/java/biomesoplenty/common/init/ModGenerators.java +++ b/src/main/java/biomesoplenty/common/init/ModGenerators.java @@ -26,6 +26,7 @@ public class ModGenerators registerGenerator("twiglet_tree", GeneratorTwigletTree.class, new GeneratorTwigletTree.Builder()); registerGenerator("pine_tree", GeneratorPineTree.class, new GeneratorPineTree.Builder()); registerGenerator("bulb_tree", GeneratorBulbTree.class, new GeneratorBulbTree.Builder()); + registerGenerator("bayou_tree", GeneratorBayouTree.class, new GeneratorBayouTree.Builder()); registerGenerator("flora", GeneratorFlora.class, new GeneratorFlora.Builder()); registerGenerator("double_flora", GeneratorDoubleFlora.class, new GeneratorDoubleFlora.Builder()); registerGenerator("grass", GeneratorGrass.class, new GeneratorGrass.Builder()); diff --git a/src/main/java/biomesoplenty/common/util/biome/GeneratorUtils.java b/src/main/java/biomesoplenty/common/util/biome/GeneratorUtils.java index 2cc3d05f1..bd252ecaa 100644 --- a/src/main/java/biomesoplenty/common/util/biome/GeneratorUtils.java +++ b/src/main/java/biomesoplenty/common/util/biome/GeneratorUtils.java @@ -80,31 +80,34 @@ public class GeneratorUtils public static enum ScatterYMethod { - ANYWHERE, AT_SURFACE, AT_OR_BELOW_SURFACE, BELOW_SURFACE, AT_OR_ABOVE_SURFACE, ABOVE_SURFACE; + ANYWHERE, AT_SURFACE, AT_GROUND, BELOW_SURFACE, BELOW_GROUND, ABOVE_SURFACE, ABOVE_GROUND; public BlockPos getBlockPos(World world, Random random, int x, int z) { - int surfaceY; + int tempY; switch(this) { case AT_SURFACE: - // always at world surface + // always at the 'surface level' - to be precise, the air block directly above land or sea return world.getHeight(new BlockPos(x, 0, z)); - case AT_OR_BELOW_SURFACE: - // random point below or at surface - surfaceY = world.getHeight(new BlockPos(x, 0, z)).getY(); - return new BlockPos(x, nextIntBetween(random, 1, surfaceY), z); + case AT_GROUND: + // always at the 'ground level' - the air or water block directly above the land, or the bottom of the sea bed + return world.getTopSolidOrLiquidBlock(new BlockPos(x, 0, z)); case BELOW_SURFACE: - // random point below surface - surfaceY = world.getHeight(new BlockPos(x, 0, z)).getY(); - return new BlockPos(x, nextIntBetween(random, 1, surfaceY - 1), z); - case AT_OR_ABOVE_SURFACE: - // random point at or above surface - surfaceY = world.getHeight(new BlockPos(x, 0, z)).getY(); - return new BlockPos(x, GeneratorUtils.nextIntBetween(random, surfaceY, 255), z); + // random point below surface (but possibly in the sea) + tempY = world.getHeight(new BlockPos(x, 0, z)).getY(); + return new BlockPos(x, nextIntBetween(random, 1, tempY - 1), z); + case BELOW_GROUND: + // random point below ground (and below sea) + tempY = world.getTopSolidOrLiquidBlock(new BlockPos(x, 0, z)).getY(); + return new BlockPos(x, nextIntBetween(random, 1, tempY - 1), z); case ABOVE_SURFACE: - // random point above surface - surfaceY = world.getHeight(new BlockPos(x, 0, z)).getY(); - return new BlockPos(x, GeneratorUtils.nextIntBetween(random, surfaceY + 1, 255), z); + // random point above surface (amd above the sea) + tempY = world.getHeight(new BlockPos(x, 0, z)).getY(); + return new BlockPos(x, GeneratorUtils.nextIntBetween(random, tempY, 255), z); + case ABOVE_GROUND: + // random point above ground (but possibly in the sea) + tempY = world.getTopSolidOrLiquidBlock(new BlockPos(x, 0, z)).getY(); + return new BlockPos(x, GeneratorUtils.nextIntBetween(random, tempY, 255), z); case ANYWHERE: default: // random y coord return new BlockPos(x, nextIntBetween(random, 1, 255), z); diff --git a/src/main/java/biomesoplenty/common/world/feature/GeneratorBlobs.java b/src/main/java/biomesoplenty/common/world/feature/GeneratorBlobs.java index c54f00972..683d52de8 100644 --- a/src/main/java/biomesoplenty/common/world/feature/GeneratorBlobs.java +++ b/src/main/java/biomesoplenty/common/world/feature/GeneratorBlobs.java @@ -38,7 +38,7 @@ public class GeneratorBlobs extends BOPGeneratorBase protected float maxRadius = 5.0F; protected float radiusFalloff = 0.5F; protected int numBalls = 3; - protected ScatterYMethod scatterYMethod = ScatterYMethod.AT_OR_BELOW_SURFACE; + protected ScatterYMethod scatterYMethod = ScatterYMethod.BELOW_SURFACE; public Builder amountPerChunk(float a) {this.amountPerChunk = a; return this;} public Builder placeOn(IBlockPosQuery a) {this.placeOn = a; return this;} diff --git a/src/main/java/biomesoplenty/common/world/feature/GeneratorDoubleFlora.java b/src/main/java/biomesoplenty/common/world/feature/GeneratorDoubleFlora.java index d92242370..5e0fd0807 100644 --- a/src/main/java/biomesoplenty/common/world/feature/GeneratorDoubleFlora.java +++ b/src/main/java/biomesoplenty/common/world/feature/GeneratorDoubleFlora.java @@ -41,7 +41,7 @@ public class GeneratorDoubleFlora extends BOPGeneratorBase protected IBlockPosQuery replace = new BlockQueryMaterial(Material.air); protected IBlockState bottomState = BOPBlocks.double_plant.getDefaultState().withProperty(BlockBOPDoublePlant.VARIANT, BlockBOPDoublePlant.DoublePlantType.FLAX).withProperty(BlockBOPDoublePlant.HALF, BlockBOPDoubleDecoration.Half.LOWER); protected IBlockState topState = BOPBlocks.double_plant.getDefaultState().withProperty(BlockBOPDoublePlant.VARIANT, BlockBOPDoublePlant.DoublePlantType.FLAX).withProperty(BlockBOPDoublePlant.HALF, BlockBOPDoubleDecoration.Half.UPPER); - protected int generationAttempts = 20; + protected int generationAttempts = 32; public Builder amountPerChunk(float a) {this.amountPerChunk = a; return this;} public Builder replace(IBlockPosQuery a) {this.replace = a; return this;} diff --git a/src/main/java/biomesoplenty/common/world/feature/GeneratorFlora.java b/src/main/java/biomesoplenty/common/world/feature/GeneratorFlora.java index 3dbd3889c..4aef546a9 100644 --- a/src/main/java/biomesoplenty/common/world/feature/GeneratorFlora.java +++ b/src/main/java/biomesoplenty/common/world/feature/GeneratorFlora.java @@ -28,7 +28,7 @@ import biomesoplenty.common.block.BlockBOPPlant; import biomesoplenty.common.block.BlockBOPDecoration; import biomesoplenty.common.enums.BOPFlowers; import biomesoplenty.common.enums.BOPPlants; -import biomesoplenty.common.util.biome.GeneratorUtils; +import biomesoplenty.common.util.biome.GeneratorUtils.ScatterYMethod; import biomesoplenty.common.util.block.BlockQuery; import biomesoplenty.common.util.block.BlockQuery.*; import biomesoplenty.common.util.config.BOPConfig.IConfigObj; @@ -41,7 +41,8 @@ public class GeneratorFlora extends BOPGeneratorBase protected float amountPerChunk = 1.0F; protected IBlockPosQuery replace = new BlockQueryMaterial(Material.air); protected IBlockState with = Blocks.red_flower.getDefaultState(); - protected int generationAttempts = 20; + protected int generationAttempts = 32; + protected ScatterYMethod scatterYMethod = ScatterYMethod.AT_SURFACE; public Builder amountPerChunk(float a) {this.amountPerChunk = a; return this;} public Builder replace(IBlockPosQuery a) {this.replace = a; return this;} @@ -61,11 +62,13 @@ public class GeneratorFlora extends BOPGeneratorBase } public Builder with(BlockTallGrass.EnumType a) {this.with = Blocks.tallgrass.getDefaultState().withProperty(BlockTallGrass.TYPE, a); return this;} public Builder generationAttempts(int a) {this.generationAttempts = a; return this;} + public Builder scatterYMethod(ScatterYMethod a) {this.scatterYMethod = a; return this;} + @Override public GeneratorFlora create() { - return new GeneratorFlora(this.amountPerChunk, this.replace, this.with, this.generationAttempts); + return new GeneratorFlora(this.amountPerChunk, this.replace, this.with, this.generationAttempts, this.scatterYMethod); } } @@ -73,20 +76,21 @@ public class GeneratorFlora extends BOPGeneratorBase protected IBlockPosQuery replace; protected IBlockState with; protected int generationAttempts; + protected ScatterYMethod scatterYMethod; - public GeneratorFlora(float amountPerChunk, IBlockPosQuery replace, IBlockState with, int generationAttempts) + public GeneratorFlora(float amountPerChunk, IBlockPosQuery replace, IBlockState with, int generationAttempts, ScatterYMethod scatterYMethod) { super(amountPerChunk); this.replace = replace; this.with = with; this.generationAttempts = generationAttempts; + this.scatterYMethod = scatterYMethod; } @Override public BlockPos getScatterY(World world, Random random, int x, int z) { - // always at world surface - return GeneratorUtils.ScatterYMethod.AT_SURFACE.getBlockPos(world, random, x, z); + return this.scatterYMethod.getBlockPos(world, random, x, z); } @Override @@ -127,6 +131,8 @@ public class GeneratorFlora extends BOPGeneratorBase this.replace = conf.getBlockPosQuery("replace", this.replace); this.with = conf.getBlockState("with", this.with); this.generationAttempts = conf.getInt("generationAttempts", this.generationAttempts); + this.scatterYMethod = conf.getEnum("scatterYMethod", this.scatterYMethod, ScatterYMethod.class); + } } diff --git a/src/main/java/biomesoplenty/common/world/feature/GeneratorGrass.java b/src/main/java/biomesoplenty/common/world/feature/GeneratorGrass.java index 225d90bf8..9bee8a753 100644 --- a/src/main/java/biomesoplenty/common/world/feature/GeneratorGrass.java +++ b/src/main/java/biomesoplenty/common/world/feature/GeneratorGrass.java @@ -15,6 +15,7 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import biomesoplenty.common.block.BlockBOPPlant; import biomesoplenty.common.enums.BOPPlants; +import biomesoplenty.common.util.biome.GeneratorUtils.ScatterYMethod; import biomesoplenty.common.util.block.BlockQuery; import biomesoplenty.common.util.block.BlockQuery.BlockQueryBlock; import biomesoplenty.common.util.block.BlockQuery.BlockQueryMaterial; @@ -32,6 +33,7 @@ public class GeneratorGrass extends GeneratorFlora protected int generationAttempts = 96; protected IBlockState with = Blocks.tallgrass.getDefaultState(); protected IBlockPosQuery replace = new BlockQueryMaterial(Material.air); + protected ScatterYMethod scatterYMethod = ScatterYMethod.AT_SURFACE; public Builder amountPerChunk(float a) {this.amountPerChunk = a; return this;} public Builder replace(IBlockPosQuery a) {this.replace = a; return this;} @@ -42,17 +44,18 @@ public class GeneratorGrass extends GeneratorFlora public Builder with(BOPPlants a) {this.with = BlockBOPPlant.paging.getVariantState(a); return this;} public Builder with(BlockTallGrass.EnumType a) {this.with = Blocks.tallgrass.getDefaultState().withProperty(BlockTallGrass.TYPE, a); return this;} public Builder generationAttempts(int a) {this.generationAttempts = a; return this;} + public Builder scatterYMethod(ScatterYMethod a) {this.scatterYMethod = a; return this;} @Override public GeneratorGrass create() { - return new GeneratorGrass(this.amountPerChunk, this.replace, this.with, this.generationAttempts); + return new GeneratorGrass(this.amountPerChunk, this.replace, this.with, this.generationAttempts, this.scatterYMethod); } } - public GeneratorGrass(float amountPerChunk, IBlockPosQuery replace, IBlockState with, int generationAttempts) + public GeneratorGrass(float amountPerChunk, IBlockPosQuery replace, IBlockState with, int generationAttempts, ScatterYMethod scatterYMethod) { - super(amountPerChunk, replace, with, generationAttempts); + super(amountPerChunk, replace, with, generationAttempts, scatterYMethod); } } diff --git a/src/main/java/biomesoplenty/common/world/feature/GeneratorSplotches.java b/src/main/java/biomesoplenty/common/world/feature/GeneratorSplotches.java index 685b36dd1..240a58e3b 100644 --- a/src/main/java/biomesoplenty/common/world/feature/GeneratorSplotches.java +++ b/src/main/java/biomesoplenty/common/world/feature/GeneratorSplotches.java @@ -32,7 +32,7 @@ public class GeneratorSplotches extends BOPGeneratorBase protected IBlockPosQuery replace = new BlockQueryMaterial(Material.grass, Material.ground); protected IBlockState with = Blocks.cobblestone.getDefaultState(); protected int splotchSize = 8; - protected ScatterYMethod scatterYMethod = ScatterYMethod.AT_OR_BELOW_SURFACE; + protected ScatterYMethod scatterYMethod = ScatterYMethod.BELOW_SURFACE; public Builder amountPerChunk(float a) {this.amountPerChunk = a; return this;} public Builder replace(IBlockPosQuery a) {this.replace = a; return this;} diff --git a/src/main/java/biomesoplenty/common/world/feature/tree/GeneratorBayouTree.java b/src/main/java/biomesoplenty/common/world/feature/tree/GeneratorBayouTree.java new file mode 100644 index 000000000..7746eb13f --- /dev/null +++ b/src/main/java/biomesoplenty/common/world/feature/tree/GeneratorBayouTree.java @@ -0,0 +1,381 @@ +/******************************************************************************* + * Copyright 2015, the Biomes O' Plenty Team + * + * This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License. + * + * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/. + ******************************************************************************/ + +package biomesoplenty.common.world.feature.tree; +import java.util.Random; + +import biomesoplenty.api.biome.generation.BOPGeneratorBase; +import biomesoplenty.api.block.BlockQueries; +import biomesoplenty.common.block.BlockBOPLeaves; +import biomesoplenty.common.block.BlockBOPLog; +import biomesoplenty.common.enums.BOPTrees; +import biomesoplenty.common.enums.BOPWoods; +import biomesoplenty.common.util.biome.GeneratorUtils; +import biomesoplenty.common.util.block.BlockQuery; +import biomesoplenty.common.util.block.BlockQuery.BlockQueryBlock; +import biomesoplenty.common.util.block.BlockQuery.BlockQueryParseException; +import biomesoplenty.common.util.block.BlockQuery.BlockQueryState; +import biomesoplenty.common.util.block.BlockQuery.IBlockPosQuery; +import biomesoplenty.common.util.config.BOPConfig.IConfigObj; +import net.minecraft.block.Block; +import net.minecraft.block.BlockNewLeaf; +import net.minecraft.block.BlockNewLog; +import net.minecraft.block.BlockOldLeaf; +import net.minecraft.block.BlockOldLog; +import net.minecraft.block.BlockPlanks; +import net.minecraft.block.BlockVine; +import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +public class GeneratorBayouTree extends BOPGeneratorBase +{ + + public static class Builder implements IGeneratorBuilder + { + protected float amountPerChunk = 1.0F; + protected int minHeight = 8; + protected int maxHeight = 18; + protected int minLeavesRadius = 2; + protected int leavesGradient = 4; + protected int vineAttempts = 10; + protected int maxVineLength = 20; + protected IBlockPosQuery placeOn = BlockQueries.fertile; + protected IBlockPosQuery replace = BlockQueries.airOrLeaves; + protected IBlockPosQuery rootsReplace = BlockQueries.rootsCanDigThrough; + protected IBlockState log = Blocks.log.getDefaultState(); + protected IBlockState leaves = Blocks.leaves.getDefaultState(); + protected IBlockState vine = Blocks.vine.getDefaultState(); + + public Builder amountPerChunk(float a) {this.amountPerChunk = a; return this;} + public Builder minHeight(int a) {this.minHeight = a; return this;} + public Builder maxHeight(int a) {this.maxHeight = a; return this;} + public Builder minLeavesRadius(int a) {this.minLeavesRadius = a; return this;} + public Builder leavesGradient(int a) {this.leavesGradient = a; return this;} + public Builder vineAttempts(int a) {this.vineAttempts = a; return this;} + public Builder maxVineLength(int a) {this.maxVineLength = a; return this;} + public Builder placeOn(IBlockPosQuery a) {this.placeOn = a; return this;} + public Builder placeOn(String a) throws BlockQueryParseException {this.placeOn = BlockQuery.parseQueryString(a); return this;} + public Builder placeOn(Block a) {this.placeOn = new BlockQueryBlock(a); return this;} + public Builder placeOn(IBlockState a) {this.placeOn = new BlockQueryState(a); return this;} + public Builder replace(IBlockPosQuery a) {this.replace = a; return this;} + public Builder replace(String a) throws BlockQueryParseException {this.replace = BlockQuery.parseQueryString(a); return this;} + public Builder replace(Block a) {this.replace = new BlockQueryBlock(a); return this;} + public Builder replace(IBlockState a) {this.replace = new BlockQueryState(a); return this;} + public Builder rootsReplace(IBlockPosQuery a) {this.replace = a; return this;} + public Builder rootsReplace(String a) throws BlockQueryParseException {this.replace = BlockQuery.parseQueryString(a); return this;} + public Builder rootsReplace(Block a) {this.replace = new BlockQueryBlock(a); return this;} + public Builder rootsReplace(IBlockState a) {this.replace = new BlockQueryState(a); return this;} + public Builder log(IBlockState a) {this.log = a; return this;} + public Builder log(BOPWoods a) {this.log = BlockBOPLog.paging.getVariantState(a); return this;} + public Builder log(BlockPlanks.EnumType a) + { + if (a.getMetadata() < 4) + { + this.log = Blocks.log.getDefaultState().withProperty(BlockOldLog.VARIANT, a); + } else { + this.log = Blocks.log2.getDefaultState().withProperty(BlockNewLog.VARIANT, a); + } + return this; + } + public Builder leaves(IBlockState a) {this.leaves = a; return this;} + public Builder leaves(BOPTrees a) {this.leaves = BlockBOPLeaves.paging.getVariantState(a); return this;} + public Builder leaves(BlockPlanks.EnumType a) + { + if (a.getMetadata() < 4) + { + this.leaves = Blocks.leaves.getDefaultState().withProperty(BlockOldLeaf.VARIANT, a); + } else { + this.leaves = Blocks.leaves2.getDefaultState().withProperty(BlockNewLeaf.VARIANT, a); + } + return this; + } + public Builder vine(IBlockState a) + { + if (a.getBlock() instanceof BlockVine) + { + this.vine = a; + } else { + throw new IllegalArgumentException("vine must use a BlockVine block"); + } + return this; + } + + + @Override + public GeneratorBayouTree create() + { + return new GeneratorBayouTree(this.amountPerChunk, this.minHeight, this.maxHeight, this.minLeavesRadius, this.leavesGradient, this.vineAttempts, this.maxVineLength, this.placeOn, this.replace, this.rootsReplace, this.log, this.leaves, this.vine); + } + } + + + private int minHeight; + private int maxHeight; + private int minLeavesRadius; + private int leavesGradient; + private int vineAttempts; + private int maxVineLength; + private IBlockPosQuery placeOn; + private IBlockPosQuery replace; + private IBlockPosQuery rootsReplace; + private IBlockState log; + private IBlockState leaves; + private IBlockState vine; + + public GeneratorBayouTree(float amountPerChunk, int minHeight, int maxHeight, int minLeavesRadius, int leavesGradient, int vineAttempts, int maxVineLength, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockPosQuery rootsReplace, IBlockState log, IBlockState leaves, IBlockState vine) + { + super(amountPerChunk); + + this.minHeight = minHeight; + this.maxHeight = maxHeight; + this.minLeavesRadius = minLeavesRadius; + this.leavesGradient = leavesGradient; + this.vineAttempts = vineAttempts; + this.maxVineLength = maxVineLength; + this.placeOn = placeOn; + this.replace = replace; + this.rootsReplace = rootsReplace; + this.log = log; + this.leaves = leaves; + this.vine = vine; + } + + @Override + public BlockPos getScatterY(World world, Random random, int x, int z) + { + // always at world surface + return GeneratorUtils.ScatterYMethod.AT_GROUND.getBlockPos(world, random, x, z); + } + + + public boolean setLeaves(World world, BlockPos pos) + { + if (this.replace.matches(world, pos)) + { + world.setBlockState(pos, this.leaves, 2); + return true; + } + return false; + } + + public boolean setLog(World world, BlockPos pos) + { + if (this.replace.matches(world, pos)) + { + world.setBlockState(pos, this.log, 2); + return true; + } + return false; + } + + public boolean setRoot(World world, BlockPos pos) + { + if (this.rootsReplace.matches(world, pos)) + { + world.setBlockState(pos, this.log, 2); + return true; + } + return false; + } + + public boolean setVine(World world, Random rand, BlockPos pos, EnumFacing side, int length) + { + IBlockState vineState = this.vine.withProperty(BlockVine.NORTH, Boolean.valueOf(side == EnumFacing.NORTH)).withProperty(BlockVine.EAST, Boolean.valueOf(side == EnumFacing.EAST)).withProperty(BlockVine.SOUTH, Boolean.valueOf(side == EnumFacing.SOUTH)).withProperty(BlockVine.WEST, Boolean.valueOf(side == EnumFacing.WEST)); + boolean setOne = false; + while (this.replace.matches(world, pos) && length > 0 && rand.nextInt(12) > 0) + { + world.setBlockState(pos, vineState, 2); + setOne = true; + length--; + pos = pos.down(); + } + return setOne; + } + + public boolean checkRootViable(World world, BlockPos pos, int rootHeight, EnumFacing direction) + { + // a viable root has an path which roots can dig through from trunk to some fertile ground + pos = pos.offset(direction).up(rootHeight - 1); + for (int i = 0; i < rootHeight; i++) + { + if (!this.rootsReplace.matches(world, pos)) {return false;} + pos = pos.down(); + if (this.placeOn.matches(world, pos)) {return true;} + } + return false; + } + + public boolean checkSpace(World world, BlockPos pos, int rootHeight, int middleHeight, int height) + { + + // we want at least 2 of the roots to be viable + int rootsOk = 0; + for (EnumFacing direction : EnumFacing.Plane.HORIZONTAL) + { + if (this.checkRootViable(world, pos, rootHeight, direction)) {rootsOk++;} + } + if (rootsOk < 2) {return false;} + + // check there's some space for the trunk and leaves too + for (int y = rootHeight; y <= height; y++) + { + // require 1x1 for the trunk, 3x3 for the leaves + int radius = (y <= (rootHeight + middleHeight) ? 0 : 1); + for (int x = -radius; x <= radius; x++) + { + for (int z = -radius; z <= radius; z++) + { + BlockPos pos1 = pos.add(x, y, z); + // note, there may be a sapling on the first layer - make sure this.replace matches it! + if (pos1.getY() >= 255 || !this.replace.matches(world, pos1)) + { + return false; + } + } + } + } + return true; + } + + public void generateTop(World world, Random random, BlockPos pos, int topHeight) + { + + for (int y = 0; y < topHeight; y++) + { + int radius = Math.min(3, this.minLeavesRadius + (topHeight - y) / this.leavesGradient); + + for (int x = -radius; x <= radius; ++x) + { + for (int z = -radius; z <= radius; ++z) + { + // too far away and the leaves will decay + int dist = Math.abs(x) + Math.abs(z); + if (dist < 4 || (dist == 4 && random.nextInt(2) == 0)) + { + this.setLeaves(world, pos.add(x, y, z)); + } + } + } + if (y < topHeight - 1) + { + // add the trunk in the middle + this.setLog(world, pos.add(0, y, 0)); + } else { + // add leaves on top for certain + this.setLeaves(world, pos.add(0, y, 0)); + } + } + } + + public void generateRoots(World world, Random random, BlockPos pos, int rootHeight) + { + for (int i = 0; i < rootHeight; i++) + { + this.setRoot(world, pos.north()); + this.setRoot(world, pos.east()); + this.setRoot(world, pos.south()); + this.setRoot(world, pos.west()); + pos = pos.up(); + } + this.setRoot(world, pos.down()); + } + + @Override + public boolean generate(World world, Random random, BlockPos startPos) + { + + if (!this.placeOn.matches(world, startPos.down())) + { + // Abandon if we can't place the tree on this block + return false; + } + + // Choose heights + int height = GeneratorUtils.nextIntBetween(random, this.minHeight, this.maxHeight); + + int topHeight = Math.min(6, GeneratorUtils.nextIntBetween(random, height / 5, height / 3)); + int rootHeight = Math.min(5, GeneratorUtils.nextIntBetween(random, height / 4, height / 2)); + int middleHeight = height - topHeight - rootHeight; + if (middleHeight < 1) {return false;} + + // Start in the ground block + BlockPos pos = startPos.down(); + + if (!this.checkSpace(world, pos, rootHeight, middleHeight, height)) + { + // Abandon if there isn't enough room + return false; + } + + // Generate roots + this.generateRoots(world, random, pos, rootHeight); + pos = pos.up(rootHeight); + + // Generate middle of tree (trunk only) + for(int i = 0; i < middleHeight; i++) + { + this.setLog(world, pos); + pos = pos.up(); + } + + // Generate the top of the tree + this.generateTop(world, random, pos, topHeight); + + // Add vines + int maxLeavesRadius = this.minLeavesRadius + topHeight / this.leavesGradient; + this.addVines(world, random, startPos, height, maxLeavesRadius, this.vineAttempts); + + return true; + } + + protected void addVines(World world, Random rand, BlockPos startPos, int height, int leavesRadius, int generationAttempts) + { + for (int i = 0; i < generationAttempts; i++) + { + // choose a random direction + EnumFacing direction = EnumFacing.Plane.HORIZONTAL.random(rand); + EnumFacing back = direction.getOpposite(); + EnumFacing sideways = direction.rotateY(); + + // choose a random starting point somewhere just outside the boundary of the tree + BlockPos pos = startPos.up(GeneratorUtils.nextIntBetween(rand, 2, height)).offset(direction, leavesRadius + 1).offset(sideways, GeneratorUtils.nextIntBetween(rand, -leavesRadius, leavesRadius)); + + // move back towards the center until we meet a leaf or log, then stick a vine on it + IBlockState state; + for (int l = 0; l < leavesRadius; l++) + { + state = world.getBlockState(pos.offset(back, 1 + l)); + if (state == this.leaves || state == this.log) { + this.setVine(world, rand, pos.offset(back, l), back, this.maxVineLength); + break; + } + } + } + } + + + @Override + public void configure(IConfigObj conf) + { + this.amountPerChunk = conf.getFloat("amountPerChunk", this.amountPerChunk); + this.minHeight = conf.getInt("minHeight", this.minHeight); + this.minLeavesRadius = conf.getInt("minLeavesRadius", this.minLeavesRadius); + this.leavesGradient = conf.getInt("leavesGradient", this.leavesGradient); + this.vineAttempts = conf.getInt("vineAttempts", this.vineAttempts); + this.maxVineLength = conf.getInt("maxVineLength", this.maxVineLength); + this.placeOn = conf.getBlockPosQuery("placeOn", this.placeOn); + this.replace = conf.getBlockPosQuery("replace", this.replace); + this.rootsReplace = conf.getBlockPosQuery("rootsReplace", this.rootsReplace); + this.log = conf.getBlockState("logState", this.log); + this.leaves = conf.getBlockState("leavesState", this.leaves); + this.vine = conf.getBlockState("vinesState", this.vine); + } +} \ No newline at end of file diff --git a/src/main/java/biomesoplenty/common/world/feature/tree/GeneratorBulbTree.java b/src/main/java/biomesoplenty/common/world/feature/tree/GeneratorBulbTree.java index e6c688786..25020959d 100644 --- a/src/main/java/biomesoplenty/common/world/feature/tree/GeneratorBulbTree.java +++ b/src/main/java/biomesoplenty/common/world/feature/tree/GeneratorBulbTree.java @@ -10,15 +10,14 @@ package biomesoplenty.common.world.feature.tree; import java.util.Random; import biomesoplenty.api.biome.generation.BOPGeneratorBase; +import biomesoplenty.api.block.BlockQueries; import biomesoplenty.common.block.BlockBOPLeaves; import biomesoplenty.common.block.BlockBOPLog; import biomesoplenty.common.enums.BOPTrees; import biomesoplenty.common.enums.BOPWoods; import biomesoplenty.common.util.biome.GeneratorUtils; import biomesoplenty.common.util.block.BlockQuery; -import biomesoplenty.common.util.block.BlockQuery.BlockPosQueryOr; import biomesoplenty.common.util.block.BlockQuery.BlockQueryBlock; -import biomesoplenty.common.util.block.BlockQuery.BlockQueryMaterial; import biomesoplenty.common.util.block.BlockQuery.BlockQueryParseException; import biomesoplenty.common.util.block.BlockQuery.BlockQueryState; import biomesoplenty.common.util.block.BlockQuery.IBlockPosQuery; @@ -31,7 +30,6 @@ import net.minecraft.block.BlockOldLeaf; import net.minecraft.block.BlockOldLog; import net.minecraft.block.BlockPlanks; import net.minecraft.block.BlockVine; -import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.util.BlockPos; @@ -46,8 +44,8 @@ public class GeneratorBulbTree extends BOPGeneratorBase protected float amountPerChunk = 1.0F; protected int minHeight = 6; protected int maxHeight = 12; - protected IBlockPosQuery placeOn = new BlockPosQueryOr(new BlockQueryMaterial(Material.ground), new BlockQueryMaterial(Material.grass)); - protected IBlockPosQuery replace = new BlockPosQueryOr(new BlockQueryMaterial(Material.air), new BlockQueryMaterial(Material.leaves), new BlockQueryMaterial(Material.plants)); + protected IBlockPosQuery placeOn = BlockQueries.fertile; + protected IBlockPosQuery replace = BlockQueries.airOrLeaves; protected IBlockState log = Blocks.log.getDefaultState(); protected IBlockState leaves = Blocks.leaves.getDefaultState(); protected IBlockState vine = Blocks.vine.getDefaultState();