Added proper Mangrove trees
This commit is contained in:
parent
8427e01748
commit
ba6d47938d
4 changed files with 306 additions and 20 deletions
|
@ -10,36 +10,26 @@ package biomesoplenty.common.biome.overworld;
|
|||
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.ChunkPrimer;
|
||||
import biomesoplenty.api.biome.BOPBiome;
|
||||
import biomesoplenty.api.biome.generation.GeneratorStage;
|
||||
import biomesoplenty.api.biome.generation.GeneratorWeighted;
|
||||
import biomesoplenty.api.block.BOPBlocks;
|
||||
import biomesoplenty.common.block.BlockBOPLeaves;
|
||||
import biomesoplenty.common.block.BlockBOPSand;
|
||||
import biomesoplenty.common.entities.EntityButterfly;
|
||||
import biomesoplenty.common.enums.BOPFlowers;
|
||||
import biomesoplenty.common.enums.BOPGems;
|
||||
import biomesoplenty.common.enums.BOPPlants;
|
||||
import biomesoplenty.common.enums.BOPTrees;
|
||||
import biomesoplenty.common.enums.BOPWoods;
|
||||
import biomesoplenty.common.util.block.BlockQuery;
|
||||
import biomesoplenty.common.util.block.BlockQuery.IBlockPosQuery;
|
||||
import biomesoplenty.common.util.config.BOPConfig.IConfigObj;
|
||||
import biomesoplenty.common.world.BOPWorldSettings;
|
||||
import biomesoplenty.common.world.feature.GeneratorFlora;
|
||||
import biomesoplenty.common.world.feature.GeneratorGrass;
|
||||
import biomesoplenty.common.world.feature.GeneratorLakes;
|
||||
import biomesoplenty.common.world.feature.GeneratorOreSingle;
|
||||
import biomesoplenty.common.world.feature.tree.GeneratorBasicTree;
|
||||
import biomesoplenty.common.world.feature.tree.GeneratorBayouTree;
|
||||
import net.minecraft.block.BlockFlower;
|
||||
import net.minecraft.block.BlockOldLeaf;
|
||||
import net.minecraft.block.BlockTallGrass;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.ChunkPrimer;
|
||||
import biomesoplenty.common.world.feature.tree.GeneratorMangroveTree;
|
||||
|
||||
public class BiomeGenMangrove extends BOPBiome
|
||||
{
|
||||
|
@ -75,9 +65,9 @@ public class BiomeGenMangrove extends BOPBiome
|
|||
|
||||
// trees & logs
|
||||
IBlockPosQuery emptySandMud = BlockQuery.buildAnd().states(this.usualTopBlock).create();
|
||||
GeneratorWeighted treeGenerator = new GeneratorWeighted(10);
|
||||
GeneratorWeighted treeGenerator = new GeneratorWeighted(7);
|
||||
this.addGenerator("trees", GeneratorStage.TREE, treeGenerator);
|
||||
treeGenerator.add("mangrove", 1, (new GeneratorBayouTree.Builder()).placeOn(emptySandMud).log(BOPWoods.MANGROVE).leaves(BOPTrees.MANGROVE).minHeight(6).maxHeight(8).minLeavesRadius(1).vine(null).leavesGradient(1).create());
|
||||
treeGenerator.add("mangrove", 1, (new GeneratorMangroveTree.Builder()).placeOn(emptySandMud).log(BOPWoods.MANGROVE).leaves(BOPTrees.MANGROVE).create());
|
||||
|
||||
// gem
|
||||
this.addGenerator("sapphire", GeneratorStage.SAND, (new GeneratorOreSingle.Builder()).amountPerChunk(12).with(BOPGems.SAPPHIRE).create());
|
||||
|
|
|
@ -20,6 +20,7 @@ import biomesoplenty.common.world.feature.tree.GeneratorBasicTree;
|
|||
import biomesoplenty.common.world.feature.tree.GeneratorBigTree;
|
||||
import biomesoplenty.common.world.feature.tree.GeneratorBulbTree;
|
||||
import biomesoplenty.common.world.feature.tree.GeneratorMahoganyTree;
|
||||
import biomesoplenty.common.world.feature.tree.GeneratorMangroveTree;
|
||||
import biomesoplenty.common.world.feature.tree.GeneratorPalmTree;
|
||||
import biomesoplenty.common.world.feature.tree.GeneratorPineTree;
|
||||
import biomesoplenty.common.world.feature.tree.GeneratorRedwoodTree;
|
||||
|
@ -202,7 +203,7 @@ public class BlockBOPSapling extends BlockBOPDecoration implements IGrowable {
|
|||
case SACRED_OAK:
|
||||
return new GeneratorBigTree.Builder().log(BOPWoods.SACRED_OAK).leaves(BOPTrees.SACRED_OAK).minHeight(35).maxHeight(45).trunkWidth(2).foliageDensity(1.25D).create();
|
||||
case MANGROVE: //Not implemented
|
||||
return new WorldGenTrees(true);
|
||||
return new GeneratorMangroveTree.Builder().log(BOPWoods.MANGROVE).leaves(BOPTrees.MANGROVE).create();
|
||||
case PALM:
|
||||
return new GeneratorPalmTree.Builder().log(BOPWoods.PALM).leaves(BlockBOPLeaves.paging.getVariantState(BOPTrees.PALM).withProperty(BlockOldLeaf.CHECK_DECAY, Boolean.valueOf(false))).create();
|
||||
case REDWOOD:
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
package biomesoplenty.common.init;
|
||||
|
||||
import static biomesoplenty.api.biome.generation.GeneratorRegistry.registerGenerator;
|
||||
|
||||
import biomesoplenty.api.biome.generation.GeneratorWeighted;
|
||||
import biomesoplenty.common.world.feature.GeneratorBigFlower;
|
||||
import biomesoplenty.common.world.feature.GeneratorBigMushroom;
|
||||
|
@ -34,6 +33,7 @@ import biomesoplenty.common.world.feature.tree.GeneratorBigTree;
|
|||
import biomesoplenty.common.world.feature.tree.GeneratorBulbTree;
|
||||
import biomesoplenty.common.world.feature.tree.GeneratorBush;
|
||||
import biomesoplenty.common.world.feature.tree.GeneratorMahoganyTree;
|
||||
import biomesoplenty.common.world.feature.tree.GeneratorMangroveTree;
|
||||
import biomesoplenty.common.world.feature.tree.GeneratorMegaJungleTree;
|
||||
import biomesoplenty.common.world.feature.tree.GeneratorPalmTree;
|
||||
import biomesoplenty.common.world.feature.tree.GeneratorPineTree;
|
||||
|
@ -57,6 +57,7 @@ public class ModGenerators
|
|||
registerGenerator("bulb_tree", GeneratorBulbTree.class, new GeneratorBulbTree.Builder());
|
||||
registerGenerator("mega_jungle_tree", GeneratorMegaJungleTree.class, new GeneratorMegaJungleTree.Builder());
|
||||
registerGenerator("bayou_tree", GeneratorBayouTree.class, new GeneratorBayouTree.Builder());
|
||||
registerGenerator("mangrove_tree", GeneratorMangroveTree.class, new GeneratorMangroveTree.Builder());
|
||||
registerGenerator("taiga_tree", GeneratorTaigaTree.class, new GeneratorTaigaTree.Builder());
|
||||
registerGenerator("profile_tree", GeneratorProfileTree.class, new GeneratorProfileTree.Builder());
|
||||
registerGenerator("flora", GeneratorFlora.class, new GeneratorFlora.Builder());
|
||||
|
|
|
@ -0,0 +1,294 @@
|
|||
/*******************************************************************************
|
||||
* Copyright 2015-2016, the Biomes O' Plenty Team
|
||||
*
|
||||
* This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License.
|
||||
*
|
||||
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/.
|
||||
******************************************************************************/
|
||||
|
||||
package biomesoplenty.common.world.feature.tree;
|
||||
import java.util.Random;
|
||||
|
||||
import biomesoplenty.api.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;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class GeneratorMangroveTree extends GeneratorTreeBase
|
||||
{
|
||||
|
||||
public static class Builder extends GeneratorTreeBase.InnerBuilder<Builder, GeneratorMangroveTree> implements IGeneratorBuilder<GeneratorMangroveTree>
|
||||
{
|
||||
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.hanging = null;
|
||||
this.altLeaves = null;
|
||||
this.minHeight = 8;
|
||||
this.maxHeight = 10;
|
||||
this.minLeavesRadius = 1;
|
||||
this.leavesGradient = 1;
|
||||
this.vineAttempts = 20;
|
||||
this.maxVineLength = 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeneratorMangroveTree create()
|
||||
{
|
||||
return new GeneratorMangroveTree(this.amountPerChunk, this.placeOn, this.replace, this.log, this.leaves, this.vine, this.hanging, this.altLeaves, this.minHeight, this.maxHeight, this.minLeavesRadius, this.leavesGradient, this.vineAttempts, this.maxVineLength, this.rootsReplace);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int minLeavesRadius;
|
||||
private int leavesGradient;
|
||||
private int vineAttempts;
|
||||
private int maxVineLength;
|
||||
private IBlockPosQuery rootsReplace;
|
||||
|
||||
public GeneratorMangroveTree(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState log, IBlockState leaves, IBlockState vine, IBlockState hanging, IBlockState altLeaves, int minHeight, int maxHeight, int minLeavesRadius, int leavesGradient, int vineAttempts, int maxVineLength, IBlockPosQuery rootsReplace)
|
||||
{
|
||||
super(amountPerChunk, placeOn, replace, log, leaves, vine, hanging, altLeaves, minHeight, maxHeight);
|
||||
this.minLeavesRadius = minLeavesRadius;
|
||||
this.leavesGradient = leavesGradient;
|
||||
this.vineAttempts = vineAttempts;
|
||||
this.maxVineLength = maxVineLength;
|
||||
this.rootsReplace = rootsReplace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getScatterY(World world, Random random, int x, int z)
|
||||
{
|
||||
// always at ground (sometimes underwater)
|
||||
return GeneratorUtils.ScatterYMethod.AT_GROUND.getBlockPos(world, random, x, z);
|
||||
}
|
||||
|
||||
public boolean setRoot(World world, BlockPos pos)
|
||||
{
|
||||
if (this.rootsReplace.matches(world, pos))
|
||||
{
|
||||
world.setBlockState(pos, this.log, 2);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean checkRootViable(World world, BlockPos pos, int rootHeight, EnumFacing direction)
|
||||
{
|
||||
// a viable root has an path which roots can dig through from trunk to some fertile ground
|
||||
pos = pos.offset(direction).up(rootHeight - 1);
|
||||
for (int i = 0; i < rootHeight; i++)
|
||||
{
|
||||
if (!this.rootsReplace.matches(world, pos)) {return false;}
|
||||
pos = pos.down();
|
||||
if (this.placeOn.matches(world, pos)) {return true;}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean checkSpace(World world, BlockPos pos, int rootHeight, int middleHeight, int height)
|
||||
{
|
||||
|
||||
// we want at least 2 of the roots to be viable
|
||||
int rootsOk = 0;
|
||||
for (EnumFacing direction : EnumFacing.Plane.HORIZONTAL)
|
||||
{
|
||||
if (this.checkRootViable(world, pos, rootHeight, direction)) {rootsOk++;}
|
||||
}
|
||||
if (rootsOk < 2) {return false;}
|
||||
|
||||
// check there's some space for the trunk and leaves too
|
||||
for (int y = rootHeight; y <= height; y++)
|
||||
{
|
||||
// require 1x1 for the trunk, 3x3 for the leaves
|
||||
int radius = (y <= (rootHeight + middleHeight) ? 0 : 1);
|
||||
for (int x = -radius; x <= radius; x++)
|
||||
{
|
||||
for (int z = -radius; z <= radius; z++)
|
||||
{
|
||||
BlockPos pos1 = pos.add(x, y, z);
|
||||
// note, there may be a sapling on the first layer - make sure this.replace matches it!
|
||||
if (pos1.getY() >= 255 || !this.replace.matches(world, pos1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void generateTop(World world, Random random, BlockPos pos, int topHeight)
|
||||
{
|
||||
|
||||
for (int y = 0; y < topHeight; y++)
|
||||
{
|
||||
int radius = Math.min(3, this.minLeavesRadius + (topHeight - y) / this.leavesGradient);
|
||||
|
||||
for (int x = -radius; x <= radius; ++x)
|
||||
{
|
||||
for (int z = -radius; z <= radius; ++z)
|
||||
{
|
||||
// too far away and the leaves will decay
|
||||
int dist = Math.abs(x) + Math.abs(z);
|
||||
if (dist < 4 || (dist == 4 && random.nextInt(2) == 0))
|
||||
{
|
||||
this.setLeaves(world, pos.add(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (y < topHeight - 1)
|
||||
{
|
||||
// add the trunk in the middle
|
||||
this.setLog(world, pos.add(0, y, 0));
|
||||
} else {
|
||||
// add leaves on top for certain
|
||||
this.setLeaves(world, pos.add(0, y, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void generateRoots(World world, Random random, BlockPos pos, int rootHeight)
|
||||
{
|
||||
this.setRoot(world, pos.north().add(0, rootHeight, 0));
|
||||
this.setRoot(world, pos.east().add(0, rootHeight, 0));
|
||||
this.setRoot(world, pos.south().add(0, rootHeight, 0));
|
||||
this.setRoot(world, pos.west().add(0, rootHeight, 0));
|
||||
|
||||
for (int i = 0; i < rootHeight; i++)
|
||||
{
|
||||
this.setRoot(world, pos.north().north());
|
||||
this.setRoot(world, pos.east().east());
|
||||
this.setRoot(world, pos.south().south());
|
||||
this.setRoot(world, pos.west().west());
|
||||
pos = pos.up();
|
||||
}
|
||||
//this.setRoot(world, pos.down());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean generate(World world, Random random, BlockPos startPos)
|
||||
{
|
||||
|
||||
if (!this.placeOn.matches(world, startPos.down()))
|
||||
{
|
||||
// Abandon if we can't place the tree on this block
|
||||
return false;
|
||||
}
|
||||
|
||||
// Choose heights
|
||||
int height = GeneratorUtils.nextIntBetween(random, this.minHeight, this.maxHeight);
|
||||
|
||||
int topHeight = Math.min(6, GeneratorUtils.nextIntBetween(random, height / 5, height / 3));
|
||||
int rootHeight = Math.min(5, GeneratorUtils.nextIntBetween(random, height / 4, height / 2));
|
||||
int middleHeight = height - topHeight - rootHeight;
|
||||
if (middleHeight < 1) {return false;}
|
||||
|
||||
// Start in the ground block
|
||||
BlockPos pos = startPos.down();
|
||||
|
||||
if (!this.checkSpace(world, pos, rootHeight, middleHeight, height))
|
||||
{
|
||||
// Abandon if there isn't enough room
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate roots
|
||||
this.generateRoots(world, random, pos, rootHeight);
|
||||
pos = pos.up(rootHeight);
|
||||
|
||||
// Generate middle of tree (trunk only)
|
||||
for(int i = 0; i < middleHeight; i++)
|
||||
{
|
||||
this.setLog(world, pos);
|
||||
pos = pos.up();
|
||||
}
|
||||
|
||||
// Generate the top of the tree
|
||||
this.generateTop(world, random, pos, topHeight);
|
||||
|
||||
// Add vines
|
||||
if (this.vine != null)
|
||||
{
|
||||
int maxLeavesRadius = this.minLeavesRadius + topHeight / this.leavesGradient;
|
||||
this.addVines(world, random, startPos, height, maxLeavesRadius, this.vineAttempts);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void addVines(World world, Random rand, BlockPos startPos, int height, int leavesRadius, int generationAttempts)
|
||||
{
|
||||
for (int i = 0; i < generationAttempts; i++)
|
||||
{
|
||||
// choose a random direction
|
||||
EnumFacing direction = EnumFacing.Plane.HORIZONTAL.random(rand);
|
||||
EnumFacing back = direction.getOpposite();
|
||||
EnumFacing sideways = direction.rotateY();
|
||||
|
||||
// choose a random starting point somewhere just outside the boundary of the tree
|
||||
BlockPos pos = startPos.up(GeneratorUtils.nextIntBetween(rand, 2, height)).offset(direction, leavesRadius + 1).offset(sideways, GeneratorUtils.nextIntBetween(rand, -leavesRadius, leavesRadius));
|
||||
|
||||
// move back towards the center until we meet a leaf or log, then stick a vine on it
|
||||
IBlockState state;
|
||||
for (int l = 0; l < leavesRadius; l++)
|
||||
{
|
||||
state = world.getBlockState(pos.offset(back, 1 + l));
|
||||
if (state == this.leaves || state == this.log) {
|
||||
this.setVine(world, rand, pos.offset(back, l), back, this.maxVineLength);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void configure(IConfigObj conf)
|
||||
{
|
||||
this.amountPerChunk = conf.getFloat("amountPerChunk", this.amountPerChunk);
|
||||
this.minHeight = conf.getInt("minHeight", this.minHeight);
|
||||
this.minLeavesRadius = conf.getInt("minLeavesRadius", this.minLeavesRadius);
|
||||
this.leavesGradient = conf.getInt("leavesGradient", this.leavesGradient);
|
||||
this.vineAttempts = conf.getInt("vineAttempts", this.vineAttempts);
|
||||
this.maxVineLength = conf.getInt("maxVineLength", this.maxVineLength);
|
||||
this.placeOn = conf.getBlockPosQuery("placeOn", this.placeOn);
|
||||
this.replace = conf.getBlockPosQuery("replace", this.replace);
|
||||
this.rootsReplace = conf.getBlockPosQuery("rootsReplace", this.rootsReplace);
|
||||
this.log = conf.getBlockState("logState", this.log);
|
||||
this.leaves = conf.getBlockState("leavesState", this.leaves);
|
||||
this.vine = conf.getBlockState("vinesState", this.vine);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue