Add Bayou biome, GeneratorBayouTree and some adjustments to other generators

This commit is contained in:
Cheeserolls 2015-06-11 22:03:52 +01:00
parent 1d7217a78d
commit 56e5fbfaa8
20 changed files with 570 additions and 44 deletions

View File

@ -18,6 +18,7 @@ public class BOPBiomes
public static Optional<BiomeGenBase> alps = Optional.absent();
public static Optional<BiomeGenBase> arctic = Optional.absent();
public static Optional<BiomeGenBase> bamboo_forest = Optional.absent();
public static Optional<BiomeGenBase> bayou = Optional.absent();
public static Optional<BiomeGenBase> crag = Optional.absent();
public static Optional<BiomeGenBase> chaparral = Optional.absent();
public static Optional<BiomeGenBase> denseForest = Optional.absent();

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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

View File

@ -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());

View File

@ -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:

View File

@ -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:

View File

@ -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");

View File

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

View File

@ -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());

View File

@ -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);

View File

@ -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;}

View File

@ -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;}

View File

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

View File

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

View File

@ -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;}

View File

@ -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<GeneratorBayouTree>
{
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);
}
}

View File

@ -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();