Added the Lavender Fields, fixed the height of regular trees in some biomes
This commit is contained in:
parent
035e96676a
commit
21555fb6ee
|
@ -18,6 +18,7 @@ public class BOPBiomes
|
||||||
public static Optional<BiomeGenBase> arctic = Optional.absent();
|
public static Optional<BiomeGenBase> arctic = Optional.absent();
|
||||||
public static Optional<BiomeGenBase> crag = Optional.absent();
|
public static Optional<BiomeGenBase> crag = Optional.absent();
|
||||||
public static Optional<BiomeGenBase> flowerField = Optional.absent();
|
public static Optional<BiomeGenBase> flowerField = Optional.absent();
|
||||||
|
public static Optional<BiomeGenBase> lavenderFields = Optional.absent();
|
||||||
public static Optional<BiomeGenBase> originValley = Optional.absent();
|
public static Optional<BiomeGenBase> originValley = Optional.absent();
|
||||||
public static Optional<BiomeGenBase> shrubland = Optional.absent();
|
public static Optional<BiomeGenBase> shrubland = Optional.absent();
|
||||||
public static Optional<BiomeGenBase> steppe = Optional.absent();
|
public static Optional<BiomeGenBase> steppe = Optional.absent();
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright 2015, the Biomes O' Plenty Team
|
||||||
|
*
|
||||||
|
* This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License.
|
||||||
|
*
|
||||||
|
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
package biomesoplenty.common.biome.overworld;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockTallGrass;
|
||||||
|
import net.minecraft.init.Blocks;
|
||||||
|
import net.minecraft.util.BlockPos;
|
||||||
|
import net.minecraftforge.common.BiomeManager.BiomeType;
|
||||||
|
import biomesoplenty.api.biome.BOPBiome;
|
||||||
|
import biomesoplenty.api.biome.generation.GeneratorStage;
|
||||||
|
import biomesoplenty.api.biome.generation.GeneratorWeighted;
|
||||||
|
import biomesoplenty.api.block.BOPBlocks;
|
||||||
|
import biomesoplenty.api.block.BOPPlantEnums.AllPlants;
|
||||||
|
import biomesoplenty.api.block.BOPTreeEnums.AllTrees;
|
||||||
|
import biomesoplenty.api.block.BOPWoodEnums.AllWoods;
|
||||||
|
import biomesoplenty.common.block.BlockBOPFlower2;
|
||||||
|
import biomesoplenty.common.block.BlockBOPFlower2.FlowerType;
|
||||||
|
import biomesoplenty.common.block.BlockBOPLeaves;
|
||||||
|
import biomesoplenty.common.block.BlockBOPLeaves3;
|
||||||
|
import biomesoplenty.common.block.BlockBOPLeaves4;
|
||||||
|
import biomesoplenty.common.block.BlockBOPLog;
|
||||||
|
import biomesoplenty.common.block.BlockBOPLog3;
|
||||||
|
import biomesoplenty.common.block.BlockBOPPlant;
|
||||||
|
import biomesoplenty.common.block.BlockGem;
|
||||||
|
import biomesoplenty.common.block.BlockGem.GemType;
|
||||||
|
import biomesoplenty.common.world.feature.GeneratorFlora;
|
||||||
|
import biomesoplenty.common.world.feature.GeneratorGrass;
|
||||||
|
import biomesoplenty.common.world.feature.GeneratorOreSingle;
|
||||||
|
import biomesoplenty.common.world.feature.tree.GeneratorBasicTree;
|
||||||
|
import biomesoplenty.common.world.feature.tree.GeneratorBigTree;
|
||||||
|
|
||||||
|
public class BiomeGenLavenderFields extends BOPBiome
|
||||||
|
{
|
||||||
|
private static final Height biomeHeight = new Height(0.125F, 0.05F);
|
||||||
|
|
||||||
|
public BiomeGenLavenderFields()
|
||||||
|
{
|
||||||
|
this.setHeight(biomeHeight);
|
||||||
|
this.setColor(11035852);
|
||||||
|
this.setTemperatureRainfall(0.6F, 0.7F);
|
||||||
|
|
||||||
|
this.addWeight(BiomeType.WARM, 3);
|
||||||
|
|
||||||
|
this.addGenerator("lavender", GeneratorStage.FLOWERS, new GeneratorFlora(999, BOPBlocks.flower2.getDefaultState().withProperty(BlockBOPFlower2.VARIANT, FlowerType.LAVENDER)));
|
||||||
|
|
||||||
|
GeneratorWeighted treeGenerator = new GeneratorWeighted(1);
|
||||||
|
treeGenerator.add(3, new GeneratorBasicTree(1, false, 4, 7, BOPBlocks.log_3.getDefaultState().withProperty(BlockBOPLog.getVariantProperty(BlockBOPLog3.PAGENUM), AllWoods.JACARANDA), BOPBlocks.leaves_3.getDefaultState().withProperty(BlockBOPLeaves.getVariantProperty(BlockBOPLeaves3.PAGENUM), AllTrees.JACARANDA)));
|
||||||
|
treeGenerator.add(1, new GeneratorBigTree(1, false, Blocks.log.getDefaultState(), Blocks.leaves.getDefaultState()));
|
||||||
|
this.addGenerator("trees", GeneratorStage.TREE, treeGenerator);
|
||||||
|
|
||||||
|
GeneratorWeighted grassGenerator = new GeneratorWeighted(20);
|
||||||
|
grassGenerator.add(1, new GeneratorGrass(1, BlockBOPPlant.getVariantState(AllPlants.WHEATGRASS)));
|
||||||
|
grassGenerator.add(3, new GeneratorGrass(1, Blocks.tallgrass.getDefaultState().withProperty(BlockTallGrass.TYPE, BlockTallGrass.EnumType.GRASS)));
|
||||||
|
this.addGenerator("grass", GeneratorStage.GRASS, grassGenerator);
|
||||||
|
|
||||||
|
this.addGenerator("peridot", GeneratorStage.SAND, new GeneratorOreSingle(BOPBlocks.gem_ore.getDefaultState().withProperty(BlockGem.VARIANT, GemType.PERIDOT), 12, 4, 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getGrassColorAtPos(BlockPos pos)
|
||||||
|
{
|
||||||
|
return 10601325;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getFoliageColorAtPos(BlockPos pos)
|
||||||
|
{
|
||||||
|
return 10601325;
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,7 +38,7 @@ public class BiomeGenThicket extends BOPBiome
|
||||||
this.addWeight(BiomeType.COOL, 5);
|
this.addWeight(BiomeType.COOL, 5);
|
||||||
|
|
||||||
GeneratorWeighted treeGenerator = new GeneratorWeighted(17);
|
GeneratorWeighted treeGenerator = new GeneratorWeighted(17);
|
||||||
treeGenerator.add(1, new GeneratorBasicTree(1, false, 4, 3, Blocks.log.getDefaultState(), Blocks.leaves.getDefaultState()));
|
treeGenerator.add(1, new GeneratorBasicTree(1, false, 4, 7, Blocks.log.getDefaultState(), Blocks.leaves.getDefaultState()));
|
||||||
treeGenerator.add(4, new GeneratorBush(1, Blocks.log.getDefaultState(), Blocks.leaves.getDefaultState()));
|
treeGenerator.add(4, new GeneratorBush(1, Blocks.log.getDefaultState(), Blocks.leaves.getDefaultState()));
|
||||||
this.addGenerator("trees", GeneratorStage.TREE, treeGenerator);
|
this.addGenerator("trees", GeneratorStage.TREE, treeGenerator);
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import biomesoplenty.common.biome.overworld.BiomeGenAlps;
|
||||||
import biomesoplenty.common.biome.overworld.BiomeGenArctic;
|
import biomesoplenty.common.biome.overworld.BiomeGenArctic;
|
||||||
import biomesoplenty.common.biome.overworld.BiomeGenCrag;
|
import biomesoplenty.common.biome.overworld.BiomeGenCrag;
|
||||||
import biomesoplenty.common.biome.overworld.BiomeGenFlowerField;
|
import biomesoplenty.common.biome.overworld.BiomeGenFlowerField;
|
||||||
|
import biomesoplenty.common.biome.overworld.BiomeGenLavenderFields;
|
||||||
import biomesoplenty.common.biome.overworld.BiomeGenOriginValley;
|
import biomesoplenty.common.biome.overworld.BiomeGenOriginValley;
|
||||||
import biomesoplenty.common.biome.overworld.BiomeGenShrubland;
|
import biomesoplenty.common.biome.overworld.BiomeGenShrubland;
|
||||||
import biomesoplenty.common.biome.overworld.BiomeGenSteppe;
|
import biomesoplenty.common.biome.overworld.BiomeGenSteppe;
|
||||||
|
@ -53,6 +54,7 @@ public class ModBiomes
|
||||||
arctic = registerBiome(new BiomeGenArctic().setBiomeName("Arctic"), "arctic");
|
arctic = registerBiome(new BiomeGenArctic().setBiomeName("Arctic"), "arctic");
|
||||||
crag = registerBiome(new BiomeGenCrag().setBiomeName("Crag"), "crag");
|
crag = registerBiome(new BiomeGenCrag().setBiomeName("Crag"), "crag");
|
||||||
flowerField = registerBiome(new BiomeGenFlowerField().setBiomeName("Flower Field"), "flower_field");
|
flowerField = registerBiome(new BiomeGenFlowerField().setBiomeName("Flower Field"), "flower_field");
|
||||||
|
lavenderFields = registerBiome(new BiomeGenLavenderFields().setBiomeName("Lavender Fields"), "lavender_fields");
|
||||||
originValley = registerBiome(new BiomeGenOriginValley().setBiomeName("Origin Valley"), "origin_valley");
|
originValley = registerBiome(new BiomeGenOriginValley().setBiomeName("Origin Valley"), "origin_valley");
|
||||||
shrubland = registerBiome(new BiomeGenShrubland().setBiomeName("Shrubland"), "shrubland");
|
shrubland = registerBiome(new BiomeGenShrubland().setBiomeName("Shrubland"), "shrubland");
|
||||||
steppe = registerBiome(new BiomeGenSteppe().setBiomeName("Steppe"), "steppe");
|
steppe = registerBiome(new BiomeGenSteppe().setBiomeName("Steppe"), "steppe");
|
||||||
|
|
|
@ -18,6 +18,7 @@ import biomesoplenty.common.world.feature.GeneratorOreCluster;
|
||||||
import biomesoplenty.common.world.feature.GeneratorOreSingle;
|
import biomesoplenty.common.world.feature.GeneratorOreSingle;
|
||||||
import biomesoplenty.common.world.feature.GeneratorWaterside;
|
import biomesoplenty.common.world.feature.GeneratorWaterside;
|
||||||
import biomesoplenty.common.world.feature.tree.GeneratorBasicTree;
|
import biomesoplenty.common.world.feature.tree.GeneratorBasicTree;
|
||||||
|
import biomesoplenty.common.world.feature.tree.GeneratorBigTree;
|
||||||
import biomesoplenty.common.world.feature.tree.GeneratorBush;
|
import biomesoplenty.common.world.feature.tree.GeneratorBush;
|
||||||
|
|
||||||
public class ModGenerators
|
public class ModGenerators
|
||||||
|
@ -29,6 +30,7 @@ public class ModGenerators
|
||||||
registerGenerator("weighted", GeneratorWeighted.class);
|
registerGenerator("weighted", GeneratorWeighted.class);
|
||||||
registerGenerator("weighted_entry", GeneratorWeightedEntry.class);
|
registerGenerator("weighted_entry", GeneratorWeightedEntry.class);
|
||||||
registerGenerator("basic_tree", GeneratorBasicTree.class);
|
registerGenerator("basic_tree", GeneratorBasicTree.class);
|
||||||
|
registerGenerator("big_tree", GeneratorBigTree.class);
|
||||||
registerGenerator("bush", GeneratorBush.class);
|
registerGenerator("bush", GeneratorBush.class);
|
||||||
registerGenerator("flora", GeneratorFlora.class);
|
registerGenerator("flora", GeneratorFlora.class);
|
||||||
registerGenerator("double_flora", GeneratorDoubleFlora.class);
|
registerGenerator("double_flora", GeneratorDoubleFlora.class);
|
||||||
|
|
|
@ -34,19 +34,6 @@ public class GeneratorUtils
|
||||||
minHeight = maxHeight;
|
minHeight = maxHeight;
|
||||||
maxHeight = prevMinHeight;
|
maxHeight = prevMinHeight;
|
||||||
}
|
}
|
||||||
else if (maxHeight == minHeight)
|
|
||||||
{
|
|
||||||
if (minHeight < 255)
|
|
||||||
{
|
|
||||||
//Increase max height to be higher than min height
|
|
||||||
++maxHeight;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Decrease min height so that max is higher
|
|
||||||
--minHeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Pair.of(minHeight, maxHeight);
|
return Pair.of(minHeight, maxHeight);
|
||||||
}
|
}
|
||||||
|
|
|
@ -317,6 +317,8 @@ public class GeneratorBasicTree extends GeneratorCustomizable
|
||||||
{
|
{
|
||||||
this.amountPerChunk = json.get("amount_per_chunk").getAsInt();
|
this.amountPerChunk = json.get("amount_per_chunk").getAsInt();
|
||||||
this.updateNeighbours = json.get("update_neighbours").getAsBoolean();
|
this.updateNeighbours = json.get("update_neighbours").getAsBoolean();
|
||||||
|
int minHeight = json.get("min_height").getAsInt();
|
||||||
|
int maxHeight = json.get("max_height").getAsInt();
|
||||||
|
|
||||||
Pair<Integer, Integer> heights = GeneratorUtils.validateMinMaxHeight(minHeight, maxHeight);
|
Pair<Integer, Integer> heights = GeneratorUtils.validateMinMaxHeight(minHeight, maxHeight);
|
||||||
this.minHeight = heights.getLeft();
|
this.minHeight = heights.getLeft();
|
||||||
|
@ -325,5 +327,7 @@ public class GeneratorBasicTree extends GeneratorCustomizable
|
||||||
this.log = context.deserialize(json.get("log_state"), IBlockState.class);
|
this.log = context.deserialize(json.get("log_state"), IBlockState.class);
|
||||||
this.leaves = context.deserialize(json.get("leaves_state"), IBlockState.class);
|
this.leaves = context.deserialize(json.get("leaves_state"), IBlockState.class);
|
||||||
this.vine = context.deserialize(json.get("vine_state"), IBlockState.class);
|
this.vine = context.deserialize(json.get("vine_state"), IBlockState.class);
|
||||||
|
|
||||||
|
System.out.println(amountPerChunk + " " + updateNeighbours + " " + minHeight + " " + maxHeight + " " + log + " " + leaves);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,561 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockLog;
|
||||||
|
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.util.MathHelper;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.gen.feature.WorldGenBigTree;
|
||||||
|
import biomesoplenty.api.biome.generation.GeneratorCustomizable;
|
||||||
|
import biomesoplenty.common.util.biome.GeneratorUtils;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.gson.JsonDeserializationContext;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonSerializationContext;
|
||||||
|
|
||||||
|
/*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 GeneratorCustomizable
|
||||||
|
{
|
||||||
|
private Random random;
|
||||||
|
private World world;
|
||||||
|
private BlockPos origin;
|
||||||
|
|
||||||
|
private int height;
|
||||||
|
private int trunkHeight;
|
||||||
|
private double trunkHeightScale = 0.618;
|
||||||
|
private double branchSlope = 0.381;
|
||||||
|
private double widthScale = 1;
|
||||||
|
private double foliageDensity = 1;
|
||||||
|
private int trunkWidth = 1;
|
||||||
|
//private int heightVariance = 12;
|
||||||
|
private int foliageHeight = 4;
|
||||||
|
|
||||||
|
//Configurable fields
|
||||||
|
private int amountPerChunk;
|
||||||
|
private boolean updateNeighbours;
|
||||||
|
private int minHeight;
|
||||||
|
private int maxHeight;
|
||||||
|
private IBlockState log;
|
||||||
|
private IBlockState leaves;
|
||||||
|
|
||||||
|
private List<FoliageCoords> foliageCoords;
|
||||||
|
|
||||||
|
public GeneratorBigTree() {}
|
||||||
|
|
||||||
|
public GeneratorBigTree(int amountPerChunk, boolean updateNeighbours, int minHeight, int maxHeight, IBlockState log, IBlockState leaves)
|
||||||
|
{
|
||||||
|
this.amountPerChunk = amountPerChunk;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GeneratorBigTree(int amountPerChunk, boolean updateNeighbours, IBlockState log, IBlockState leaves)
|
||||||
|
{
|
||||||
|
this(amountPerChunk, updateNeighbours, 5, 17, log, leaves);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void prepare()
|
||||||
|
{
|
||||||
|
// Populate the list of foliage cluster locations.
|
||||||
|
// Designed to be overridden in child classes to change basic
|
||||||
|
// tree properties (trunk width, branch angle, foliage density, etc..).
|
||||||
|
|
||||||
|
trunkHeight = (int) (height * trunkHeightScale);
|
||||||
|
|
||||||
|
if (trunkHeight >= height)
|
||||||
|
{
|
||||||
|
trunkHeight = height - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define foliage clusters per y
|
||||||
|
int clustersPerY = (int) (1.382 + Math.pow(foliageDensity * height / 13.0, 2));
|
||||||
|
if (clustersPerY < 1) {
|
||||||
|
clustersPerY = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int trunkTop = origin.getY() + trunkHeight;
|
||||||
|
int relativeY = height - foliageHeight;
|
||||||
|
|
||||||
|
foliageCoords = Lists.newArrayList();
|
||||||
|
foliageCoords.add(new FoliageCoords(origin.up(relativeY), trunkTop));
|
||||||
|
|
||||||
|
for (; relativeY >= 0; relativeY--)
|
||||||
|
{
|
||||||
|
float treeShape = treeShape(relativeY);
|
||||||
|
|
||||||
|
if (treeShape < 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < clustersPerY; i++)
|
||||||
|
{
|
||||||
|
final double radius = widthScale * treeShape * (random.nextFloat() + 0.328);
|
||||||
|
final double angle = random.nextFloat() * 2 * Math.PI;
|
||||||
|
|
||||||
|
final double x = radius * Math.sin(angle) + 0.5;
|
||||||
|
final double z = radius * Math.cos(angle) + 0.5;
|
||||||
|
|
||||||
|
final BlockPos checkStart = origin.add(x, relativeY - 1, z);
|
||||||
|
final BlockPos checkEnd = checkStart.up(foliageHeight);
|
||||||
|
|
||||||
|
// check the center column of the cluster for obstructions.
|
||||||
|
if (checkLine(checkStart, checkEnd) == -1)
|
||||||
|
{
|
||||||
|
// If the cluster can be created, check the branch path for obstructions.
|
||||||
|
final int dx = origin.getX() - checkStart.getX();
|
||||||
|
final int dz = origin.getZ() - checkStart.getZ();
|
||||||
|
|
||||||
|
final double height = checkStart.getY() - Math.sqrt(dx * dx + dz * dz) * branchSlope;
|
||||||
|
final int branchTop = height > trunkTop ? trunkTop : (int) height;
|
||||||
|
final BlockPos checkBranchBase = new BlockPos(origin.getX(), branchTop, origin.getZ());
|
||||||
|
|
||||||
|
// Now check the branch path
|
||||||
|
if (checkLine(checkBranchBase, checkStart) == -1)
|
||||||
|
{
|
||||||
|
// If the branch path is clear, add the position to the list of foliage positions
|
||||||
|
foliageCoords.add(new FoliageCoords(checkStart, checkBranchBase.getY()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void crossection(BlockPos pos, float radius, IBlockState state)
|
||||||
|
{
|
||||||
|
// Create a circular cross section.
|
||||||
|
//
|
||||||
|
// Used to nearly everything in the foliage, branches, and trunk.
|
||||||
|
// This is a good target for performance optimization.
|
||||||
|
|
||||||
|
// Passed values:
|
||||||
|
// pos is the center location of the cross section
|
||||||
|
// radius is the radius of the section from the center
|
||||||
|
// direction is the direction the cross section is pointed, 0 for x, 1
|
||||||
|
// for y, 2 for z material is the index number for the material to use
|
||||||
|
|
||||||
|
final int r = (int) (radius + 0.618);
|
||||||
|
|
||||||
|
for (int dx = -r; dx <= r; dx++)
|
||||||
|
{
|
||||||
|
for (int dz = -r; dz <= r; dz++)
|
||||||
|
{
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
this.setBlockAndNotifyAdequately(world, checkedPos, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected float treeShape(int y)
|
||||||
|
{
|
||||||
|
// Take the y position relative to the base of the tree.
|
||||||
|
// Return the distance the foliage should be from the trunk axis.
|
||||||
|
// Return a negative number if foliage should not be created at this
|
||||||
|
// height. This method is intended for overriding in child classes,
|
||||||
|
// allowing different shaped trees. This method should return a
|
||||||
|
// consistent value for each y (don't randomize).
|
||||||
|
|
||||||
|
if (y < height * 0.3f) {
|
||||||
|
return -1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
final float radius = height / 2.0f;
|
||||||
|
final float adjacent = radius - y;
|
||||||
|
|
||||||
|
float distance = MathHelper.sqrt_float(radius * radius - adjacent * adjacent);
|
||||||
|
|
||||||
|
if (adjacent == 0) {
|
||||||
|
distance = radius;
|
||||||
|
} else if (Math.abs(adjacent) >= radius) {
|
||||||
|
return 0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alter this factor to change the overall width of the tree.
|
||||||
|
return distance * 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected float foliageShape(int y)
|
||||||
|
{
|
||||||
|
// Take the y position relative to the base of the foliage cluster.
|
||||||
|
// Return the radius of the cluster at this y
|
||||||
|
// Return a negative number if no foliage should be created at this
|
||||||
|
// level. This method is intended for overriding in child classes,
|
||||||
|
// allowing foliage of different sizes and shapes.
|
||||||
|
|
||||||
|
if (y < 0 || y >= foliageHeight)
|
||||||
|
{
|
||||||
|
return -1f;
|
||||||
|
}
|
||||||
|
//The following has been replaced as recommended by
|
||||||
|
//http://www.reddit.com/r/Minecraft/comments/1m97cw/while_you_are_all_crying_over_the_name_change_of/ccfgc3k
|
||||||
|
//The change should fix the decaying leaves
|
||||||
|
/*else if (y == 0 || y == foliageHeight - 1)
|
||||||
|
{
|
||||||
|
return 2f;
|
||||||
|
}*/
|
||||||
|
else if (y == 0 || y == foliageHeight - 2)
|
||||||
|
{
|
||||||
|
return 2f;
|
||||||
|
}
|
||||||
|
else if (y == foliageHeight - 1)
|
||||||
|
{
|
||||||
|
return 1.5f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 3f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void foliageCluster(BlockPos blockPos)
|
||||||
|
{
|
||||||
|
// Generate a cluster of foliage, with the base at blockPos
|
||||||
|
// The shape of the cluster is derived from foliageShape
|
||||||
|
// crossection is called to make each level.
|
||||||
|
|
||||||
|
for (int y = 0; y < foliageHeight; y++)
|
||||||
|
{
|
||||||
|
crossection(blockPos.up(y), foliageShape(y), this.leaves);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void limb(BlockPos startPos, BlockPos endPos, IBlockState state)
|
||||||
|
{
|
||||||
|
// Create a limb from the start position to the end position.
|
||||||
|
// Used for creating the branches and trunk.
|
||||||
|
// Similar to checkLine, however it is setting rather than checking
|
||||||
|
|
||||||
|
//The distance between the two points, may be negative if the second pos is smaller
|
||||||
|
BlockPos delta = endPos.add(-startPos.getX(), -startPos.getY(), -startPos.getZ());
|
||||||
|
|
||||||
|
int steps = getSteps(delta);
|
||||||
|
|
||||||
|
//How much should be incremented with each iteration relative
|
||||||
|
//to the greatest distance which will have a value of 1.0F.
|
||||||
|
float dx = delta.getX() / (float) steps;
|
||||||
|
float dy = delta.getY() / (float) steps;
|
||||||
|
float dz = delta.getZ() / (float) steps;
|
||||||
|
|
||||||
|
//Iterates over all values between the start pos and end pos
|
||||||
|
for (int i = 0; i <= steps; i++)
|
||||||
|
{
|
||||||
|
//A delta position between the start pos and end pos. Increments are added to the x, y and z coords
|
||||||
|
//so that they meet their corresponding values in the end pos when j reaches the greatest distance. 0.5F
|
||||||
|
//is added to ensure the final point is reached.
|
||||||
|
BlockPos blockPos = startPos.add(.5f + i * dx, .5f + i * dy, .5f + i * dz);
|
||||||
|
BlockLog.EnumAxis logAxis = getLogAxis(startPos, blockPos);
|
||||||
|
|
||||||
|
this.setBlockAndNotifyAdequately(world, blockPos, state.withProperty(BlockLog.LOG_AXIS, logAxis));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getSteps(BlockPos pos)
|
||||||
|
{
|
||||||
|
final int absX = MathHelper.abs_int(pos.getX());
|
||||||
|
final int absY = MathHelper.abs_int(pos.getY());
|
||||||
|
final int absZ = MathHelper.abs_int(pos.getZ());
|
||||||
|
|
||||||
|
//Determine which axis has the greatest distance from the origin (0, 0, 0)
|
||||||
|
if (absZ > absX && absZ > absY) {
|
||||||
|
return absZ;
|
||||||
|
} else if (absY > absX) {
|
||||||
|
return absY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return absX;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getGreatestDistance(BlockPos posIn)
|
||||||
|
{
|
||||||
|
int i = MathHelper.abs_int(posIn.getX());
|
||||||
|
int j = MathHelper.abs_int(posIn.getY());
|
||||||
|
int k = MathHelper.abs_int(posIn.getZ());
|
||||||
|
return k > i && k > j ? k : (j > i ? j : i);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockLog.EnumAxis getLogAxis(BlockPos startPos, BlockPos endPos)
|
||||||
|
{
|
||||||
|
BlockLog.EnumAxis axis = BlockLog.EnumAxis.Y;
|
||||||
|
|
||||||
|
//Find the difference between the start and end pos
|
||||||
|
int xDiff = Math.abs(endPos.getX() - startPos.getX());
|
||||||
|
int zDiff = Math.abs(endPos.getZ() - startPos.getZ());
|
||||||
|
int maxDiff = Math.max(xDiff, zDiff);
|
||||||
|
|
||||||
|
//Check if the distance between the two positions is greater than 0 on either
|
||||||
|
//the x or the z axis. axis is set to the axis with the greatest distance
|
||||||
|
if (maxDiff > 0)
|
||||||
|
{
|
||||||
|
if (xDiff == maxDiff)
|
||||||
|
{
|
||||||
|
axis = BlockLog.EnumAxis.X;
|
||||||
|
}
|
||||||
|
else if (zDiff == maxDiff)
|
||||||
|
{
|
||||||
|
axis = BlockLog.EnumAxis.Z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return axis;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeFoliage()
|
||||||
|
{
|
||||||
|
// Create the tree foliage.
|
||||||
|
// Call foliageCluster at the correct locations
|
||||||
|
|
||||||
|
for (FoliageCoords foliageCoord : foliageCoords)
|
||||||
|
{
|
||||||
|
foliageCluster(foliageCoord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean trimBranches(int localY)
|
||||||
|
{
|
||||||
|
// For larger trees, randomly "prune" the branches so there
|
||||||
|
// aren't too many.
|
||||||
|
// Return true if the branch should be created.
|
||||||
|
// This method is intended for overriding in child classes, allowing
|
||||||
|
// decent amounts of branches on very large trees.
|
||||||
|
// Can also be used to disable branches on some tree types, or
|
||||||
|
// make branches more sparse.
|
||||||
|
return localY >= height * 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeTrunk()
|
||||||
|
{
|
||||||
|
// Create the trunk of the tree.
|
||||||
|
BlockPos start = origin;
|
||||||
|
BlockPos end = origin.up(trunkHeight);
|
||||||
|
IBlockState materialState = this.log;
|
||||||
|
|
||||||
|
limb(start, end, materialState);
|
||||||
|
|
||||||
|
if (trunkWidth == 2)
|
||||||
|
{
|
||||||
|
limb(start.east(), end.east(), materialState);
|
||||||
|
limb(start.east().south(), end.east().south(), materialState);
|
||||||
|
limb(start.south(), end.south(), materialState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeBranches()
|
||||||
|
{
|
||||||
|
for (FoliageCoords endCoord : foliageCoords)
|
||||||
|
{
|
||||||
|
int branchBase = endCoord.getBranchBase();
|
||||||
|
BlockPos baseCoord = new BlockPos(this.origin.getX(), branchBase, this.origin.getZ());
|
||||||
|
|
||||||
|
if (this.trimBranches(branchBase - this.origin.getY()))
|
||||||
|
{
|
||||||
|
this.limb(baseCoord, endCoord, this.log);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int checkLine(BlockPos startPos, BlockPos endPos)
|
||||||
|
{
|
||||||
|
// Check from coordinates start to end (both inclusive) for blocks
|
||||||
|
// other than air and foliage If a block other than air and foliage is
|
||||||
|
// found, return the number of steps taken.
|
||||||
|
// If no block other than air and foliage is found, return -1.
|
||||||
|
// Examples:
|
||||||
|
// If the third block searched is stone, return 2
|
||||||
|
// If the first block searched is lava, return 0
|
||||||
|
|
||||||
|
//The distance between the two points, may be negative if the second pos is smaller
|
||||||
|
BlockPos delta = endPos.add(-startPos.getX(), -startPos.getY(), -startPos.getZ());
|
||||||
|
|
||||||
|
int steps = this.getGreatestDistance(delta);
|
||||||
|
|
||||||
|
//How much should be incremented with each iteration relative
|
||||||
|
//to the greatest distance which will have a value of 1.0F.
|
||||||
|
float dx = (float)delta.getX() / (float)steps;
|
||||||
|
float dy = (float)delta.getY() / (float)steps;
|
||||||
|
float dz = (float)delta.getZ() / (float)steps;
|
||||||
|
|
||||||
|
//Check if both positions are the same
|
||||||
|
if (steps == 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Iterates over all values between the start pos and end pos
|
||||||
|
for (int i = 0; i <= steps; i++)
|
||||||
|
{
|
||||||
|
//A delta position between the start pos and end pos. Increments are added to the x, y and z coords
|
||||||
|
//so that they meet their corresponding values in the end pos when j reaches the greatest distance. 0.5F
|
||||||
|
//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))
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//The line is unobstructed
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void scatter(World world, Random random, BlockPos pos)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < amountPerChunk; i++)
|
||||||
|
{
|
||||||
|
int x = random.nextInt(16) + 8;
|
||||||
|
int z = random.nextInt(16) + 8;
|
||||||
|
BlockPos genPos = world.getHeight(pos.add(x, 0, z));
|
||||||
|
|
||||||
|
generate(world, random, genPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean generate(World world, Random rand, BlockPos pos)
|
||||||
|
{
|
||||||
|
this.world = world;
|
||||||
|
this.origin = pos;
|
||||||
|
|
||||||
|
this.random = new Random(rand.nextLong());
|
||||||
|
|
||||||
|
if (this.height == 0)
|
||||||
|
{
|
||||||
|
this.height = random.nextInt(this.maxHeight - this.minHeight) + this.minHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.checkLocation())
|
||||||
|
{
|
||||||
|
this.world = null; //Fix vanilla Mem leak, holds latest world
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare();
|
||||||
|
makeFoliage();
|
||||||
|
makeTrunk();
|
||||||
|
makeBranches();
|
||||||
|
this.world = null; //Fix vanilla Mem leak, holds latest world
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean checkLocation()
|
||||||
|
{
|
||||||
|
BlockPos down = this.origin.down();
|
||||||
|
IBlockState state = this.world.getBlockState(down);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Examine center column for how tall the tree can be.
|
||||||
|
int allowedHeight = checkLine(this.origin, this.origin.up(height - 1));
|
||||||
|
|
||||||
|
// If the set height is good, go with that
|
||||||
|
if (allowedHeight == -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the space is too short, tell the build to abort
|
||||||
|
if (allowedHeight < 6) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
height = allowedHeight;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBlockAndNotifyAdequately(World world, BlockPos pos, IBlockState state)
|
||||||
|
{
|
||||||
|
if (this.updateNeighbours)
|
||||||
|
{
|
||||||
|
world.setBlockState(pos, state, 3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
world.setBlockState(pos, state, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class FoliageCoords extends BlockPos
|
||||||
|
{
|
||||||
|
private final int branchBase;
|
||||||
|
|
||||||
|
public FoliageCoords(BlockPos pos, int branchBase)
|
||||||
|
{
|
||||||
|
super(pos.getX(), pos.getY(), pos.getZ());
|
||||||
|
this.branchBase = branchBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBranchBase()
|
||||||
|
{
|
||||||
|
return branchBase;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToJson(JsonObject json, JsonSerializationContext context)
|
||||||
|
{
|
||||||
|
json.addProperty("amount_per_chunk", this.amountPerChunk);
|
||||||
|
json.addProperty("update_neighbours", this.updateNeighbours);
|
||||||
|
json.addProperty("min_height", this.minHeight);
|
||||||
|
json.addProperty("max_height", this.maxHeight);
|
||||||
|
json.add("log_state", context.serialize(this.log));
|
||||||
|
json.add("leaves_state", context.serialize(this.leaves));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readFromJson(JsonObject json, JsonDeserializationContext context)
|
||||||
|
{
|
||||||
|
this.amountPerChunk = json.get("amount_per_chunk").getAsInt();
|
||||||
|
this.updateNeighbours = json.get("update_neighbours").getAsBoolean();
|
||||||
|
int minHeight = json.get("min_height").getAsInt();
|
||||||
|
int maxHeight = json.get("max_height").getAsInt();
|
||||||
|
|
||||||
|
Pair<Integer, Integer> heights = GeneratorUtils.validateMinMaxHeight(minHeight, maxHeight);
|
||||||
|
this.minHeight = heights.getLeft();
|
||||||
|
this.maxHeight = heights.getRight();
|
||||||
|
|
||||||
|
this.log = context.deserialize(json.get("log_state"), IBlockState.class);
|
||||||
|
this.leaves = context.deserialize(json.get("leaves_state"), IBlockState.class);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue