Use inheritance to avoid code duplication in Generators

This commit is contained in:
Cheeserolls 2015-06-15 18:39:44 +01:00
parent 2783bcebba
commit ec0123e9ea
31 changed files with 840 additions and 1206 deletions

View file

@ -34,6 +34,16 @@ public abstract class BOPGeneratorBase implements IGenerator
this.amountPerChunk = amountPerChunk;
}
protected static abstract class InnerBuilder<T extends InnerBuilder<T, G>, G extends BOPGeneratorBase>
{
protected T self() {return (T)this;}
protected float amountPerChunk;
public T amountPerChunk(float amountPerChunk) {this.amountPerChunk = amountPerChunk; return this.self();}
public abstract G create();
}
@Override
public void setName(String name)
{

View file

@ -71,7 +71,7 @@ public class BiomeGenBayou extends BOPBiome
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());
this.addGenerator("dead_logs", GeneratorStage.TREE, (new GeneratorLogs.Builder()).amountPerChunk(1.5F).log(BOPWoods.DEAD).create());
this.addGenerator("dead_logs", GeneratorStage.TREE, (new GeneratorLogs.Builder()).amountPerChunk(1.5F).with(BOPWoods.DEAD).create());
// grasses
GeneratorWeighted grassGenerator = new GeneratorWeighted(10.0F);

View file

@ -64,7 +64,7 @@ public class BiomeGenChaparral extends BOPBiome
grassGenerator.add("dampgrass", 1, (new GeneratorGrass.Builder()).with(BOPPlants.DAMPGRASS).create());
// trees
this.addGenerator("trees", GeneratorStage.TREE, new GeneratorBush(8, Blocks.log.getDefaultState(), Blocks.leaves.getDefaultState()));
this.addGenerator("trees", GeneratorStage.TREE, (new GeneratorBush.Builder()).amountPerChunk(8).create());
// other plants
this.addGenerator("berry_bushes", GeneratorStage.FLOWERS,(new GeneratorFlora.Builder()).amountPerChunk(0.2F).with(BOPPlants.BERRYBUSH).create());

View file

@ -41,8 +41,8 @@ public class BiomeGenHighland extends BOPBiome
this.addGenerator("wild_carrots", GeneratorStage.FLOWERS,(new GeneratorFlora.Builder()).amountPerChunk(0.1F).with(BOPPlants.WILDCARROT).create());
// boulders
this.addGenerator("boulders", GeneratorStage.SAND, (new GeneratorBlobs.Builder()).amountPerChunk(0.5F).placeOn(Blocks.grass).to(Blocks.cobblestone.getDefaultState()).minRadius(0.3F).maxRadius(1.2F).numBalls(1).scatterYMethod(ScatterYMethod.AT_SURFACE).create());
this.addGenerator("big_boulders", GeneratorStage.SAND, (new GeneratorBlobs.Builder()).amountPerChunk(0.1F).placeOn(Blocks.grass).to(Blocks.cobblestone.getDefaultState()).minRadius(0.3F).maxRadius(4.0F).numBalls(3).scatterYMethod(ScatterYMethod.AT_SURFACE).create());
this.addGenerator("boulders", GeneratorStage.SAND, (new GeneratorBlobs.Builder()).amountPerChunk(0.5F).placeOn(Blocks.grass).with(Blocks.cobblestone.getDefaultState()).minRadius(0.3F).maxRadius(1.2F).numBalls(1).scatterYMethod(ScatterYMethod.AT_SURFACE).create());
this.addGenerator("big_boulders", GeneratorStage.SAND, (new GeneratorBlobs.Builder()).amountPerChunk(0.1F).placeOn(Blocks.grass).with(Blocks.cobblestone.getDefaultState()).minRadius(0.3F).maxRadius(4.0F).numBalls(3).scatterYMethod(ScatterYMethod.AT_SURFACE).create());
// grasses
GeneratorWeighted grassGenerator = new GeneratorWeighted(10);

View file

@ -114,8 +114,8 @@ public class BiomeGenMountain extends BOPBiome
treeGenerator.add("pine", 1, (new GeneratorPineTree.Builder()).minHeight(6).maxHeight(18).placeOn(suitableTreePosition).create());
GeneratorWeighted logsGenerator = new GeneratorWeighted(2.5F);
this.addGenerator("logs", GeneratorStage.TREE, logsGenerator);
logsGenerator.add("pine_logs", 1, (new GeneratorLogs.Builder()).placeOn(suitableTreePosition).log(BOPWoods.PINE).create());
logsGenerator.add("dead_logs", 1, (new GeneratorLogs.Builder()).placeOn(suitableTreePosition).log(BOPWoods.DEAD).create());
logsGenerator.add("pine_logs", 1, (new GeneratorLogs.Builder()).placeOn(suitableTreePosition).with(BOPWoods.PINE).create());
logsGenerator.add("dead_logs", 1, (new GeneratorLogs.Builder()).placeOn(suitableTreePosition).with(BOPWoods.DEAD).create());
// grasses
GeneratorWeighted grassGenerator = new GeneratorWeighted(5.0F);

View file

@ -44,7 +44,7 @@ public class BiomeGenTundra extends BOPBiome
this.spawnableCreatureList.clear();
// boulders
this.addGenerator("boulders", GeneratorStage.SAND, (new GeneratorBlobs.Builder()).amountPerChunk(0.5F).placeOn(Blocks.grass).to(Blocks.cobblestone.getDefaultState()).minRadius(0.3F).maxRadius(1.2F).numBalls(1).scatterYMethod(ScatterYMethod.AT_SURFACE).create());
this.addGenerator("boulders", GeneratorStage.SAND, (new GeneratorBlobs.Builder()).amountPerChunk(0.5F).placeOn(Blocks.grass).with(Blocks.cobblestone.getDefaultState()).minRadius(0.3F).maxRadius(1.2F).numBalls(1).scatterYMethod(ScatterYMethod.AT_SURFACE).create());
// sand & gravel
this.addGenerator("sand", GeneratorStage.SAND_PASS2, (new GeneratorWaterside.Builder()).amountPerChunk(8).maxRadius(7).with(Blocks.sand.getDefaultState()).create());

View file

@ -90,7 +90,7 @@ public class BiomeGenWoodland extends BOPBiome
GeneratorWeighted logsGenerator = new GeneratorWeighted(2.5F);
this.addGenerator("logs", GeneratorStage.TREE, logsGenerator);
logsGenerator.add("oak_logs", 1, (new GeneratorLogs.Builder()).create());
logsGenerator.add("dead_logs", 1, (new GeneratorLogs.Builder()).log(BOPWoods.DEAD).create());
logsGenerator.add("dead_logs", 1, (new GeneratorLogs.Builder()).with(BOPWoods.DEAD).create());
// gem
this.addGenerator("amber", GeneratorStage.SAND, (new GeneratorOreSingle.Builder()).amountPerChunk(12).with(BOPGems.AMBER).create());

View file

@ -16,10 +16,7 @@ import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
@ -65,17 +62,6 @@ public class GeneratorUtils
return state;
}
public static boolean isBlockTreeReplacable(Block block)
{
return block.getMaterial() == Material.air || block.getMaterial() == Material.leaves || block == Blocks.grass || block == Blocks.dirt || block == Blocks.log || block == Blocks.log2 || block == Blocks.sapling || block == Blocks.vine;
}
public static boolean canTreeReplace(World world, BlockPos pos)
{
IBlockState state = world.getBlockState(pos);
return state.getBlock().isAir(world, pos) || state.getBlock().isLeaves(world, pos) || state.getBlock().isWood(world, pos) || isBlockTreeReplacable(state.getBlock());
}
public static enum ScatterYMethod

View file

@ -19,6 +19,11 @@ import net.minecraft.world.World;
import biomesoplenty.api.biome.generation.BOPGeneratorBase;
import biomesoplenty.api.block.BlockQueries;
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;
public class GeneratorBigMushroom extends BOPGeneratorBase
@ -70,29 +75,50 @@ public class GeneratorBigMushroom extends BOPGeneratorBase
return (y < (height - 1));
}
}
}
}
public static class Builder implements IGeneratorBuilder<GeneratorBigMushroom>
public static class Builder extends BOPGeneratorBase.InnerBuilder<Builder, GeneratorBigMushroom> implements IGeneratorBuilder<GeneratorBigMushroom>
{
protected float amountPerChunk = 1.0F;
protected BigMushroomType mushroomType = BigMushroomType.BROWN;
protected BigMushroomType mushroomType;
protected IBlockPosQuery placeOn;
protected IBlockPosQuery replace;
public Builder amountPerChunk(float a) {this.amountPerChunk = a; return this;}
public Builder mushroomType(BigMushroomType a) {this.mushroomType = a; return this;}
public Builder placeOn(IBlockPosQuery a) {this.placeOn = a; return this.self();}
public Builder placeOn(String a) throws BlockQueryParseException {this.placeOn = BlockQuery.parseQueryString(a); return this.self();}
public Builder placeOn(Block a) {this.placeOn = new BlockQueryBlock(a); return this.self();}
public Builder placeOn(IBlockState a) {this.placeOn = new BlockQueryState(a); return this.self();}
public Builder replace(IBlockPosQuery a) {this.replace = a; return this.self();}
public Builder replace(String a) throws BlockQueryParseException {this.replace = BlockQuery.parseQueryString(a); return this.self();}
public Builder replace(Block a) {this.replace = new BlockQueryBlock(a); return this.self();}
public Builder replace(IBlockState a) {this.replace = new BlockQueryState(a); return this.self();}
public Builder()
{
this.mushroomType = BigMushroomType.BROWN;
this.placeOn = BlockQueries.fertile;
this.replace = BlockQueries.airOrLeaves;
}
@Override
public GeneratorBigMushroom create()
{
return new GeneratorBigMushroom(this.amountPerChunk, this.mushroomType);
return new GeneratorBigMushroom(this.amountPerChunk, this.placeOn, this.replace, this.mushroomType);
}
}
protected IBlockPosQuery placeOn;
protected IBlockPosQuery replace;
protected BigMushroomType mushroomType;
protected IBlockState mushroomState;
public GeneratorBigMushroom(float amountPerChunk, BigMushroomType mushroomType)
public GeneratorBigMushroom(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, BigMushroomType mushroomType)
{
super(amountPerChunk);
this.placeOn = placeOn;
this.replace = replace;
this.setMushroomType(mushroomType);
}
@ -111,7 +137,7 @@ public class GeneratorBigMushroom extends BOPGeneratorBase
protected void replaceWithMushroom(World world, BlockPos pos, BlockHugeMushroom.EnumType side)
{
if (world.getBlockState(pos).getBlock().canBeReplacedByLeaves(world, pos))
if (this.replace.matches(world, pos))
{
world.setBlockState(pos, this.mushroomState.withProperty(BlockHugeMushroom.VARIANT, side), 2);
}
@ -131,7 +157,7 @@ public class GeneratorBigMushroom extends BOPGeneratorBase
{
for (int z = pos.getZ() - radius; z <= pos.getZ() + radius; ++z)
{
if (!BlockQueries.airOrLeaves.matches(world, new BlockPos(x, y, z)))
if (!this.replace.matches(world, new BlockPos(x, y, z)))
{
return false;
}
@ -151,8 +177,7 @@ public class GeneratorBigMushroom extends BOPGeneratorBase
// check that there's room
if (!this.isEnoughSpace(world, pos, height)) {return false;}
Block blockBelow = world.getBlockState(pos.down()).getBlock();
if (blockBelow != Blocks.dirt && blockBelow != Blocks.grass && blockBelow != Blocks.mycelium)
if (!this.placeOn.matches(world, pos.down()))
{
return false;
}

View file

@ -10,80 +10,67 @@ package biomesoplenty.common.world.feature;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
import biomesoplenty.api.biome.generation.BOPGeneratorBase;
import biomesoplenty.api.block.BlockQueries;
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.BlockQueryParseException;
import biomesoplenty.common.util.block.BlockQuery.BlockQueryState;
import biomesoplenty.common.util.block.BlockQuery.IBlockPosQuery;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
public class GeneratorBlobs extends BOPGeneratorBase
public class GeneratorBlobs extends GeneratorReplacing
{
public static class Builder implements IGeneratorBuilder<GeneratorBlobs>
public static class Builder extends GeneratorReplacing.InnerBuilder<Builder, GeneratorBlobs> implements IGeneratorBuilder<GeneratorBlobs>
{
protected float amountPerChunk = 1.0F;
protected IBlockPosQuery placeOn = BlockQuery.buildOr().blocks(Blocks.stone).materials(Material.ground, Material.grass).create();
protected IBlockState with = Blocks.cobblestone.getDefaultState();
protected float minRadius = 2.0F;
protected float maxRadius = 5.0F;
protected float radiusFalloff = 0.5F;
protected int numBalls = 3;
protected ScatterYMethod scatterYMethod = ScatterYMethod.BELOW_SURFACE;
protected float minRadius;
protected float maxRadius;
protected float radiusFalloff;
protected int numBalls;
public Builder amountPerChunk(float a) {this.amountPerChunk = 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 to(IBlockState a) {this.with = a; return this;}
public Builder minRadius(float a) {this.minRadius = a; return this;}
public Builder maxRadius(float a) {this.maxRadius = a; return this;}
public Builder radiusFalloff(float a) {this.radiusFalloff = a; return this;}
public Builder numBalls(int a) {this.numBalls = a; return this;}
public Builder scatterYMethod(ScatterYMethod a) {this.scatterYMethod = a; return this;}
public Builder minRadius(float a) {this.minRadius = a; return this.self();}
public Builder maxRadius(float a) {this.maxRadius = a; return this.self();}
public Builder radiusFalloff(float a) {this.radiusFalloff = a; return this.self();}
public Builder numBalls(int a) {this.numBalls = a; return this.self();}
public Builder()
{
// defaults
this.amountPerChunk = 1.0F;
this.placeOn = BlockQuery.buildOr().blocks(Blocks.stone).materials(Material.ground, Material.grass).create();
this.replace = BlockQueries.breakable;
this.with = Blocks.cobblestone.getDefaultState();
this.scatterYMethod = ScatterYMethod.BELOW_SURFACE;
this.minRadius = 2.0F;
this.maxRadius = 5.0F;
this.radiusFalloff = 0.5F;
this.numBalls = 3;
}
@Override
public GeneratorBlobs create()
{
return new GeneratorBlobs(this.amountPerChunk, this.placeOn, this.with, this.minRadius, this.maxRadius, this.radiusFalloff, this.numBalls, this.scatterYMethod);
return new GeneratorBlobs(this.amountPerChunk, this.placeOn, this.replace, this.with, this.scatterYMethod, this.minRadius, this.maxRadius, this.radiusFalloff, this.numBalls);
}
}
protected IBlockPosQuery placeOn;
protected IBlockState with;
protected float minRadius;
protected float maxRadius;
protected float radiusFalloff; // should normally be between 0 and 1 so that balls get smaller
protected int numBalls;
protected ScatterYMethod scatterYMethod;
public GeneratorBlobs(float amountPerChunk, IBlockPosQuery placeOn, IBlockState with, float minRadius, float maxRadius, float radiusFalloff, int numBalls, ScatterYMethod scatterYMethod)
public GeneratorBlobs(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState with, ScatterYMethod scatterYMethod, float minRadius, float maxRadius, float radiusFalloff, int numBalls)
{
super(amountPerChunk);
this.with = with;
super(amountPerChunk, placeOn, replace, with, scatterYMethod);
this.minRadius = minRadius;
this.maxRadius = maxRadius;
this.radiusFalloff = radiusFalloff;
this.numBalls = numBalls;
this.placeOn = placeOn;
this.scatterYMethod = scatterYMethod;
}
@Override
public BlockPos getScatterY(World world, Random random, int x, int z)
{
return this.scatterYMethod.getBlockPos(world, random, x, z);
}
@Override
@ -155,7 +142,10 @@ public class GeneratorBlobs extends BOPGeneratorBase
if (px * px + py * py + pz * pz < 1.0D)
{
BlockPos pos = new BlockPos(x, y, z);
world.setBlockState(pos, this.with);
if (this.replace.matches(world, pos))
{
world.setBlockState(pos, this.with);
}
}
}
}

View file

@ -10,75 +10,62 @@ package biomesoplenty.common.world.feature;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import biomesoplenty.api.biome.generation.BOPGeneratorBase;
import biomesoplenty.api.block.BlockQueries;
import biomesoplenty.common.util.biome.GeneratorUtils;
import biomesoplenty.common.util.block.BlockQuery;
import biomesoplenty.common.util.biome.GeneratorUtils.ScatterYMethod;
import biomesoplenty.common.util.block.BlockQuery.BlockQueryMaterial;
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;
public class GeneratorColumns extends BOPGeneratorBase
public class GeneratorColumns extends GeneratorReplacing
{
public static class Builder implements IGeneratorBuilder<GeneratorColumns>
public static class Builder extends GeneratorReplacing.InnerBuilder<Builder, GeneratorColumns> implements IGeneratorBuilder<GeneratorColumns>
{
protected float amountPerChunk = 1.0F;
protected IBlockPosQuery placeOn = new BlockQueryMaterial(Material.ground, Material.grass);
protected IBlockState with = Blocks.cobblestone.getDefaultState();
protected int minHeight = 2;
protected int maxHeight = 4;
protected int generationAttempts = 12;
protected int minHeight;
protected int maxHeight;
protected int generationAttempts;
public Builder amountPerChunk(float a) {this.amountPerChunk = 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 with(IBlockState a) {this.with = 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 generationAttempts(int a) {this.generationAttempts = a; return this;}
public Builder minHeight(int a) {this.minHeight = a; return this.self();}
public Builder maxHeight(int a) {this.maxHeight = a; return this.self();}
public Builder generationAttempts(int a) {this.generationAttempts = a; return this.self();}
public Builder()
{
// defaults
this.amountPerChunk = 1.0F;
this.placeOn = new BlockQueryMaterial(Material.ground, Material.grass);
this.replace = BlockQueries.airOrLeaves;
this.with = Blocks.cobblestone.getDefaultState();
this.scatterYMethod = ScatterYMethod.AT_SURFACE;
this.minHeight = 2;
this.maxHeight = 4;
this.generationAttempts = 12;
}
@Override
public GeneratorColumns create()
{
return new GeneratorColumns(this.amountPerChunk, this.with, this.minHeight, this.maxHeight, this.placeOn, this.generationAttempts);
return new GeneratorColumns(this.amountPerChunk, this.placeOn, this.replace, this.with, this.scatterYMethod, this.minHeight, this.maxHeight, this.generationAttempts);
}
}
protected IBlockPosQuery placeOn;
protected IBlockState with;
protected int minHeight;
protected int maxHeight;
protected int generationAttempts;
public GeneratorColumns(float amountPerChunk, IBlockState with, int minHeight, int maxHeight, IBlockPosQuery placeOn, int generationAttempts)
public GeneratorColumns(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState with, ScatterYMethod scatterYMethod, int minHeight, int maxHeight, int generationAttempts)
{
super(amountPerChunk);
this.with = with;
super(amountPerChunk, placeOn, replace, with, scatterYMethod);
this.minHeight = minHeight;
this.maxHeight = maxHeight;
this.placeOn = placeOn;
this.generationAttempts = generationAttempts;
}
@Override
public BlockPos getScatterY(World world, Random random, int x, int z)
{
// always at world surface
return world.getHeight(new BlockPos(x, 0, z));
}
@Override
public boolean generate(World world, Random rand, BlockPos pos)

View file

@ -10,17 +10,13 @@ package biomesoplenty.common.world.feature;
import java.util.Random;
import biomesoplenty.api.biome.generation.BOPGeneratorBase;
import biomesoplenty.api.block.BOPBlocks;
import biomesoplenty.api.block.BlockQueries;
import biomesoplenty.common.block.BlockBOPDoublePlant;
import biomesoplenty.common.block.BlockBOPDecoration;
import biomesoplenty.common.block.BlockBOPDoubleDecoration;
import biomesoplenty.common.util.biome.GeneratorUtils;
import biomesoplenty.common.util.block.BlockQuery;
import biomesoplenty.common.util.block.BlockQuery.BlockQueryBlock;
import biomesoplenty.common.util.biome.GeneratorUtils.ScatterYMethod;
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;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
import net.minecraft.block.Block;
@ -32,80 +28,77 @@ import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
public class GeneratorDoubleFlora extends BOPGeneratorBase
public class GeneratorDoubleFlora extends GeneratorReplacing
{
public static class Builder implements IGeneratorBuilder<GeneratorDoubleFlora>
public static class Builder extends GeneratorReplacing.InnerBuilder<Builder, GeneratorDoubleFlora> implements IGeneratorBuilder<GeneratorDoubleFlora>
{
protected float amountPerChunk = 1.0F;
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 = 32;
protected int generationAttempts;
protected IBlockState withTop;
public Builder amountPerChunk(float a) {this.amountPerChunk = 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 with(IBlockState bottom, IBlockState top) {this.bottomState = bottom; this.topState = top; return this;}
public Builder generationAttempts(int a) {this.generationAttempts = a; return this.self();}
@Override
public Builder with(IBlockState a) {this.with = a; this.withTop = a; return this.self();}
public Builder with(IBlockState bottom, IBlockState top) {this.with = bottom; this.withTop = top; return this.self();}
public Builder with(BlockBOPDoublePlant.DoublePlantType type)
{
this.bottomState = BOPBlocks.double_plant.getDefaultState().withProperty(BlockBOPDoublePlant.VARIANT, type).withProperty(BlockBOPDoublePlant.HALF, BlockBOPDoubleDecoration.Half.LOWER);
this.topState = BOPBlocks.double_plant.getDefaultState().withProperty(BlockBOPDoublePlant.VARIANT, type).withProperty(BlockBOPDoublePlant.HALF, BlockBOPDoubleDecoration.Half.UPPER);
return this;
this.with = BOPBlocks.double_plant.getDefaultState().withProperty(BlockBOPDoublePlant.VARIANT, type).withProperty(BlockBOPDoublePlant.HALF, BlockBOPDoubleDecoration.Half.LOWER);
this.withTop = BOPBlocks.double_plant.getDefaultState().withProperty(BlockBOPDoublePlant.VARIANT, type).withProperty(BlockBOPDoublePlant.HALF, BlockBOPDoubleDecoration.Half.UPPER);
return this.self();
}
public Builder with(BlockDoublePlant.EnumPlantType type)
{
this.bottomState = Blocks.double_plant.getStateFromMeta(type.getMeta());
this.topState = Blocks.double_plant.getStateFromMeta(8);
this.with = Blocks.double_plant.getStateFromMeta(type.getMeta());
this.withTop = Blocks.double_plant.getStateFromMeta(8);
return this;
}
public Builder generationAttempts(int a) {this.generationAttempts = a; return this;}
@Override
public GeneratorDoubleFlora create()
public Builder()
{
return new GeneratorDoubleFlora(this.amountPerChunk, this.replace, this.bottomState, this.topState, this.generationAttempts);
// defaults
this.amountPerChunk = 1.0F;
this.placeOn = BlockQueries.anything;
this.replace = new BlockQueryMaterial(Material.air);
this.with = BOPBlocks.double_plant.getDefaultState().withProperty(BlockBOPDoublePlant.VARIANT, BlockBOPDoublePlant.DoublePlantType.FLAX).withProperty(BlockBOPDoublePlant.HALF, BlockBOPDoubleDecoration.Half.LOWER);
this.withTop = BOPBlocks.double_plant.getDefaultState().withProperty(BlockBOPDoublePlant.VARIANT, BlockBOPDoublePlant.DoublePlantType.FLAX).withProperty(BlockBOPDoublePlant.HALF, BlockBOPDoubleDecoration.Half.UPPER);
this.scatterYMethod = ScatterYMethod.AT_SURFACE;
this.generationAttempts = 32;
}
@Override
public GeneratorDoubleFlora create() {
return new GeneratorDoubleFlora(this.amountPerChunk, this.placeOn, this.replace, this.with, this.scatterYMethod, this.withTop, this.generationAttempts);
}
}
protected IBlockPosQuery replace;
protected IBlockState bottomState;
protected IBlockState topState;
protected IBlockState withTop;
protected int generationAttempts;
public GeneratorDoubleFlora(float amountPerChunk, IBlockPosQuery replace, IBlockState bottomState, IBlockState topState, int generationAttempts)
public GeneratorDoubleFlora(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState with, ScatterYMethod scatterYMethod, IBlockState withTop, int generationAttempts)
{
super(amountPerChunk);
this.replace = replace;
this.bottomState = bottomState;
this.topState = topState;
super(amountPerChunk, placeOn, replace, with, scatterYMethod);
this.withTop = withTop;
this.generationAttempts = generationAttempts;
}
@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);
}
@Override
public boolean generate(World world, Random random, BlockPos pos)
{
Block bottomBlock = this.bottomState.getBlock();
Block bottomBlock = this.with.getBlock();
for (int i = 0; i < this.generationAttempts; ++i)
{
BlockPos genPos = pos.add(random.nextInt(8) - random.nextInt(8), random.nextInt(4) - random.nextInt(4), random.nextInt(8) - random.nextInt(8));
if (this.replace.matches(world, genPos) && this.replace.matches(world, genPos.up()) && genPos.getY() < 254)
if (this.placeOn.matches(world, genPos.down()) && this.replace.matches(world, genPos) && this.replace.matches(world, genPos.up()) && genPos.getY() < 254)
{
boolean canStay;
if (bottomBlock instanceof BlockBOPDecoration)
{
canStay = ((BlockBOPDecoration)bottomBlock).canBlockStay(world, genPos, this.bottomState);
canStay = ((BlockBOPDecoration)bottomBlock).canBlockStay(world, genPos, this.with);
} else if (bottomBlock instanceof BlockBush) {
canStay = ((BlockBush)bottomBlock).canPlaceBlockAt(world, genPos);
} else {
@ -114,8 +107,8 @@ public class GeneratorDoubleFlora extends BOPGeneratorBase
if (canStay)
{
world.setBlockState(genPos, this.bottomState, 2);
world.setBlockState(genPos.up(), this.topState, 2);
world.setBlockState(genPos, this.with, 2);
world.setBlockState(genPos.up(), this.withTop, 2);
}
}
}
@ -128,8 +121,8 @@ public class GeneratorDoubleFlora extends BOPGeneratorBase
{
this.amountPerChunk = conf.getFloat("amountPerChunk", this.amountPerChunk);
this.replace = conf.getBlockPosQuery("replace", this.replace);
this.bottomState = conf.getBlockState("bottomState", this.bottomState);
this.topState = conf.getBlockState("topState", this.topState);
this.with = conf.getBlockState("with", this.with);
this.withTop = conf.getBlockState("withTop", this.withTop);
this.generationAttempts = conf.getInt("generationAttempts", this.generationAttempts);
}
}

View file

@ -19,8 +19,8 @@ import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import biomesoplenty.api.biome.generation.BOPGeneratorBase;
import biomesoplenty.api.block.BOPBlocks;
import biomesoplenty.api.block.BlockQueries;
import biomesoplenty.common.block.BlockBOPFlower;
import biomesoplenty.common.block.BlockBOPLilypad;
import biomesoplenty.common.block.BlockBOPMushroom;
@ -29,68 +29,58 @@ import biomesoplenty.common.block.BlockBOPDecoration;
import biomesoplenty.common.enums.BOPFlowers;
import biomesoplenty.common.enums.BOPPlants;
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;
public class GeneratorFlora extends BOPGeneratorBase
public class GeneratorFlora extends GeneratorReplacing
{
public static class Builder implements IGeneratorBuilder<GeneratorFlora>
protected static abstract class InnerBuilder<T extends GeneratorReplacing.InnerBuilder<T, G>, G extends GeneratorFlora> extends GeneratorReplacing.InnerBuilder<T, G>
{
protected float amountPerChunk = 1.0F;
protected IBlockPosQuery replace = new BlockQueryMaterial(Material.air);
protected IBlockState with = Blocks.red_flower.getDefaultState();
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;}
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 with(IBlockState a) {this.with = a; return this;}
public Builder with(BOPPlants a) {this.with = BlockBOPPlant.paging.getVariantState(a); return this;}
public Builder with(BOPFlowers a) {this.with = BlockBOPFlower.paging.getVariantState(a); return this;}
public Builder with(BlockBOPMushroom.MushroomType a) {this.with = BOPBlocks.mushroom.getDefaultState().withProperty(BlockBOPMushroom.VARIANT, a); return this;}
public Builder with(BlockBOPLilypad.LilypadType a) {this.with = BOPBlocks.waterlily.getDefaultState().withProperty(BlockBOPLilypad.VARIANT, a); return this;}
public Builder with(BlockFlower.EnumFlowerType a)
protected int generationAttempts;
public T with(BOPPlants a) {this.with = BlockBOPPlant.paging.getVariantState(a); return this.self();}
public T with(BOPFlowers a) {this.with = BlockBOPFlower.paging.getVariantState(a); return this.self();}
public T with(BlockBOPMushroom.MushroomType a) {this.with = BOPBlocks.mushroom.getDefaultState().withProperty(BlockBOPMushroom.VARIANT, a); return this.self();}
public T with(BlockBOPLilypad.LilypadType a) {this.with = BOPBlocks.waterlily.getDefaultState().withProperty(BlockBOPLilypad.VARIANT, a); return this.self();}
public T with(BlockFlower.EnumFlowerType a)
{
BlockFlower flowerBlock = a.getBlockType().getBlock();
this.with = flowerBlock.getDefaultState().withProperty(flowerBlock.getTypeProperty(), a);
return this;
return this.self();
}
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;}
public T with(BlockTallGrass.EnumType a) {this.with = Blocks.tallgrass.getDefaultState().withProperty(BlockTallGrass.TYPE, a); return this.self();}
public T generationAttempts(int a) {this.generationAttempts = a; return this.self();}
}
public static class Builder extends InnerBuilder<Builder, GeneratorFlora> implements IGeneratorBuilder<GeneratorFlora>
{
public Builder()
{
// defaults
this.amountPerChunk = 1.0F;
this.placeOn = BlockQueries.anything;
this.replace = new BlockQueryMaterial(Material.air);
this.with = Blocks.red_flower.getDefaultState();
this.scatterYMethod = ScatterYMethod.AT_SURFACE;
this.generationAttempts = 32;
}
@Override
public GeneratorFlora create()
{
return new GeneratorFlora(this.amountPerChunk, this.replace, this.with, this.generationAttempts, this.scatterYMethod);
return new GeneratorFlora(this.amountPerChunk, this.placeOn, this.replace, this.with, this.scatterYMethod, this.generationAttempts);
}
}
protected IBlockPosQuery replace;
protected IBlockState with;
protected int generationAttempts;
protected ScatterYMethod scatterYMethod;
public GeneratorFlora(float amountPerChunk, IBlockPosQuery replace, IBlockState with, int generationAttempts, ScatterYMethod scatterYMethod)
public GeneratorFlora(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState with, ScatterYMethod scatterYMethod, int generationAttempts)
{
super(amountPerChunk);
this.replace = replace;
this.with = with;
super(amountPerChunk, placeOn, replace, with, scatterYMethod);
this.generationAttempts = generationAttempts;
this.scatterYMethod = scatterYMethod;
}
@Override
public BlockPos getScatterY(World world, Random random, int x, int z)
{
return this.scatterYMethod.getBlockPos(world, random, x, z);
}
@Override
@ -102,7 +92,7 @@ public class GeneratorFlora extends BOPGeneratorBase
{
BlockPos genPos = pos.add(random.nextInt(8) - random.nextInt(8), random.nextInt(4) - random.nextInt(4), random.nextInt(8) - random.nextInt(8));
if (this.replace.matches(world, genPos) && genPos.getY() < 255)
if (this.placeOn.matches(world, genPos.down()) && this.replace.matches(world, genPos) && genPos.getY() < 255)
{
boolean canStay;
if (block instanceof BlockBOPDecoration)
@ -132,7 +122,6 @@ public class GeneratorFlora extends BOPGeneratorBase
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

@ -8,54 +8,41 @@
package biomesoplenty.common.world.feature;
import net.minecraft.block.Block;
import net.minecraft.block.BlockTallGrass;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import biomesoplenty.common.block.BlockBOPPlant;
import biomesoplenty.common.enums.BOPPlants;
import biomesoplenty.api.block.BlockQueries;
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;
import biomesoplenty.common.util.block.BlockQuery.BlockQueryParseException;
import biomesoplenty.common.util.block.BlockQuery.BlockQueryState;
import biomesoplenty.common.util.block.BlockQuery.IBlockPosQuery;
public class GeneratorGrass extends GeneratorFlora
{
public static class Builder implements IGeneratorBuilder<GeneratorGrass>
public static class Builder extends GeneratorFlora.InnerBuilder<Builder, GeneratorGrass> implements IGeneratorBuilder<GeneratorGrass>
{
protected float amountPerChunk = 1.0F;
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;}
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 with(IBlockState a) {this.with = a; return this;}
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;}
public Builder()
{
// defaults
this.amountPerChunk = 1.0F;
this.placeOn = BlockQueries.anything;
this.replace = new BlockQueryMaterial(Material.air);
this.with = Blocks.tallgrass.getDefaultState();
this.scatterYMethod = ScatterYMethod.AT_SURFACE;
this.generationAttempts = 96;
}
@Override
public GeneratorGrass create()
{
return new GeneratorGrass(this.amountPerChunk, this.replace, this.with, this.generationAttempts, this.scatterYMethod);
return new GeneratorGrass(this.amountPerChunk, this.placeOn, this.replace, this.with, this.scatterYMethod, this.generationAttempts);
}
}
public GeneratorGrass(float amountPerChunk, IBlockPosQuery replace, IBlockState with, int generationAttempts, ScatterYMethod scatterYMethod)
public GeneratorGrass(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState with, ScatterYMethod scatterYMethod, int generationAttempts)
{
super(amountPerChunk, replace, with, generationAttempts, scatterYMethod);
super(amountPerChunk, placeOn, replace, with, scatterYMethod, generationAttempts);
}
}

View file

@ -29,26 +29,28 @@ import net.minecraft.world.biome.BiomeGenBase;
public class GeneratorLakes extends BOPGeneratorBase
{
public static class Builder implements IGeneratorBuilder<GeneratorLakes>
{
protected float amountPerChunk = 1.0F;
protected IBlockState liquid = Blocks.water.getDefaultState();
protected IBlockState frozenLiquid = Blocks.ice.getDefaultState();
protected IBlockState grassBorderWith = Blocks.grass.getDefaultState();
protected IBlockPosQuery grassReplace = new BlockQueryBlock(Blocks.dirt);
protected IBlockState lineWith = null;
public static class Builder extends BOPGeneratorBase.InnerBuilder<Builder, GeneratorLakes> implements IGeneratorBuilder<GeneratorLakes>
{
protected IBlockState liquid;
protected IBlockState frozenLiquid;
protected IBlockState grassBorderWith;
protected IBlockPosQuery grassReplace;
protected IBlockState lineWith;
public Builder liquid(IBlockState a) {this.liquid = a; return this.self();}
public Builder liquid(Block a) {this.liquid = a.getDefaultState(); return this.self();}
public Builder frozenLiquid(IBlockState a) {this.frozenLiquid = a; return this.self();}
public Builder frozenLiquid(Block a) {this.frozenLiquid = a.getDefaultState(); return this.self();}
public Builder grassBorderWith(IBlockState a) {this.grassBorderWith = a; return this.self();}
public Builder grassBorderWith(Block a) {this.grassBorderWith = a.getDefaultState(); return this.self();}
public Builder grassReplace(IBlockPosQuery a) {this.grassReplace = a; return this.self();}
public Builder grassReplace(String a) throws BlockQueryParseException {this.grassReplace = BlockQuery.parseQueryString(a); return this.self();}
public Builder grassReplace(Block a) {this.grassReplace = new BlockQueryBlock(a); return this.self();}
public Builder grassReplace(IBlockState a) {this.grassReplace = new BlockQueryState(a); return this.self();}
public Builder lineWith(IBlockState a) {this.lineWith = a; return this.self();}
public Builder lineWith(Block a) {this.lineWith = a.getDefaultState(); return this.self();}
public Builder amountPerChunk(float a) {this.amountPerChunk = a; return this;}
public Builder liquid(IBlockState a) {this.liquid = a; return this;}
public Builder frozenLiquid(IBlockState a) {this.frozenLiquid = a; return this;}
public Builder grassBorderWith(IBlockState a) {this.grassBorderWith = a; return this;}
public Builder grassReplace(IBlockPosQuery a) {this.grassReplace = a; return this;}
public Builder grassReplace(String a) throws BlockQueryParseException {this.grassReplace = BlockQuery.parseQueryString(a); return this;}
public Builder grassReplace(Block a) {this.grassReplace = new BlockQueryBlock(a); return this;}
public Builder grassReplace(IBlockState a) {this.grassReplace = new BlockQueryState(a); return this;}
public Builder lineWith(IBlockState a) {this.lineWith = a; return this;}
public Builder waterLakeForBiome(BiomeGenBase a)
{
this.liquid = Blocks.water.getDefaultState();
@ -67,10 +69,20 @@ public class GeneratorLakes extends BOPGeneratorBase
this.lineWith = Blocks.stone.getDefaultState();
return this;
}
@Override
public GeneratorLakes create()
public Builder()
{
// defaults
this.amountPerChunk = 1.0F;
this.liquid = Blocks.water.getDefaultState();
this.frozenLiquid = Blocks.ice.getDefaultState();
this.grassBorderWith = Blocks.grass.getDefaultState();
this.grassReplace = new BlockQueryBlock(Blocks.dirt);
this.lineWith = null;
}
@Override
public GeneratorLakes create() {
return new GeneratorLakes(this.amountPerChunk, this.liquid, this.frozenLiquid, this.grassBorderWith, this.grassReplace, this.lineWith);
}
}
@ -80,7 +92,6 @@ public class GeneratorLakes extends BOPGeneratorBase
protected IBlockState grassBorderWith;
protected IBlockPosQuery grassReplace;
protected IBlockState lineWith;
public GeneratorLakes(float amountPerChunk, IBlockState liquid, IBlockState frozenLiquid, IBlockState grassBorderWith, IBlockPosQuery grassReplace, IBlockState lineWith)

View file

@ -11,70 +11,76 @@ package biomesoplenty.common.world.feature;
import java.util.Collection;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLog;
import net.minecraft.block.BlockNewLog;
import net.minecraft.block.BlockOldLog;
import net.minecraft.block.BlockPlanks;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import biomesoplenty.api.biome.generation.BOPGeneratorBase;
import biomesoplenty.common.block.BlockBOPLog;
import biomesoplenty.common.enums.BOPWoods;
import biomesoplenty.common.util.block.BlockQuery;
import biomesoplenty.common.util.block.BlockQuery.BlockQueryBlock;
import biomesoplenty.common.util.biome.GeneratorUtils.ScatterYMethod;
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;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
public class GeneratorLogs extends BOPGeneratorBase
public class GeneratorLogs extends GeneratorReplacing
{
public static class Builder implements IGeneratorBuilder<GeneratorLogs>
public static class Builder extends GeneratorReplacing.InnerBuilder<Builder, GeneratorLogs> implements IGeneratorBuilder<GeneratorLogs>
{
protected float amountPerChunk = 1.0F;
protected IBlockState with = Blocks.log.getDefaultState();
protected IBlockPosQuery placeOn = new BlockQueryMaterial(Material.ground, Material.grass);
protected int minLength = 3;
protected int maxLength = 5;
protected int minLength;
protected int maxLength;
public Builder with(BOPWoods a) {this.with = BlockBOPLog.paging.getVariantState(a); return this.self();}
public Builder with(BlockPlanks.EnumType a)
{
if (a.getMetadata() < 4)
{
this.with = Blocks.log.getDefaultState().withProperty(BlockOldLog.VARIANT, a);
} else {
this.with = Blocks.log2.getDefaultState().withProperty(BlockNewLog.VARIANT, a);
}
return this.self();
}
public Builder minLength(int a) {this.minLength = a; return this.self();}
public Builder maxLength(int a) {this.maxLength = a; return this.self();}
public Builder amountPerChunk(float a) {this.amountPerChunk = a; return this;}
public Builder log(IBlockState a) {this.with = a; return this;}
public Builder log(BOPWoods a) {this.with = BlockBOPLog.paging.getVariantState(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 minLength(int a) {this.minLength = a; return this;}
public Builder maxLength(int a) {this.maxLength = a; return this;}
public Builder()
{
// defaults
this.amountPerChunk = 1.0F;
this.placeOn = new BlockQueryMaterial(Material.grass, Material.ground);
this.replace = new BlockQueryMaterial(Material.air);
this.with = Blocks.log.getDefaultState();
this.scatterYMethod = ScatterYMethod.AT_SURFACE;
this.minLength = 3;
this.maxLength = 5;
}
@Override
public GeneratorLogs create()
{
return new GeneratorLogs(this.amountPerChunk, this.with, this.minLength, this.maxLength, this.placeOn);
return new GeneratorLogs(this.amountPerChunk, this.placeOn, this.replace, this.with, this.scatterYMethod, this.minLength, this.maxLength);
}
}
protected IBlockState with;
}
protected IProperty axisProperty;
protected IBlockPosQuery placeOn;
protected int minLength;
protected int maxLength;
public GeneratorLogs(float amountPerChunk, IBlockState with, int minLength, int maxLength, IBlockPosQuery placeOn)
public GeneratorLogs(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState with, ScatterYMethod scatterYMethod, int minLength, int maxLength)
{
super(amountPerChunk);
this.with = with;
super(amountPerChunk, placeOn, replace, with, scatterYMethod);
this.axisProperty = getAxisProperty(with);
if (this.axisProperty == null)
{
throw new RuntimeException("Block state " + with + " has no axis property with X and Z values - is it actually a log?");
}
this.placeOn = placeOn;
this.minLength = minLength;
this.maxLength = maxLength;
@ -94,21 +100,10 @@ public class GeneratorLogs extends BOPGeneratorBase
return null;
}
@Override
public BlockPos getScatterY(World world, Random random, int x, int z)
{
// always at world surface
return world.getHeight(new BlockPos(x, 0, z));
}
@Override
public boolean generate(World world, Random random, BlockPos pos)
{
// move upwards until we find an air block
while (!world.isAirBlock(pos)) {pos = pos.up();}
// if we can't start placing the log, abandon now
if (!this.placeOn.matches(world, pos.down())) {return false;}
@ -117,7 +112,7 @@ public class GeneratorLogs extends BOPGeneratorBase
int length = this.minLength + random.nextInt(this.maxLength - this.minLength);
// keep placing logs along the chosen direction (as long as the block beneath is suitable)
while(length > 0 && world.isAirBlock(pos) && this.placeOn.matches(world, pos.down()))
while(length > 0 && this.replace.matches(world, pos) && this.placeOn.matches(world, pos.down()))
{
world.setBlockState(pos, this.with.withProperty(this.axisProperty, direction));
pos = (direction == BlockLog.EnumAxis.X) ? pos.east() : pos.north();

View file

@ -10,27 +10,43 @@ package biomesoplenty.common.world.feature;
import java.util.Random;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import org.apache.commons.lang3.tuple.Pair;
import biomesoplenty.api.biome.generation.BOPGeneratorBase;
import biomesoplenty.api.block.BOPBlocks;
import biomesoplenty.common.block.BlockBOPGem;
import biomesoplenty.common.enums.BOPGems;
import biomesoplenty.common.util.biome.GeneratorUtils;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
public abstract class GeneratorOreBase extends BOPGeneratorBase
{
protected static abstract class InnerBuilder<T extends BOPGeneratorBase.InnerBuilder<T, G>, G extends GeneratorOreBase> extends BOPGeneratorBase.InnerBuilder<T, G>
{
protected IBlockState with;
protected int minHeight;
protected int maxHeight;
public T with(IBlockState a) {this.with = a; return this.self();}
public T with(BOPGems a) {this.with = BOPBlocks.gem_ore.getDefaultState().withProperty(BlockBOPGem.VARIANT, a); return this.self();}
public T minHeight(int a) {this.minHeight = a; return this.self();}
public T maxHeight(int a) {this.maxHeight = a; return this.self();}
}
protected int minHeight;
protected int maxHeight;
protected GeneratorOreBase(float amountPerChunk, int minHeight, int maxHeight)
{
super(amountPerChunk);
Pair<Integer, Integer> heights = GeneratorUtils.validateMinMaxHeight(minHeight, maxHeight);
this.minHeight = heights.getLeft();
this.maxHeight = heights.getRight();
this.minHeight = minHeight;
this.maxHeight = maxHeight;
}
@Override

View file

@ -19,31 +19,33 @@ import net.minecraft.world.gen.feature.WorldGenMinable;
public class GeneratorOreCluster extends GeneratorOreBase
{
public static class Builder implements IGeneratorBuilder<GeneratorOreCluster>
public static class Builder extends GeneratorOreBase.InnerBuilder<Builder, GeneratorOreCluster> implements IGeneratorBuilder<GeneratorOreCluster>
{
protected float amountPerChunk = 1.0F;
protected int minHeight = 4;
protected int maxHeight = 32;
protected int clusterSize = 4;
protected IBlockState with = Blocks.emerald_ore.getDefaultState();
protected int clusterSize;
public Builder amountPerChunk(float a) {this.amountPerChunk = a; return this;}
public Builder with(IBlockState a) {this.with = 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 clusterSize(int a) {this.clusterSize = a; return this;}
public Builder clusterSize(int a) {this.clusterSize = a; return this.self();}
public Builder()
{
this.amountPerChunk = 1.0F;
this.with = Blocks.emerald_ore.getDefaultState();
this.minHeight = 4;
this.maxHeight = 32;
this.clusterSize = 4;
}
@Override
public GeneratorOreCluster create()
{
return new GeneratorOreCluster(this.amountPerChunk, this.with, this.clusterSize, this.minHeight, this.maxHeight);
return new GeneratorOreCluster(this.amountPerChunk, this.minHeight, this.maxHeight, this.with, this.clusterSize);
}
}
private WorldGenMinable generator;
public GeneratorOreCluster(float amountPerChunk, IBlockState with, int clusterSize, int minHeight, int maxHeight)
public GeneratorOreCluster(float amountPerChunk, int minHeight, int maxHeight, IBlockState with, int clusterSize)
{
super(amountPerChunk, minHeight, maxHeight);
this.generator = new WorldGenMinable(with, clusterSize);

View file

@ -10,62 +10,64 @@ package biomesoplenty.common.world.feature;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.block.state.pattern.BlockHelper;
import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import biomesoplenty.api.block.BOPBlocks;
import biomesoplenty.common.block.BlockBOPGem;
import biomesoplenty.common.enums.BOPGems;
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 com.google.common.base.Predicate;
public class GeneratorOreSingle extends GeneratorOreBase
{
public static class Builder implements IGeneratorBuilder<GeneratorOreSingle>
public static class Builder extends GeneratorOreBase.InnerBuilder<Builder, GeneratorOreSingle> implements IGeneratorBuilder<GeneratorOreSingle>
{
protected float amountPerChunk = 1.0F;
protected IBlockState with = Blocks.emerald_ore.getDefaultState();
protected int minHeight = 4;
protected int maxHeight = 32;
protected IBlockPosQuery replace;
public Builder amountPerChunk(float a) {this.amountPerChunk = a; return this;}
public Builder with(IBlockState a) {this.with = a; return this;}
public Builder with(BOPGems a) {this.with = BOPBlocks.gem_ore.getDefaultState().withProperty(BlockBOPGem.VARIANT, 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 replace(IBlockPosQuery a) {this.replace = a; return this.self();}
public Builder replace(String a) throws BlockQueryParseException {this.replace = BlockQuery.parseQueryString(a); return this.self();}
public Builder replace(Block a) {this.replace = new BlockQueryBlock(a); return this.self();}
public Builder replace(IBlockState a) {this.replace = new BlockQueryState(a); return this.self();}
public Builder()
{
this.amountPerChunk = 1.0F;
this.minHeight = 4;
this.maxHeight = 32;
this.with = Blocks.emerald_ore.getDefaultState();
this.replace = new BlockQueryBlock(Blocks.stone);
}
@Override
public GeneratorOreSingle create()
{
return new GeneratorOreSingle(this.amountPerChunk, this.with, this.minHeight, this.maxHeight);
return new GeneratorOreSingle(this.amountPerChunk, this.minHeight, this.maxHeight, this.with, this.replace);
}
}
}
private IBlockState with;
private Predicate replace;
private IBlockPosQuery replace;
public GeneratorOreSingle(float amountPerChunk, IBlockState state, int minHeight, int maxHeight)
public GeneratorOreSingle(float amountPerChunk, int minHeight, int maxHeight, IBlockState with, IBlockPosQuery replace)
{
super(amountPerChunk, minHeight, maxHeight);
this.with = state;
this.replace = BlockHelper.forBlock(Blocks.stone);
this.with = with;
this.replace = replace;
}
@Override
public boolean generate(World world, Random random, BlockPos pos)
{
if (world.getBlockState(pos).getBlock().isReplaceableOreGen(world, pos, this.replace))
if (this.replace.matches(world, pos))
{
return world.setBlockState(pos, this.with, 2);
}
}
return false;
}
@ -75,6 +77,7 @@ public class GeneratorOreSingle extends GeneratorOreBase
super.configure(conf);
this.with = conf.getBlockState("with", this.with);
this.replace = conf.getBlockPosQuery("replace", this.replace);
}
}

View file

@ -0,0 +1,70 @@
/*******************************************************************************
* 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;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import biomesoplenty.api.biome.generation.BOPGeneratorBase;
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.BlockQueryParseException;
import biomesoplenty.common.util.block.BlockQuery.BlockQueryState;
import biomesoplenty.common.util.block.BlockQuery.IBlockPosQuery;
public abstract class GeneratorReplacing extends BOPGeneratorBase
{
protected IBlockPosQuery placeOn;
protected IBlockPosQuery replace;
protected IBlockState with;
protected ScatterYMethod scatterYMethod;
protected GeneratorReplacing(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState with, ScatterYMethod scatterYMethod) {
super(amountPerChunk);
this.placeOn = placeOn;
this.replace = replace;
this.with = with;
this.scatterYMethod = scatterYMethod;
}
protected static abstract class InnerBuilder<T extends InnerBuilder<T, G>, G extends GeneratorReplacing> extends BOPGeneratorBase.InnerBuilder<T, G>
{
protected IBlockPosQuery placeOn;
protected IBlockPosQuery replace;
protected IBlockState with;
protected ScatterYMethod scatterYMethod;
public T placeOn(IBlockPosQuery a) {this.placeOn = a; return this.self();}
public T placeOn(String a) throws BlockQueryParseException {this.placeOn = BlockQuery.parseQueryString(a); return this.self();}
public T placeOn(Block a) {this.placeOn = new BlockQueryBlock(a); return this.self();}
public T placeOn(IBlockState a) {this.placeOn = new BlockQueryState(a); return this.self();}
public T replace(IBlockPosQuery a) {this.replace = a; return this.self();}
public T replace(String a) throws BlockQueryParseException {this.replace = BlockQuery.parseQueryString(a); return this.self();}
public T replace(Block a) {this.replace = new BlockQueryBlock(a); return this.self();}
public T replace(IBlockState a) {this.replace = new BlockQueryState(a); return this.self();}
public T with(IBlockState a) {this.with = a; return this.self();}
public T scatterYMethod(ScatterYMethod a) {this.scatterYMethod = a; return this.self();}
}
@Override
public BlockPos getScatterY(World world, Random random, int x, int z)
{
return this.scatterYMethod.getBlockPos(world, random, x, z);
}
}

View file

@ -10,79 +10,48 @@ package biomesoplenty.common.world.feature;
import java.util.Random;
import biomesoplenty.api.biome.generation.BOPGeneratorBase;
import biomesoplenty.api.block.BlockQueries;
import biomesoplenty.common.util.biome.GeneratorUtils.ScatterYMethod;
import biomesoplenty.common.util.block.BlockQuery;
import biomesoplenty.common.util.block.BlockQuery.BlockQueryParseException;
import biomesoplenty.common.util.block.BlockQuery.IBlockPosQuery;
import biomesoplenty.common.util.block.BlockQuery.BlockPosQueryOr;
import biomesoplenty.common.util.block.BlockQuery.BlockQueryMaterial;
import biomesoplenty.common.util.block.BlockQuery.BlockQueryBlock;
import biomesoplenty.common.util.block.BlockQuery.BlockQueryState;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
public class GeneratorSplatter extends BOPGeneratorBase
public class GeneratorSplatter extends GeneratorReplacing
{
public static class Builder implements IGeneratorBuilder<GeneratorSplatter>
public static class Builder extends GeneratorReplacing.InnerBuilder<Builder, GeneratorSplatter> implements IGeneratorBuilder<GeneratorSplatter>
{
protected float amountPerChunk = 1.0F;
protected IBlockPosQuery placeOn = BlockQueries.anything;
protected IBlockPosQuery replace = BlockQueries.breakable;
protected IBlockState with = Blocks.stone.getDefaultState();
protected int generationAttempts = 64;
protected ScatterYMethod scatterYMethod = ScatterYMethod.AT_SURFACE;
protected int generationAttempts;
public Builder generationAttempts(int a) {this.generationAttempts = a; return this.self();}
public Builder amountPerChunk(float a) {this.amountPerChunk = 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 with(IBlockState a) {this.with = a; return this;}
public Builder generationAttempts(int a) {this.generationAttempts = a; return this;}
public Builder scatterYMethod(ScatterYMethod a) {this.scatterYMethod = a; return this;}
public Builder()
{
// defaults
this.amountPerChunk = 1.0F;
this.placeOn = BlockQueries.anything;
this.replace = BlockQueries.breakable;
this.with = Blocks.stone.getDefaultState();
this.scatterYMethod = ScatterYMethod.AT_SURFACE;
this.generationAttempts = 64;
}
@Override
public GeneratorSplatter create()
{
return new GeneratorSplatter(this.amountPerChunk, this.placeOn, this.replace, this.with, this.generationAttempts, this.scatterYMethod);
return new GeneratorSplatter(this.amountPerChunk, this.placeOn, this.replace, this.with, this.scatterYMethod, this.generationAttempts);
}
}
}
private static IBlockPosQuery isLeavesOrAir = new BlockPosQueryOr(new BlockQueryMaterial(Material.leaves), new BlockQueryMaterial(Material.air));
protected IBlockPosQuery placeOn;
protected IBlockPosQuery replace;
protected IBlockState with;
protected int generationAttempts;
protected ScatterYMethod scatterYMethod;
public GeneratorSplatter(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState with, int generationAttempts, ScatterYMethod scatterYMethod)
public GeneratorSplatter(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState with, ScatterYMethod scatterYMethod, int generationAttempts)
{
super(amountPerChunk);
this.placeOn = placeOn;
this.replace = replace;
this.with = with;
super(amountPerChunk, placeOn, replace, with, scatterYMethod);
this.generationAttempts = generationAttempts;
this.scatterYMethod = scatterYMethod;
}
@Override
public BlockPos getScatterY(World world, Random random, int x, int z)
{
return this.scatterYMethod.getBlockPos(world, random, x, z);
}
@Override

View file

@ -10,71 +10,57 @@ package biomesoplenty.common.world.feature;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
import biomesoplenty.api.biome.generation.BOPGeneratorBase;
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;
public class GeneratorSplotches extends BOPGeneratorBase
public class GeneratorSplotches extends GeneratorReplacing
{
public static class Builder implements IGeneratorBuilder<GeneratorSplotches>
public static class Builder extends GeneratorReplacing.InnerBuilder<Builder, GeneratorSplotches> implements IGeneratorBuilder<GeneratorSplotches>
{
protected float amountPerChunk = 1.0F;
protected IBlockPosQuery replace = new BlockQueryMaterial(Material.grass, Material.ground);
protected IBlockState with = Blocks.cobblestone.getDefaultState();
protected int splotchSize = 8;
protected ScatterYMethod scatterYMethod = ScatterYMethod.BELOW_SURFACE;
protected int splotchSize;
public Builder splotchSize(int a) {this.splotchSize = a; return this.self();}
public Builder amountPerChunk(float a) {this.amountPerChunk = 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 with(IBlockState a) {this.with = a; return this;}
public Builder splotchSize(int a) {this.splotchSize = a; return this;}
public Builder scatterYMethod(ScatterYMethod a) {this.scatterYMethod = a; return this;}
public Builder()
{
// defaults
this.amountPerChunk = 1.0F;
this.placeOn = new BlockQueryMaterial(Material.grass, Material.ground);
this.replace = new BlockQueryMaterial(Material.grass, Material.ground);
this.with = Blocks.cobblestone.getDefaultState();
this.scatterYMethod = ScatterYMethod.BELOW_SURFACE;
this.splotchSize = 8;
}
@Override
public GeneratorSplotches create()
{
return new GeneratorSplotches(this.amountPerChunk, this.replace, this.with, this.splotchSize, this.scatterYMethod);
return new GeneratorSplotches(this.amountPerChunk, this.placeOn, this.replace, this.with, this.scatterYMethod, this.splotchSize);
}
}
}
protected IBlockPosQuery replace;
protected IBlockState with;
protected int splotchSize;
protected ScatterYMethod scatterYMethod;
public GeneratorSplotches(float amountPerChunk, IBlockPosQuery replace, IBlockState with, int splotchSize, ScatterYMethod scatterYMethod)
public GeneratorSplotches(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState with, ScatterYMethod scatterYMethod, int splotchSize)
{
super(amountPerChunk);
this.replace = replace;
this.with = with;
super(amountPerChunk, placeOn, replace, with, scatterYMethod);
this.splotchSize = splotchSize;
this.scatterYMethod = scatterYMethod;
}
@Override
public BlockPos getScatterY(World world, Random random, int x, int z)
{
return this.scatterYMethod.getBlockPos(world, random, x, z);
}
}
@Override
public boolean generate(World world, Random random, BlockPos pos)
{
if (! this.placeOn.matches(world, pos.down())) {return false;}
float a = random.nextFloat() * (float)Math.PI;
// choose a start point

View file

@ -10,62 +10,51 @@ package biomesoplenty.common.world.feature;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import biomesoplenty.api.biome.generation.BOPGeneratorBase;
import biomesoplenty.common.util.block.BlockQuery;
import biomesoplenty.api.block.BlockQueries;
import biomesoplenty.common.util.biome.GeneratorUtils.ScatterYMethod;
import biomesoplenty.common.util.block.BlockQuery.*;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
public class GeneratorWaterside extends BOPGeneratorBase
public class GeneratorWaterside extends GeneratorReplacing
{
public static class Builder implements IGeneratorBuilder<GeneratorWaterside>
public static class Builder extends GeneratorReplacing.InnerBuilder<Builder, GeneratorWaterside> implements IGeneratorBuilder<GeneratorWaterside>
{
protected float amountPerChunk = 1.0F;
protected int maxRadius = 7;
protected IBlockPosQuery replace = new BlockQueryMaterial(Material.grass, Material.ground);
protected IBlockState with = Blocks.gravel.getDefaultState();
protected int maxRadius;
public Builder maxRadius(int a) {this.maxRadius = a; return this.self();}
public Builder amountPerChunk(float a) {this.amountPerChunk = 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 with(IBlockState a) {this.with = a; return this;}
public Builder maxRadius(int a) {this.maxRadius = a; return this;}
public Builder()
{
// defaults
this.amountPerChunk = 1.0F;
this.placeOn = BlockQueries.anything;
this.replace = new BlockQueryMaterial(Material.grass, Material.ground);
this.with = Blocks.gravel.getDefaultState();
this.scatterYMethod = ScatterYMethod.AT_GROUND;
this.maxRadius = 7;
}
@Override
public GeneratorWaterside create()
{
return new GeneratorWaterside(this.amountPerChunk, this.replace, this.with, this.maxRadius);
return new GeneratorWaterside(this.amountPerChunk, this.placeOn, this.replace, this.with, this.scatterYMethod, this.maxRadius);
}
}
}
protected IBlockPosQuery replace;
protected IBlockState with;
protected int maxRadius;
public GeneratorWaterside(float amountPerChunk, IBlockPosQuery replace, IBlockState with, int maxRadius)
public GeneratorWaterside(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState with, ScatterYMethod scatterYMethod, int maxRadius)
{
super(amountPerChunk);
this.replace = replace;
this.with = with;
super(amountPerChunk, placeOn, replace, with, scatterYMethod);
this.maxRadius = maxRadius;
}
@Override
public BlockPos getScatterY(World world, Random random, int x, int z)
{
return world.getTopSolidOrLiquidBlock(new BlockPos(x, 0, z));
}
@Override
public boolean generate(World world, Random random, BlockPos pos)

View file

@ -11,11 +11,6 @@ package biomesoplenty.common.world.feature.tree;
import java.util.Random;
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.BlockSapling;
import net.minecraft.block.BlockVine;
import net.minecraft.block.material.Material;
@ -27,92 +22,44 @@ import net.minecraft.world.World;
import org.apache.commons.lang3.tuple.Pair;
import biomesoplenty.api.biome.generation.BOPGeneratorBase;
import biomesoplenty.common.block.BlockBOPLeaves;
import biomesoplenty.common.block.BlockBOPLog;
import biomesoplenty.common.enums.BOPTrees;
import biomesoplenty.common.enums.BOPWoods;
import biomesoplenty.api.block.BlockQueries;
import biomesoplenty.common.util.biome.GeneratorUtils;
import biomesoplenty.common.util.block.BlockQuery.BlockQueryMaterial;
import biomesoplenty.common.util.block.BlockQuery.IBlockPosQuery;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
public class GeneratorBasicTree extends BOPGeneratorBase
public class GeneratorBasicTree extends GeneratorTreeBase
{
public static class Builder implements IGeneratorBuilder<GeneratorBasicTree>
{
protected float amountPerChunk = 1.0F;
protected boolean updateNeighbours = false;
protected int minHeight = 4;
protected int maxHeight = 7;
protected IBlockState log = Blocks.log.getDefaultState();
protected IBlockState leaves = Blocks.leaves.getDefaultState();
protected IBlockState vine = null;
public Builder amountPerChunk(float a) {this.amountPerChunk = a; return this;}
public Builder updateNeighbours(boolean a) {this.updateNeighbours = 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 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)
// TODO: update neighbours in builder?
public static class Builder extends GeneratorTreeBase.InnerBuilder<Builder, GeneratorBasicTree> implements IGeneratorBuilder<GeneratorBasicTree>
{
public Builder()
{
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;
// defaults
this.amountPerChunk = 1.0F;
this.placeOn = BlockQueries.anything;
this.replace = new BlockQueryMaterial(Material.air);
this.log = Blocks.log.getDefaultState();
this.leaves = Blocks.leaves.getDefaultState();
this.vine = null;
this.minHeight = 4;
this.maxHeight = 7;
}
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) {this.vine = a; return this;}
@Override
public GeneratorBasicTree create()
{
return new GeneratorBasicTree(this.amountPerChunk, this.updateNeighbours, this.minHeight, this.maxHeight, this.log, this.leaves, this.vine);
return new GeneratorBasicTree(this.amountPerChunk, this.placeOn, this.replace, this.log, this.leaves, this.vine, this.minHeight, this.maxHeight, false);
}
}
private boolean updateNeighbours;
private int minHeight;
private int maxHeight;
private IBlockState log;
private IBlockState leaves;
private IBlockState vine;
public GeneratorBasicTree(float amountPerChunk, boolean updateNeighbours, int minHeight, int maxHeight, IBlockState log, IBlockState leaves, IBlockState vine)
public GeneratorBasicTree(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState log, IBlockState leaves, IBlockState vine, int minHeight, int maxHeight, boolean updateNeighbours)
{
super(amountPerChunk);
super(amountPerChunk, placeOn, replace, log, leaves, vine, minHeight, maxHeight);
this.updateNeighbours = updateNeighbours;
Pair<Integer, Integer> heights = GeneratorUtils.validateMinMaxHeight(minHeight, maxHeight);
this.minHeight = heights.getLeft();
this.maxHeight = heights.getRight();
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_SURFACE.getBlockPos(world, random, x, z);
}
@Override
@ -150,7 +97,7 @@ public class GeneratorBasicTree extends BOPGeneratorBase
{
if (y >= 0 && y < 256)
{
if (!GeneratorUtils.canTreeReplace(world, new BlockPos(x, y, z)))
if (!this.replace.matches(world, new BlockPos(x, y, z)))
{
hasSpace = false;
}
@ -173,7 +120,7 @@ public class GeneratorBasicTree extends BOPGeneratorBase
Block soil = world.getBlockState(soilPos).getBlock();
boolean isSoil = soil.canSustainPlant(world, soilPos, EnumFacing.UP, (BlockSapling)Blocks.sapling);
if (isSoil && pos.getY() < 256 - height - 1)
if (this.placeOn.matches(world, soilPos) && isSoil && pos.getY() < 256 - height - 1)
{
soil.onPlantGrow(world, soilPos, pos);
int leavesLayers = 3;
@ -200,9 +147,7 @@ public class GeneratorBasicTree extends BOPGeneratorBase
if (Math.abs(xDiff) != leavesRadius || Math.abs(zDiff) != leavesRadius || random.nextInt(2) != 0 && currentLayer != 0)
{
BlockPos leavesPos = new BlockPos(x, y, z);
Block block = world.getBlockState(leavesPos).getBlock();
if (block.isAir(world, leavesPos) || block.isLeaves(world, leavesPos) || block.getMaterial() == Material.vine)
if (this.replace.matches(world, leavesPos))
{
this.setBlockAndNotifyAdequately(world, leavesPos, this.leaves);
}
@ -215,31 +160,27 @@ public class GeneratorBasicTree extends BOPGeneratorBase
for (int layer = 0; layer < height; ++layer)
{
BlockPos blockpos2 = pos.up(layer);
Block block2 = world.getBlockState(blockpos2).getBlock();
if (block2.isAir(world, blockpos2) || block2.isLeaves(world, blockpos2) || block2.getMaterial() == Material.vine)
if (this.replace.matches(world, blockpos2))
{
this.setBlockAndNotifyAdequately(world, pos.up(layer), this.log);
//If vines are enabled, randomly cover the sides of the trunk with vines from the bottom up
if (this.vine != null && layer > 0)
{
if (random.nextInt(3) > 0 && world.isAirBlock(pos.add(-1, layer, 0)))
if (random.nextInt(3) > 0 && this.replace.matches(world, pos.add(-1, layer, 0)))
{
this.setBlockAndNotifyAdequately(world, pos.add(-1, layer, 0), this.getVineStateForSide(EnumFacing.EAST));
}
if (random.nextInt(3) > 0 && world.isAirBlock(pos.add(1, layer, 0)))
if (random.nextInt(3) > 0 && this.replace.matches(world, pos.add(1, layer, 0)))
{
this.setBlockAndNotifyAdequately(world, pos.add(1, layer, 0), this.getVineStateForSide(EnumFacing.WEST));
}
if (random.nextInt(3) > 0 && world.isAirBlock(pos.add(0, layer, -1)))
if (random.nextInt(3) > 0 && this.replace.matches(world, pos.add(0, layer, -1)))
{
this.setBlockAndNotifyAdequately(world, pos.add(0, layer, -1), this.getVineStateForSide(EnumFacing.SOUTH));
}
if (random.nextInt(3) > 0 && world.isAirBlock(pos.add(0, layer, 1)))
if (random.nextInt(3) > 0 && this.replace.matches(world, pos.add(0, layer, 1)))
{
this.setBlockAndNotifyAdequately(world, pos.add(0, layer, 1), this.getVineStateForSide(EnumFacing.NORTH));
}
@ -271,22 +212,22 @@ public class GeneratorBasicTree extends BOPGeneratorBase
BlockPos northPos = blockpos3.north();
BlockPos southPos = blockpos3.south();
if (random.nextInt(4) == 0 && world.getBlockState(westPos).getBlock().isAir(world, westPos))
if (random.nextInt(4) == 0 && this.replace.matches(world, westPos))
{
this.extendVines(world, westPos, EnumFacing.EAST);
}
if (random.nextInt(4) == 0 && world.getBlockState(eastPos).getBlock().isAir(world, eastPos))
if (random.nextInt(4) == 0 && this.replace.matches(world, eastPos))
{
this.extendVines(world, eastPos, EnumFacing.WEST);
}
if (random.nextInt(4) == 0 && world.getBlockState(northPos).getBlock().isAir(world, northPos))
if (random.nextInt(4) == 0 && this.replace.matches(world, northPos))
{
this.extendVines(world, northPos, EnumFacing.SOUTH);
}
if (random.nextInt(4) == 0 && world.getBlockState(southPos).getBlock().isAir(world, southPos))
if (random.nextInt(4) == 0 && this.replace.matches(world, southPos))
{
this.extendVines(world, southPos, EnumFacing.NORTH);
}
@ -323,7 +264,7 @@ public class GeneratorBasicTree extends BOPGeneratorBase
int length = 4;
//Extend vine downwards for a maximum of 4 blocks
for (pos = pos.down(); world.getBlockState(pos).getBlock().isAir(world, pos) && length > 0; length--)
for (pos = pos.down(); this.replace.matches(world, pos) && length > 0; length--)
{
this.setBlockAndNotifyAdequately(world, pos, vineState);
pos = pos.down();

View file

@ -9,12 +9,7 @@
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;
@ -23,159 +18,81 @@ 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 class GeneratorBayouTree extends GeneratorTreeBase
{
public static class Builder implements IGeneratorBuilder<GeneratorBayouTree>
public static class Builder extends GeneratorTreeBase.InnerBuilder<Builder, GeneratorBayouTree> 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;
}
protected int minLeavesRadius;
protected int leavesGradient;
protected int vineAttempts;
protected int maxVineLength;
protected IBlockPosQuery rootsReplace;
public Builder minLeavesRadius(int a) {this.minLeavesRadius = a; return this.self();}
public Builder leavesGradient(int a) {this.leavesGradient = a; return this.self();}
public Builder vineAttempts(int a) {this.vineAttempts = a; return this.self();}
public Builder maxVineLength(int a) {this.maxVineLength = a; return this.self();}
public Builder rootsReplace(IBlockPosQuery a) {this.replace = a; return this.self();}
public Builder rootsReplace(String a) throws BlockQueryParseException {this.replace = BlockQuery.parseQueryString(a); return this.self();}
public Builder rootsReplace(Block a) {this.replace = new BlockQueryBlock(a); return this.self();}
public Builder rootsReplace(IBlockState a) {this.replace = new BlockQueryState(a); return this.self();}
public Builder()
{
// defaults
this.amountPerChunk = 1.0F;
this.placeOn = BlockQueries.fertile;
this.replace = BlockQueries.airOrLeaves;
this.rootsReplace = BlockQueries.rootsCanDigThrough;
this.log = Blocks.log.getDefaultState();
this.leaves = Blocks.leaves.getDefaultState();
this.vine = null;
this.minHeight = 8;
this.maxHeight = 18;
this.minLeavesRadius = 2;
this.leavesGradient = 4;
this.vineAttempts = 10;
this.maxVineLength = 20;
}
@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);
return new GeneratorBayouTree(this.amountPerChunk, this.placeOn, this.replace, this.log, this.leaves, this.vine, this.minHeight, this.maxHeight, this.minLeavesRadius, this.leavesGradient, this.vineAttempts, this.maxVineLength, this.rootsReplace);
}
}
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)
public GeneratorBayouTree(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState log, IBlockState leaves, IBlockState vine, int minHeight, int maxHeight, int minLeavesRadius, int leavesGradient, int vineAttempts, int maxVineLength, IBlockPosQuery rootsReplace)
{
super(amountPerChunk);
this.minHeight = minHeight;
this.maxHeight = maxHeight;
super(amountPerChunk, placeOn, replace, log, leaves, vine, minHeight, 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
// always at ground (sometimes underwater)
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))
@ -186,20 +103,6 @@ public class GeneratorBayouTree extends BOPGeneratorBase
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

View file

@ -14,76 +14,47 @@ import java.util.Random;
import org.apache.commons.lang3.tuple.Pair;
import net.minecraft.block.BlockLog;
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.BlockSapling;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
import biomesoplenty.api.biome.generation.BOPGeneratorBase;
import biomesoplenty.common.block.BlockBOPLeaves;
import biomesoplenty.common.block.BlockBOPLog;
import biomesoplenty.common.enums.BOPTrees;
import biomesoplenty.common.enums.BOPWoods;
import biomesoplenty.api.block.BlockQueries;
import biomesoplenty.common.util.biome.GeneratorUtils;
import biomesoplenty.common.util.block.BlockQuery.BlockQueryMaterial;
import biomesoplenty.common.util.block.BlockQuery.IBlockPosQuery;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
import com.google.common.collect.Lists;
/*This class is heavily based on https://gist.github.com/grum/62cfdec0537e8db24eb3#file-bigtreefeature-java
additional information has been added from http://pastebin.com/XBLdGqXQ. This class has been cross-checked
against WorldGenBigTree to ensure any subsequent changes from Forge/Mojang have been included.*/
public class GeneratorBigTree extends BOPGeneratorBase
public class GeneratorBigTree extends GeneratorTreeBase
{
public static class Builder implements IGeneratorBuilder<GeneratorBigTree>
{
protected float amountPerChunk = 1.0F;
protected boolean updateNeighbours = false;
protected int minHeight = 5;
protected int maxHeight = 17;
protected IBlockState log = Blocks.log.getDefaultState();
protected IBlockState leaves = Blocks.leaves.getDefaultState();
public Builder amountPerChunk(float a) {this.amountPerChunk = a; return this;}
public Builder updateNeighbours(boolean a) {this.updateNeighbours = 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 log(IBlockState a) {this.log = a; return this;}
public Builder log(BlockPlanks.EnumType a)
// TODO: update neighbours in builder?
public static class Builder extends GeneratorTreeBase.InnerBuilder<Builder, GeneratorBigTree> implements IGeneratorBuilder<GeneratorBigTree>
{
public Builder()
{
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 log(BOPWoods a) {this.log = BlockBOPLog.paging.getVariantState(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;
// defaults
this.amountPerChunk = 1.0F;
this.placeOn = BlockQueries.anything;
this.replace = new BlockQueryMaterial(Material.air);
this.log = Blocks.log.getDefaultState();
this.leaves = Blocks.leaves.getDefaultState();
this.vine = null;
this.minHeight = 5;
this.maxHeight = 17;
}
@Override
public GeneratorBigTree create()
{
return new GeneratorBigTree(this.amountPerChunk, this.updateNeighbours, this.minHeight, this.maxHeight, this.log, this.leaves);
return new GeneratorBigTree(this.amountPerChunk, this.placeOn, this.replace, this.log, this.leaves, this.vine, this.minHeight, this.maxHeight, false);
}
}
@ -104,24 +75,14 @@ public class GeneratorBigTree extends BOPGeneratorBase
//Configurable fields
private boolean updateNeighbours;
private int minHeight;
private int maxHeight;
private IBlockState log;
private IBlockState leaves;
private List<FoliageCoords> foliageCoords;
public GeneratorBigTree(float amountPerChunk, boolean updateNeighbours, int minHeight, int maxHeight, IBlockState log, IBlockState leaves)
public GeneratorBigTree(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState log, IBlockState leaves, IBlockState vine, int minHeight, int maxHeight, boolean updateNeighbours)
{
super(amountPerChunk);
super(amountPerChunk, placeOn, replace, log, leaves, vine, minHeight, maxHeight);
this.updateNeighbours = updateNeighbours;
Pair<Integer, Integer> heights = GeneratorUtils.validateMinMaxHeight(minHeight, maxHeight);
this.minHeight = heights.getLeft();
this.maxHeight = heights.getRight();
this.log = log;
this.leaves = leaves;
}
protected void prepare()
@ -213,9 +174,7 @@ public class GeneratorBigTree extends BOPGeneratorBase
if (Math.pow(Math.abs(dx) + 0.5, 2) + Math.pow(Math.abs(dz) + 0.5, 2) <= radius * radius)
{
BlockPos checkedPos = pos.add(dx, 0, dz);
IBlockState checkedState = this.world.getBlockState(checkedPos);
if (checkedState.getBlock().isAir(this.world, checkedPos) || checkedState.getBlock().isLeaves(this.world, checkedPos))
if (this.replace.matches(world, checkedPos))
{
this.setBlockAndNotifyAdequately(world, checkedPos, state);
}
@ -466,7 +425,7 @@ public class GeneratorBigTree extends BOPGeneratorBase
//is added to ensure the final point is reached.
BlockPos deltaPos = startPos.add((double)(0.5F + (float)i * dx), (double)(0.5F + (float)i * dy), (double)(0.5F + (float)i * dz));
if (!GeneratorUtils.canTreeReplace(world, deltaPos))
if (!this.replace.matches(world, deltaPos))
{
return i;
}
@ -478,13 +437,6 @@ public class GeneratorBigTree extends BOPGeneratorBase
@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);
}
@Override
public boolean generate(World world, Random rand, BlockPos pos)
{
@ -527,7 +479,7 @@ public class GeneratorBigTree extends BOPGeneratorBase
boolean isSoil = state.getBlock().canSustainPlant(this.world, down, EnumFacing.UP, ((BlockSapling)Blocks.sapling));
//Don't grow the tree here if the location can't sustain a sapling
if (!isSoil)
if (!isSoil || !this.placeOn.matches(world, down))
{
return false;
}

View file

@ -9,149 +9,45 @@
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.BlockDirectional;
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 GeneratorBulbTree extends BOPGeneratorBase
public class GeneratorBulbTree extends GeneratorTreeBase
{
public static class Builder implements IGeneratorBuilder<GeneratorBulbTree>
public static class Builder extends GeneratorTreeBase.InnerBuilder<Builder, GeneratorBulbTree> implements IGeneratorBuilder<GeneratorBulbTree>
{
protected float amountPerChunk = 1.0F;
protected int minHeight = 6;
protected int maxHeight = 12;
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();
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 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 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)
public Builder()
{
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;
this.amountPerChunk = 1.0F;
this.minHeight = 6;
this.maxHeight = 12;
this.placeOn = BlockQueries.fertile;
this.replace = BlockQueries.airOrLeaves;
this.log = Blocks.log.getDefaultState();
this.leaves = Blocks.leaves.getDefaultState();
this.vine = Blocks.vine.getDefaultState();
}
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 GeneratorBulbTree create()
{
return new GeneratorBulbTree(this.amountPerChunk, this.minHeight, this.maxHeight, this.placeOn, this.replace, this.log, this.leaves, this.vine);
public GeneratorBulbTree create() {
return new GeneratorBulbTree(this.amountPerChunk, this.placeOn, this.replace, this.log, this.leaves, this.vine, this.minHeight, this.maxHeight);
}
}
private int minHeight;
private int maxHeight;
private IBlockPosQuery placeOn;
private IBlockPosQuery replace;
private IBlockState log;
private IBlockState leaves;
private IBlockState vine;
public GeneratorBulbTree(float amountPerChunk, int minHeight, int maxHeight, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState log, IBlockState leaves, IBlockState vine)
{
super(amountPerChunk);
this.minHeight = minHeight;
this.maxHeight = maxHeight;
this.placeOn = placeOn;
this.replace = replace;
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_SURFACE.getBlockPos(world, random, x, z);
}
public boolean setLeaves(World world, BlockPos pos)
public GeneratorBulbTree(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState log, IBlockState leaves, IBlockState vine, int minHeight, int maxHeight)
{
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;
super(amountPerChunk, placeOn, replace, log, leaves, vine, minHeight, maxHeight);
}
public boolean setCocoa(World world, BlockPos pos, EnumFacing side)
@ -165,20 +61,6 @@ public class GeneratorBulbTree extends BOPGeneratorBase
return false;
}
public boolean setVine(World world, 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)
{
world.setBlockState(pos, vineState, 2);
setOne = true;
length--;
pos = pos.down();
}
return setOne;
}
public boolean checkSpace(World world, BlockPos pos, int baseHeight, int height)
{
for (int y = 0; y <= height; y++)
@ -326,7 +208,7 @@ public class GeneratorBulbTree extends BOPGeneratorBase
for (int l = 0; l < leavesRadius; l++)
{
if (world.getBlockState(pos.offset(back, 1 + l)) == this.leaves) {
this.setVine(world, pos.offset(back, l), back, 4);
this.setVine(world, rand, pos.offset(back, l), back, 4);
break;
}
}

View file

@ -10,136 +10,84 @@ package biomesoplenty.common.world.feature.tree;
import java.util.Random;
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.BlockSapling;
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;
import biomesoplenty.api.biome.generation.BOPGeneratorBase;
import biomesoplenty.common.block.BlockBOPLeaves;
import biomesoplenty.common.block.BlockBOPLog;
import biomesoplenty.common.enums.BOPTrees;
import biomesoplenty.common.enums.BOPWoods;
import biomesoplenty.api.block.BlockQueries;
import biomesoplenty.common.util.biome.GeneratorUtils;
import biomesoplenty.common.util.block.BlockQuery.IBlockPosQuery;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
public class GeneratorBush extends BOPGeneratorBase
public class GeneratorBush extends GeneratorTreeBase
{
public static class Builder implements IGeneratorBuilder<GeneratorBush>
{
protected float amountPerChunk = 1.0F;
protected IBlockState log = Blocks.log.getDefaultState();
protected IBlockState leaves = Blocks.leaves.getDefaultState();
public Builder amountPerChunk(float a) {this.amountPerChunk = 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)
public static class Builder extends GeneratorTreeBase.InnerBuilder<Builder, GeneratorBush> implements IGeneratorBuilder<GeneratorBush>
{
public Builder()
{
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;
}
this.amountPerChunk = 1.0F;
this.minHeight = 2;
this.maxHeight = 4;
this.placeOn = BlockQueries.fertile;
this.replace = BlockQueries.airOrLeaves;
this.log = Blocks.log.getDefaultState();
this.leaves = Blocks.leaves.getDefaultState();
this.vine = null;
}
@Override
public GeneratorBush create()
{
return new GeneratorBush(this.amountPerChunk, this.log, this.leaves);
public GeneratorBush create() {
return new GeneratorBush(this.amountPerChunk, this.placeOn, this.replace, this.log, this.leaves, this.vine, this.minHeight, this.maxHeight);
}
}
private IBlockState log;
private IBlockState leaves;
public GeneratorBush(float amountPerChunk, IBlockState log, IBlockState leaves)
public GeneratorBush(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState log, IBlockState leaves, IBlockState vine, int minHeight, int maxHeight)
{
super(amountPerChunk);
this.log = log;
this.leaves = leaves;
}
@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);
super(amountPerChunk, placeOn, replace, log, leaves, vine, minHeight, maxHeight);
}
@Override
public boolean generate(World world, Random random, BlockPos pos)
public boolean generate(World world, Random random, BlockPos startPos)
{
Block block;
//Move down until we reach the ground
do
// Move down until we reach the ground
while (startPos.getY() > 1 && world.isAirBlock(startPos) || world.getBlockState(startPos).getBlock().isLeaves(world, startPos)) {startPos = startPos.down();}
if (!this.placeOn.matches(world, startPos))
{
block = world.getBlockState(pos).getBlock();
if (!block.isAir(world, pos) && !block.isLeaves(world, pos)) break;
pos = pos.down();
}
while (pos.getY() > 0);
// Abandon if we can't place the tree on this block
return false;
}
// choose a random height
int height = GeneratorUtils.nextIntBetween(random, this.minHeight, this.maxHeight);
// start from the block above the ground block
BlockPos pos = startPos.up();
//Check if the ground block can sustain a sapling before generating above it
if (block.canSustainPlant(world, pos, EnumFacing.UP, ((BlockSapling)Blocks.sapling)))
//Generate a bush 3 blocks tall, with the bottom block already set to a log
for (int y = 0; y < height; ++y)
{
pos = pos.up();
world.setBlockState(pos, this.log, 2);
//Reduces the radius closer to the top of the bush
int leavesRadius = (height - y > 1 ? 2 : 1);
//Generate a bush 3 blocks tall, with the bottom block already set to a log
for (int y = pos.getY(); y <= pos.getY() + 2; ++y)
for (int x = -leavesRadius; x <= leavesRadius; ++x)
{
//Determines the distance away from the bottom of the bush
int currentLayer = y - pos.getY();
//Reduces the radius closer to the top of the bush
int leavesRadius = 2 - currentLayer;
for (int x = pos.getX() - leavesRadius; x <= pos.getX() + leavesRadius; ++x)
for (int z = -leavesRadius; z <= leavesRadius; ++z)
{
int xDiff = x - pos.getX();
for (int z = pos.getZ() - leavesRadius; z <= pos.getZ() + leavesRadius; ++z)
//Randomly prevent the generation of leaves on the corners of each layer
if (Math.abs(x) < leavesRadius || Math.abs(z) < leavesRadius || random.nextInt(2) != 0)
{
int zDiff = z - pos.getZ();
//Randomly prevent the generation of leaves on the corners of each layer
if (Math.abs(xDiff) != leavesRadius || Math.abs(zDiff) != leavesRadius || random.nextInt(2) != 0)
{
BlockPos leavesPos = new BlockPos(x, y, z);
//Ensures the leaves can replace surrounding blocks, preventing the existing log from being overriden alongside
//other terrain
if (world.isAirBlock(leavesPos))
{
world.setBlockState(leavesPos, this.leaves, 2);
}
}
this.setLeaves(world, pos.add(x, y, z));
}
}
}
// log in the center
if (height - y > 1)
{
this.setLog(world, pos.add(0, y, 0));
}
}
return true;

View file

@ -8,113 +8,47 @@
package biomesoplenty.common.world.feature.tree;
import java.util.Random;
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.material.Material;
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;
import biomesoplenty.api.biome.generation.BOPGeneratorBase;
import biomesoplenty.common.block.BlockBOPLeaves;
import biomesoplenty.common.block.BlockBOPLog;
import biomesoplenty.common.enums.BOPTrees;
import biomesoplenty.common.enums.BOPWoods;
import biomesoplenty.api.block.BlockQueries;
import biomesoplenty.common.util.biome.GeneratorUtils;
import biomesoplenty.common.util.block.BlockQuery;
import biomesoplenty.common.util.block.BlockQuery.*;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
public class GeneratorPineTree extends BOPGeneratorBase
public class GeneratorPineTree extends GeneratorTreeBase
{
public static class Builder implements IGeneratorBuilder<GeneratorPineTree>
public static class Builder extends GeneratorTreeBase.InnerBuilder<Builder, GeneratorPineTree> implements IGeneratorBuilder<GeneratorPineTree>
{
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 IBlockState log = BlockBOPLog.paging.getVariantState(BOPWoods.PINE);
protected IBlockState leaves = BlockBOPLeaves.paging.getVariantState(BOPTrees.PINE);
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 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 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)
public Builder()
{
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;
this.amountPerChunk = 1.0F;
this.minHeight = 6;
this.maxHeight = 12;
this.placeOn = BlockQueries.fertile;
this.replace = BlockQueries.airOrLeaves;
this.log = Blocks.log.getDefaultState();
this.leaves = Blocks.leaves.getDefaultState();
this.vine = null;
}
@Override
public GeneratorPineTree create()
{
return new GeneratorPineTree(this.amountPerChunk, this.minHeight, this.maxHeight, this.placeOn, this.replace, this.log, this.leaves);
public GeneratorPineTree create() {
return new GeneratorPineTree(this.amountPerChunk, this.placeOn, this.replace, this.log, this.leaves, this.vine, this.minHeight, this.maxHeight);
}
}
private int minHeight;
private int maxHeight;
private IBlockPosQuery placeOn;
private IBlockPosQuery replace;
private IBlockState log;
private IBlockState leaves;
public GeneratorPineTree(float amountPerChunk, int minHeight, int maxHeight, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState log, IBlockState leaves)
public GeneratorPineTree(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState log, IBlockState leaves, IBlockState vine, int minHeight, int maxHeight)
{
super(amountPerChunk);
this.minHeight = minHeight;
this.maxHeight = maxHeight;
this.placeOn = placeOn;
this.replace = replace;
this.log = log;
this.leaves = leaves;
super(amountPerChunk, placeOn, replace, log, leaves, vine, minHeight, maxHeight);
}
@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);
}
@Override
public boolean generate(World world, Random random, BlockPos pos)
@ -165,26 +99,6 @@ public class GeneratorPineTree extends BOPGeneratorBase
return true;
}
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 checkSpace(World world, BlockPos pos, int baseHeight, int height)
{
for (int y = 0; y <= height; y++)

View file

@ -0,0 +1,160 @@
/*******************************************************************************
* 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 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;
import biomesoplenty.api.biome.generation.BOPGeneratorBase;
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;
public abstract class GeneratorTreeBase extends BOPGeneratorBase
{
protected IBlockPosQuery placeOn;
protected IBlockPosQuery replace;
protected IBlockState log;
protected IBlockState leaves;
protected IBlockState vine;
protected int minHeight;
protected int maxHeight;
protected GeneratorTreeBase(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState log, IBlockState leaves, IBlockState vine, int minHeight, int maxHeight) {
super(amountPerChunk);
this.placeOn = placeOn;
this.replace = replace;
this.log = log;
this.leaves = leaves;
this.vine = vine;
this.minHeight = minHeight;
this.maxHeight = maxHeight;
}
protected static abstract class InnerBuilder<T extends InnerBuilder<T, G>, G extends GeneratorTreeBase> extends BOPGeneratorBase.InnerBuilder<T, G>
{
protected IBlockPosQuery placeOn;
protected IBlockPosQuery replace;
protected IBlockState log;
protected IBlockState leaves;
protected IBlockState vine;
protected int minHeight;
protected int maxHeight;
public T placeOn(IBlockPosQuery a) {this.placeOn = a; return this.self();}
public T placeOn(String a) throws BlockQueryParseException {this.placeOn = BlockQuery.parseQueryString(a); return this.self();}
public T placeOn(Block a) {this.placeOn = new BlockQueryBlock(a); return this.self();}
public T placeOn(IBlockState a) {this.placeOn = new BlockQueryState(a); return this.self();}
public T replace(IBlockPosQuery a) {this.replace = a; return this.self();}
public T replace(String a) throws BlockQueryParseException {this.replace = BlockQuery.parseQueryString(a); return this.self();}
public T replace(Block a) {this.replace = new BlockQueryBlock(a); return this.self();}
public T replace(IBlockState a) {this.replace = new BlockQueryState(a); return this.self();}
public T log(IBlockState a) {this.log = a; return this.self();}
public T log(BOPWoods a) {this.log = BlockBOPLog.paging.getVariantState(a); return this.self();}
public T 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.self();
}
public T leaves(IBlockState a) {this.leaves = a; return this.self();}
public T leaves(BOPTrees a) {this.leaves = BlockBOPLeaves.paging.getVariantState(a); return this.self();}
public T 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.self();
}
public T vine(IBlockState a)
{
if (a.getBlock() instanceof BlockVine)
{
this.vine = a;
} else {
throw new IllegalArgumentException("vine must use a BlockVine block");
}
return this.self();
}
public T minHeight(int a) {this.minHeight = a; return this.self();}
public T maxHeight(int a) {this.maxHeight = a; return this.self();}
}
@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);
}
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 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;
}
}

View file

@ -10,135 +10,61 @@ package biomesoplenty.common.world.feature.tree;
import java.util.Random;
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.BlockSapling;
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;
import biomesoplenty.api.biome.generation.BOPGeneratorBase;
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.api.block.BlockQueries;
import biomesoplenty.common.util.block.BlockQuery.IBlockPosQuery;
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
public class GeneratorTwigletTree extends BOPGeneratorBase
public class GeneratorTwigletTree extends GeneratorTreeBase
{
public static class Builder implements IGeneratorBuilder<GeneratorTwigletTree>
public static class Builder extends GeneratorTreeBase.InnerBuilder<Builder, GeneratorTwigletTree> implements IGeneratorBuilder<GeneratorTwigletTree>
{
protected float amountPerChunk = 1.0F;
protected IBlockState log = Blocks.log.getDefaultState();
protected IBlockState leaves = Blocks.leaves.getDefaultState();
protected int minHeight = 2;
protected int maxHeight = 3;
protected float leafChance = 0.9F;
protected float leafChance;
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 leafChance(float a) {this.leafChance = 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)
public Builder leafChance(float a) {this.leafChance = a; return this.self();}
public Builder()
{
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;
}
this.amountPerChunk = 1.0F;
this.minHeight = 2;
this.maxHeight = 6;
this.placeOn = BlockQueries.fertile;
this.replace = BlockQueries.airOrLeaves;
this.log = Blocks.log.getDefaultState();
this.leaves = Blocks.leaves.getDefaultState();
this.vine = null;
this.leafChance = 0.9F;
}
@Override
public GeneratorTwigletTree create()
{
return new GeneratorTwigletTree(this.amountPerChunk, this.minHeight, this.maxHeight, this.leafChance, this.log, this.leaves);
public GeneratorTwigletTree create() {
return new GeneratorTwigletTree(this.amountPerChunk, this.placeOn, this.replace, this.log, this.leaves, this.vine, this.minHeight, this.maxHeight, this.leafChance);
}
}
private int minHeight;
private int maxHeight;
private float leafChance;
private IBlockState log;
private IBlockState leaves;
public GeneratorTwigletTree(float amountPerChunk, int minHeight, int maxHeight, float leafChance, IBlockState log, IBlockState leaves)
public GeneratorTwigletTree(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState log, IBlockState leaves, IBlockState vine, int minHeight, int maxHeight, float leafChance)
{
super(amountPerChunk);
this.minHeight = minHeight;
this.maxHeight = maxHeight;
super(amountPerChunk, placeOn, replace, log, leaves, vine, minHeight, maxHeight);
this.leafChance = leafChance;
this.log = log;
this.leaves = leaves;
}
@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);
}
public boolean setLeaves(World world, BlockPos pos)
{
if (world.getBlockState(pos).getBlock().canBeReplacedByLeaves(world, pos))
{
world.setBlockState(pos, this.leaves, 2);
return true;
}
return false;
}
public boolean setLog(World world, BlockPos pos)
{
if (world.getBlockState(pos).getBlock().canBeReplacedByLeaves(world, pos))
{
world.setBlockState(pos, this.log, 2);
return true;
}
return false;
}
@Override
public boolean generate(World world, Random random, BlockPos pos)
public boolean generate(World world, Random random, BlockPos startPos)
{
Block block;
//Move down until we reach the ground
do
{
block = world.getBlockState(pos).getBlock();
if (!block.isAir(world, pos) && !block.isLeaves(world, pos)) break;
pos = pos.down();
}
while (pos.getY() > 0);
//Check if the ground block can sustain a sapling before generating above it
if (!block.canSustainPlant(world, pos, EnumFacing.UP, ((BlockSapling)Blocks.sapling)))
// Move down until we reach the ground
while (startPos.getY() > 1 && world.isAirBlock(startPos) || world.getBlockState(startPos).getBlock().isLeaves(world, startPos)) {startPos = startPos.down();}
if (!this.placeOn.matches(world, startPos))
{
// Abandon if we can't place the tree on this block
return false;
}
@ -147,7 +73,7 @@ public class GeneratorTwigletTree extends BOPGeneratorBase
int baseHeight = height / 3;
// start from the block above the ground block
pos = pos.up();
BlockPos pos = startPos.up();
// add log and leaves on each level
for (int y = 0; y < height; y++)