Search in sources :

Example 1 with INodeInspector

use of com.ferreusveritas.dynamictrees.api.network.INodeInspector 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);
        }
    }
}
Also used : INodeInspector(com.ferreusveritas.dynamictrees.api.network.INodeInspector) NodeFindEnds(com.ferreusveritas.dynamictrees.systems.nodemappers.NodeFindEnds) IBlockState(net.minecraft.block.state.IBlockState) SpeciesPostGenerationEvent(com.ferreusveritas.dynamictrees.event.SpeciesPostGenerationEvent) SimpleVoxmap(com.ferreusveritas.dynamictrees.util.SimpleVoxmap) BlockBranch(com.ferreusveritas.dynamictrees.blocks.BlockBranch) ILeavesProperties(com.ferreusveritas.dynamictrees.api.treedata.ILeavesProperties) Block(net.minecraft.block.Block) MutableBlockPos(net.minecraft.util.math.BlockPos.MutableBlockPos) BlockPos(net.minecraft.util.math.BlockPos) Cell(com.ferreusveritas.dynamictrees.util.SimpleVoxmap.Cell) MutableBlockPos(net.minecraft.util.math.BlockPos.MutableBlockPos) MapSignal(com.ferreusveritas.dynamictrees.api.network.MapSignal)

Aggregations

INodeInspector (com.ferreusveritas.dynamictrees.api.network.INodeInspector)1 MapSignal (com.ferreusveritas.dynamictrees.api.network.MapSignal)1 ILeavesProperties (com.ferreusveritas.dynamictrees.api.treedata.ILeavesProperties)1 BlockBranch (com.ferreusveritas.dynamictrees.blocks.BlockBranch)1 SpeciesPostGenerationEvent (com.ferreusveritas.dynamictrees.event.SpeciesPostGenerationEvent)1 NodeFindEnds (com.ferreusveritas.dynamictrees.systems.nodemappers.NodeFindEnds)1 SimpleVoxmap (com.ferreusveritas.dynamictrees.util.SimpleVoxmap)1 Cell (com.ferreusveritas.dynamictrees.util.SimpleVoxmap.Cell)1 Block (net.minecraft.block.Block)1 IBlockState (net.minecraft.block.state.IBlockState)1 BlockPos (net.minecraft.util.math.BlockPos)1 MutableBlockPos (net.minecraft.util.math.BlockPos.MutableBlockPos)1