use of com.ferreusveritas.dynamictrees.blocks.BlockBranch in project DynamicTrees by DynamicTreesTeam.
the class NodeInflator method returnRun.
@Override
public boolean returnRun(IBlockState blockState, World world, BlockPos pos, EnumFacing fromDir) {
// Calculate Branch Thickness based on neighboring branches
BlockBranch branch = TreeHelper.getBranch(blockState);
if (branch != null) {
// Start by accumulating the branch we just came from
float areaAccum = radius * radius;
boolean isTwig = true;
for (EnumFacing dir : EnumFacing.VALUES) {
if (!dir.equals(fromDir)) {
// Don't count where the signal originated from
BlockPos dPos = pos.offset(dir);
if (dPos.equals(last)) {
// or the branch we just came back from
// on the return journey if the block we just came from is a branch we are obviously not the endpoint(twig)
isTwig = false;
continue;
}
IBlockState deltaBlockState = world.getBlockState(dPos);
ITreePart treepart = TreeHelper.getTreePart(deltaBlockState);
if (branch.isSameTree(treepart)) {
int branchRadius = treepart.getRadius(deltaBlockState);
areaAccum += branchRadius * branchRadius;
}
}
}
if (isTwig) {
// Handle leaves here
if (leafMap != null) {
// 16(bit 5) is code for a twig
leafMap.setVoxel(pos, (byte) 16);
SimpleVoxmap leafCluster = species.getLeavesProperties().getCellKit().getLeafCluster();
leafMap.blitMax(pos, leafCluster);
}
} else {
// The new branch should be the square root of all of the sums of the areas of the branches coming into it.
radius = (float) Math.sqrt(areaAccum) + (species.getTapering() * species.getWorldGenTaperingFactor());
// Ensure the branch is never inflated past it's species maximum
int maxRadius = species.maxBranchRadius();
if (radius > maxRadius) {
radius = maxRadius;
}
// Ensure non-twig branches are at least radius 2
float secondaryThickness = species.getFamily().getSecondaryThickness();
if (radius < secondaryThickness) {
radius = secondaryThickness;
}
branch.setRadius(world, pos, (int) Math.floor(radius), null);
if (leafMap != null) {
// 32(bit 6) is code for a branch
leafMap.setVoxel(pos, (byte) 32);
}
}
last = pos;
}
return false;
}
use of com.ferreusveritas.dynamictrees.blocks.BlockBranch in project DynamicTrees by DynamicTreesTeam.
the class JoCode method generate.
/**
* Generate a tree from a JoCode instruction list.
*
* @param world The world
* @param seed The seed used to create the tree
* @param rootPos The position of what will become the rootydirt block
* @param biome The biome of the coordinates.
* @param facing Direction of tree
* @param radius Constraint radius
*/
public void generate(World world, Species species, BlockPos rootPosIn, Biome biome, EnumFacing facing, int radius, SafeChunkBounds safeBounds) {
boolean worldGen = safeBounds != SafeChunkBounds.ANY;
// A Tree generation boundary radius is at least 2 and at most 8
radius = MathHelper.clamp(radius, 2, 8);
setFacing(facing);
BlockPos rootPos = species.preGeneration(world, rootPosIn, radius, facing, safeBounds, this);
if (rootPos != BlockPos.ORIGIN) {
// Save the initial state of the dirt in case this fails
IBlockState initialDirtState = world.getBlockState(rootPos);
// Set to unfertilized rooty dirt
species.placeRootyDirtBlock(world, rootPos, 0);
// Make the tree branch structure
generateFork(world, species, 0, rootPos, false);
// Establish a position for the bottom block of the trunk
BlockPos treePos = rootPos.up();
// Fix branch thicknesses and map out leaf locations
IBlockState treeState = world.getBlockState(treePos);
BlockBranch branch = TreeHelper.getBranch(treeState);
if (branch != null) {
// If a branch exists then the growth was successful
ILeavesProperties leavesProperties = species.getLeavesProperties();
SimpleVoxmap leafMap = new SimpleVoxmap(radius * 2 + 1, species.getWorldGenLeafMapHeight(), radius * 2 + 1).setMapAndCenter(treePos, new BlockPos(radius, 0, radius));
// This is responsible for thickening the branches
INodeInspector inflator = species.getNodeInflator(leafMap);
// This is responsible for gathering a list of branch end points
NodeFindEnds endFinder = new NodeFindEnds();
// The inflator signal will "paint" a temporary voxmap of all of the leaves and branches.
MapSignal signal = new MapSignal(inflator, endFinder);
// During worldgen we will not destroy looped nodes
signal.destroyLoopedNodes = careful;
branch.analyse(treeState, world, treePos, EnumFacing.DOWN, signal);
if (signal.found || signal.overflow) {
// Something went terribly wrong.
DynamicTrees.log.debug("Non-viable branch network detected during world generation @ " + treePos);
DynamicTrees.log.debug("Species: " + species);
DynamicTrees.log.debug("Radius: " + radius);
DynamicTrees.log.debug("JoCode: " + this);
// Completely blow away any improperly defined network nodes
cleanupFrankentree(world, treePos, treeState, endFinder.getEnds(), safeBounds);
// Now that everything is clear we may as well regenerate the tree that screwed everything up.
if (!secondChanceRegen) {
secondChanceRegen = true;
generate(world, species, rootPosIn, biome, facing, radius, safeBounds);
}
secondChanceRegen = false;
return;
}
List<BlockPos> endPoints = endFinder.getEnds();
// Use the voxmap to precompute leaf smothering so we don't have to age it as many times.
smother(leafMap, leavesProperties);
// Place Growing Leaves Blocks from voxmap
for (Cell cell : leafMap.getAllNonZeroCells((byte) 0x0F)) {
// Iterate through all of the cells that are leaves(not air or branches)
MutableBlockPos cellPos = cell.getPos();
if (safeBounds.inBounds(cellPos, false)) {
IBlockState testBlockState = world.getBlockState(cellPos);
Block testBlock = testBlockState.getBlock();
if (testBlock.isReplaceable(world, cellPos)) {
// Flag 16 to prevent observers from causing cascading lag
world.setBlockState(cellPos, leavesProperties.getDynamicLeavesState(cell.getValue()), worldGen ? 16 : 2);
}
} else {
leafMap.setVoxel(cellPos, (byte) 0);
}
}
// Shrink the leafMap down by the safeBounds object so that the aging process won't look for neighbors outside of the bounds.
for (Cell cell : leafMap.getAllNonZeroCells()) {
MutableBlockPos cellPos = cell.getPos();
if (!safeBounds.inBounds(cellPos, true)) {
leafMap.setVoxel(cellPos, (byte) 0);
}
}
// Age volume for 3 cycles using a leafmap
TreeHelper.ageVolume(world, leafMap, species.getWorldGenAgeIterations(), safeBounds);
// Rot the unsupported branches
if (species.handleRot(world, endPoints, rootPos, treePos, 0, safeBounds)) {
// The entire tree rotted away before it had a chance
return;
}
// Allow for special decorations by the tree itself
species.postGeneration(world, rootPos, biome, radius, endPoints, safeBounds, initialDirtState);
MinecraftForge.EVENT_BUS.post(new SpeciesPostGenerationEvent(world, species, rootPos, endPoints, safeBounds, initialDirtState));
// Add snow to parts of the tree in chunks where snow was already placed
addSnow(leafMap, world, rootPos, biome);
} else {
// The growth failed.. turn the soil back to what it was
world.setBlockState(rootPos, initialDirtState, careful ? 3 : 2);
}
}
}
use of com.ferreusveritas.dynamictrees.blocks.BlockBranch in project DynamicTrees by DynamicTreesTeam.
the class ModelHelper method regModel.
/**
* Registers models associated with the tree. At the moment this only deals with {@link BlockBranch} blocks
*
* @param tree
*/
public static void regModel(TreeFamily tree) {
BlockBranch blockBranch = tree.getDynamicBranch();
ModelResourceLocation modelLocation = getBranchModelResourceLocation(blockBranch);
setGenericStateMapper(blockBranch, modelLocation);
if (blockBranch instanceof BlockBranchThick) {
setGenericStateMapper(((BlockBranchThick) blockBranch).otherBlock, modelLocation);
}
BlockSurfaceRoot surfaceRoot = tree.getSurfaceRoots();
if (surfaceRoot != null) {
ModelLoader.setCustomStateMapper(surfaceRoot, new StateMap.Builder().ignore(surfaceRoot.getIgnorableProperties()).build());
}
}
Aggregations