diff --git a/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenTropicalRainforest.java b/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenTropicalRainforest.java index df0f12d95..8ae83eb4d 100644 --- a/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenTropicalRainforest.java +++ b/src/main/java/biomesoplenty/common/biome/overworld/BiomeGenTropicalRainforest.java @@ -35,6 +35,7 @@ import biomesoplenty.common.world.feature.GeneratorSplatter; import biomesoplenty.common.world.feature.GeneratorSplotches; import biomesoplenty.common.world.feature.GeneratorWaterside; import biomesoplenty.common.world.feature.tree.GeneratorBasicTree; +import biomesoplenty.common.world.feature.tree.GeneratorMahoganyTree; public class BiomeGenTropicalRainforest extends BOPBiome { @@ -67,7 +68,7 @@ public class BiomeGenTropicalRainforest extends BOPBiome // trees GeneratorWeighted treeGenerator = new GeneratorWeighted(15.0F); this.addGenerator("trees", GeneratorStage.TREE, treeGenerator); - treeGenerator.add("mahogany", 6, (new GeneratorBasicTree.Builder()).log(BOPWoods.MAHOGANY).leaves(BOPTrees.MAHOGANY).minLeavesRadius(2).minHeight(10).maxHeight(15).create()); + treeGenerator.add("mahogany", 6, (new GeneratorMahoganyTree.Builder()).create()); treeGenerator.add("jungle", 2, (new GeneratorBasicTree.Builder()).log(BlockPlanks.EnumType.JUNGLE).leaves(BlockPlanks.EnumType.JUNGLE).minHeight(8).maxHeight(12).vine(Blocks.vine.getDefaultState()).create()); // flowers diff --git a/src/main/java/biomesoplenty/common/init/ModGenerators.java b/src/main/java/biomesoplenty/common/init/ModGenerators.java index 31993db46..25299b134 100644 --- a/src/main/java/biomesoplenty/common/init/ModGenerators.java +++ b/src/main/java/biomesoplenty/common/init/ModGenerators.java @@ -46,5 +46,6 @@ public class ModGenerators registerGenerator("crystals", GeneratorCrystals.class, new GeneratorCrystals.Builder()); registerGenerator("spike", GeneratorSpike.class, new GeneratorSpike.Builder()); registerGenerator("redwood_tree", GeneratorRedwoodTree.class, new GeneratorRedwoodTree.Builder()); + registerGenerator("mahogany_tree", GeneratorMahoganyTree.class, new GeneratorMahoganyTree.Builder()); } } diff --git a/src/main/java/biomesoplenty/common/world/WorldChunkManagerBOP.java b/src/main/java/biomesoplenty/common/world/WorldChunkManagerBOP.java index a0cef0975..7c186b176 100644 --- a/src/main/java/biomesoplenty/common/world/WorldChunkManagerBOP.java +++ b/src/main/java/biomesoplenty/common/world/WorldChunkManagerBOP.java @@ -68,6 +68,8 @@ public class WorldChunkManagerBOP extends WorldChunkManager // loop through the biomes and apply the settings for (BiomeGenBase biome : BiomeGenBase.getBiomeGenArray()) { + if (biome == null) {continue;} + IExtendedBiome extBiome = BOPBiomes.REG_INSTANCE.getExtendedBiome(biome); if (extBiome == null) {continue;} diff --git a/src/main/java/biomesoplenty/common/world/feature/tree/GeneratorBasicTree.java b/src/main/java/biomesoplenty/common/world/feature/tree/GeneratorBasicTree.java index 7c4488d41..6da467485 100644 --- a/src/main/java/biomesoplenty/common/world/feature/tree/GeneratorBasicTree.java +++ b/src/main/java/biomesoplenty/common/world/feature/tree/GeneratorBasicTree.java @@ -33,25 +33,9 @@ import net.minecraft.world.World; public class GeneratorBasicTree extends GeneratorTreeBase { - // TODO: update neighbours in builder? - public static class Builder extends GeneratorTreeBase.InnerBuilder implements IGeneratorBuilder + public static class Builder extends GeneratorBasicTree.InnerBuilder implements IGeneratorBuilder { - protected int leafLayers; - protected int leavesOffset; - protected int minLeavesRadius; - protected IBlockPosQuery placeVinesOn; - - public Builder leafLayers(int a) {this.leafLayers = a; return this.self();} - public Builder leavesOffset(int a) {this.leavesOffset = a; return this.self();} - public Builder minLeavesRadius(int a) {this.minLeavesRadius = a; return this.self();} - - public Builder placeVinesOn(IBlockPosQuery a) {this.placeVinesOn = a; return this.self();} - public Builder placeVinesOn(String a) throws BlockQueryParseException {this.placeVinesOn = BlockQuery.parseQueryString(a); return this.self();} - public Builder placeVinesOn(Block a) {this.placeVinesOn = new BlockQueryBlock(a); return this.self();} - public Builder placeVinesOn(IBlockState a) {this.placeVinesOn = new BlockQueryState(a); return this.self();} - public Builder placeVinesOn(Material... a) {this.placeVinesOn = new BlockQueryMaterial(a); return this.self();} - public Builder() { // defaults @@ -66,29 +50,52 @@ public class GeneratorBasicTree extends GeneratorTreeBase this.leafLayers = 4; this.leavesOffset = 1; this.minLeavesRadius = 1; + this.leavesLayerHeight = 2; this.placeVinesOn = BlockQueries.air; } @Override public GeneratorBasicTree create() { - return new GeneratorBasicTree(this.amountPerChunk, this.placeOn, this.replace, this.log, this.leaves, this.vine, this.minHeight, this.maxHeight, false, this.leafLayers, this.leavesOffset, this.minLeavesRadius, this.placeVinesOn); + return new GeneratorBasicTree(this.amountPerChunk, this.placeOn, this.replace, this.log, this.leaves, this.vine, this.minHeight, this.maxHeight, false, this.leafLayers, this.leavesOffset, this.minLeavesRadius, this.leavesLayerHeight, this.placeVinesOn); } } - private boolean updateNeighbours; - private int leafLayers; - protected int leavesOffset; - private int minLeavesRadius; - private final IBlockPosQuery placeVinesOn; + protected static abstract class InnerBuilder, G extends GeneratorBasicTree> extends GeneratorTreeBase.InnerBuilder + { + protected int leafLayers; + protected int leavesOffset; + protected int minLeavesRadius; + protected int leavesLayerHeight; + protected IBlockPosQuery placeVinesOn; + + public T leafLayers(int a) {this.leafLayers = a; return this.self();} + public T leavesOffset(int a) {this.leavesOffset = a; return this.self();} + public T leavesLayerHeight(int a) {this.leavesLayerHeight = a; return this.self();} + public T minLeavesRadius(int a) {this.minLeavesRadius = a; return this.self();} + + public T placeVinesOn(IBlockPosQuery a) {this.placeVinesOn = a; return this.self();} + public T placeVinesOn(String a) throws BlockQueryParseException {this.placeVinesOn = BlockQuery.parseQueryString(a); return this.self();} + public T placeVinesOn(Block a) {this.placeVinesOn = new BlockQueryBlock(a); return this.self();} + public T placeVinesOn(IBlockState a) {this.placeVinesOn = new BlockQueryState(a); return this.self();} + public T placeVinesOn(Material... a) {this.placeVinesOn = new BlockQueryMaterial(a); return this.self();} + } - public GeneratorBasicTree(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState log, IBlockState leaves, IBlockState vine, int minHeight, int maxHeight, boolean updateNeighbours, int leafLayers, int leavesOffset, int minLeavesRadius, IBlockPosQuery placeVinesOn) + protected boolean updateNeighbours; + protected int leafLayers; + protected int leavesOffset; + protected int minLeavesRadius; + protected int leavesLayerHeight; + protected IBlockPosQuery placeVinesOn; + + public GeneratorBasicTree(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState log, IBlockState leaves, IBlockState vine, int minHeight, int maxHeight, boolean updateNeighbours, int leafLayers, int leavesOffset, int minLeavesRadius, int leavesLayerHeight, IBlockPosQuery placeVinesOn) { super(amountPerChunk, placeOn, replace, log, leaves, vine, minHeight, maxHeight); this.updateNeighbours = updateNeighbours; this.leavesOffset = leavesOffset; this.leafLayers = leafLayers; this.minLeavesRadius = minLeavesRadius; + this.leavesLayerHeight = leavesLayerHeight; this.placeVinesOn = placeVinesOn; } @@ -162,7 +169,7 @@ public class GeneratorBasicTree extends GeneratorTreeBase int currentLayer = y - (pos.getY() + height); //Uses integer division truncation (-3 / 2 = -1, -2 / 2 = -1) to reduce //the radius closer to the top of the tree. (2, 2, 1, 1) - int leavesRadius = this.minLeavesRadius - currentLayer / 2; + int leavesRadius = this.minLeavesRadius - currentLayer / this.leavesLayerHeight; for (int x = pos.getX() - leavesRadius; x <= pos.getX() + leavesRadius; x++) { @@ -186,37 +193,7 @@ public class GeneratorBasicTree extends GeneratorTreeBase } } - //Create the trunk from the bottom up, using < to ensure it is covered with one layer of leaves - for (int layer = 0; layer < height; ++layer) - { - BlockPos blockpos2 = pos.up(layer); - 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 && this.placeVinesOn.matches(world, pos.add(-1, layer, 0))) - { - this.setBlockAndNotifyAdequately(world, pos.add(-1, layer, 0), this.getVineStateForSide(EnumFacing.EAST)); - } - - if (random.nextInt(3) > 0 && this.placeVinesOn.matches(world, pos.add(1, layer, 0))) - { - this.setBlockAndNotifyAdequately(world, pos.add(1, layer, 0), this.getVineStateForSide(EnumFacing.WEST)); - } - if (random.nextInt(3) > 0 && this.placeVinesOn.matches(world, pos.add(0, layer, -1))) - { - this.setBlockAndNotifyAdequately(world, pos.add(0, layer, -1), this.getVineStateForSide(EnumFacing.SOUTH)); - } - if (random.nextInt(3) > 0 && this.placeVinesOn.matches(world, pos.add(0, layer, 1))) - { - this.setBlockAndNotifyAdequately(world, pos.add(0, layer, 1), this.getVineStateForSide(EnumFacing.NORTH)); - } - }*/ - } - } + this.generateTrunk(world, pos, height); if (this.vine != null) { @@ -226,7 +203,7 @@ public class GeneratorBasicTree extends GeneratorTreeBase int currentLayer = y - (pos.getY() + height); //Uses integer division truncation (-3 / 2 = -1, -2 / 2 = -1) to reduce //the radius closer to the top of the tree. (3, 3, 2, 2) - int leavesRadius = (this.minLeavesRadius + this.leavesOffset) - currentLayer / 2; + int leavesRadius = (this.minLeavesRadius + this.leavesOffset) - currentLayer / this.leavesLayerHeight; for (int x = pos.getX() - leavesRadius; x <= pos.getX() + leavesRadius; x++) { @@ -281,6 +258,41 @@ public class GeneratorBasicTree extends GeneratorTreeBase } } + protected void generateTrunk(World world, BlockPos start, int height) + { + //Create the trunk from the bottom up, using < to ensure it is covered with one layer of leaves + for (int layer = 0; layer < height; ++layer) + { + BlockPos blockpos2 = start.up(layer); + if (this.replace.matches(world, blockpos2)) + { + this.setBlockAndNotifyAdequately(world, start.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 && this.placeVinesOn.matches(world, pos.add(-1, layer, 0))) + { + this.setBlockAndNotifyAdequately(world, pos.add(-1, layer, 0), this.getVineStateForSide(EnumFacing.EAST)); + } + + if (random.nextInt(3) > 0 && this.placeVinesOn.matches(world, pos.add(1, layer, 0))) + { + this.setBlockAndNotifyAdequately(world, pos.add(1, layer, 0), this.getVineStateForSide(EnumFacing.WEST)); + } + if (random.nextInt(3) > 0 && this.placeVinesOn.matches(world, pos.add(0, layer, -1))) + { + this.setBlockAndNotifyAdequately(world, pos.add(0, layer, -1), this.getVineStateForSide(EnumFacing.SOUTH)); + } + if (random.nextInt(3) > 0 && this.placeVinesOn.matches(world, pos.add(0, layer, 1))) + { + this.setBlockAndNotifyAdequately(world, pos.add(0, layer, 1), this.getVineStateForSide(EnumFacing.NORTH)); + } + }*/ + } + } + } + private IBlockState getVineStateForSide(EnumFacing side) { return this.vine.getBlock() instanceof BlockVine ? this.vine.withProperty(BlockVine.getPropertyFor(side), Boolean.valueOf(true)) : this.vine; diff --git a/src/main/java/biomesoplenty/common/world/feature/tree/GeneratorMahoganyTree.java b/src/main/java/biomesoplenty/common/world/feature/tree/GeneratorMahoganyTree.java new file mode 100644 index 000000000..15b9dca57 --- /dev/null +++ b/src/main/java/biomesoplenty/common/world/feature/tree/GeneratorMahoganyTree.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright 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 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.block.BlockQuery.BlockQueryMaterial; +import biomesoplenty.common.util.block.BlockQuery.IBlockPosQuery; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumFacing.Axis; +import net.minecraft.world.World; + +public class GeneratorMahoganyTree extends GeneratorBasicTree +{ + public static class Builder extends GeneratorBasicTree.InnerBuilder implements IGeneratorBuilder + { + public Builder() + { + // defaults + this.amountPerChunk = 1.0F; + this.placeOn = BlockQueries.anything; + this.replace = new BlockQueryMaterial(Material.air, Material.leaves); + this.log = BlockBOPLog.paging.getVariantState(BOPWoods.MAHOGANY); + this.leaves = BlockBOPLeaves.paging.getVariantState(BOPTrees.MAHOGANY); + this.vine = null; + this.minHeight = 10; + this.maxHeight = 15; + this.leafLayers = 4; + this.leavesOffset = 1; + this.minLeavesRadius = 2; + this.leavesLayerHeight = 1; + this.placeVinesOn = BlockQueries.air; + } + + @Override + public GeneratorMahoganyTree create() + { + return new GeneratorMahoganyTree(this.amountPerChunk, this.placeOn, this.replace, this.log, this.leaves, this.vine, this.minHeight, this.maxHeight, false, this.leafLayers, this.leavesOffset, this.minLeavesRadius, this.leavesLayerHeight, this.placeVinesOn); + } + } + + public GeneratorMahoganyTree(float amountPerChunk, IBlockPosQuery placeOn, IBlockPosQuery replace, IBlockState log, IBlockState leaves, IBlockState vine, int minHeight, int maxHeight, boolean updateNeighbours, int leafLayers, int leavesOffset, int minLeavesRadius, int leavesLayerHeight, IBlockPosQuery placeVinesOn) + { + super(amountPerChunk, placeOn, replace, log, leaves, vine, minHeight, maxHeight, updateNeighbours, leafLayers, leavesOffset, minLeavesRadius, leavesLayerHeight, placeVinesOn); + } + + @Override + protected void generateTrunk(World world, BlockPos start, int height) + { + int endHeight = height - this.leafLayers; + + for (int layer = 0; layer <= height; ++layer) + { + BlockPos middlePos = start.up(layer); + + if (layer == endHeight - 2) + { + int branchHeight = height - endHeight - 1 + 2; + + //Generate the upper branches and stop + generateBranch(world, middlePos, EnumFacing.NORTH, branchHeight); + generateBranch(world, middlePos, EnumFacing.EAST, branchHeight); + generateBranch(world, middlePos, EnumFacing.SOUTH, branchHeight); + generateBranch(world, middlePos, EnumFacing.WEST, branchHeight); + break; + } + else if (this.replace.matches(world, middlePos)) + { + this.setLog(world, middlePos); + } + } + } + + private void generateBranch(World world, BlockPos middle, EnumFacing direction, int height) + { + BlockPos pos; + + if (replace.matches(world, pos = middle.offset(direction))) this.setLog(world, pos, direction.getAxis()); + + for (int i = 1; i <= height; ++i) + { + if (replace.matches(world, pos = middle.offset(direction, 2).up(i))) this.setLog(world, pos, Axis.Y); + } + } +}