Search in sources :

Example 11 with MapSignal

use of com.ferreusveritas.dynamictrees.api.network.MapSignal in project DynamicTrees by DynamicTreesTeam.

the class FeatureGenFruit method postGrow.

@Override
public boolean postGrow(World world, BlockPos rootPos, BlockPos treePos, Species species, int soilLife, boolean natural) {
    IBlockState blockState = world.getBlockState(treePos);
    BlockBranch branch = TreeHelper.getBranch(blockState);
    if (branch != null && branch.getRadius(blockState) >= fruitingRadius && natural) {
        if (species.seasonalFruitProductionFactor(world, rootPos) > world.rand.nextFloat()) {
            NodeFindEnds endFinder = new NodeFindEnds();
            TreeHelper.startAnalysisFromRoot(world, rootPos, new MapSignal(endFinder));
            List<BlockPos> endPoints = endFinder.getEnds();
            int qty = getQuantity(false);
            if (!endPoints.isEmpty()) {
                for (int i = 0; i < qty; i++) {
                    BlockPos endPoint = endPoints.get(world.rand.nextInt(endPoints.size()));
                    addFruit(world, species, rootPos.up(), endPoint, false, true, SafeChunkBounds.ANY);
                }
            }
        }
    }
    return true;
}
Also used : NodeFindEnds(com.ferreusveritas.dynamictrees.systems.nodemappers.NodeFindEnds) IBlockState(net.minecraft.block.state.IBlockState) BlockPos(net.minecraft.util.math.BlockPos) BlockBranch(com.ferreusveritas.dynamictrees.blocks.BlockBranch) MapSignal(com.ferreusveritas.dynamictrees.api.network.MapSignal)

Example 12 with MapSignal

use of com.ferreusveritas.dynamictrees.api.network.MapSignal in project DynamicTrees by DynamicTreesTeam.

the class FeatureGenPodzol method postGrow.

@Override
public boolean postGrow(World world, BlockPos rootPos, BlockPos treePos, Species species, int soilLife, boolean natural) {
    if (ModConfigs.podzolGen) {
        NodeFindEnds endFinder = new NodeFindEnds();
        TreeHelper.startAnalysisFromRoot(world, rootPos, new MapSignal(endFinder));
        List<BlockPos> endPoints = endFinder.getEnds();
        if (!endPoints.isEmpty()) {
            Random random = world.rand;
            BlockPos pos = endPoints.get(random.nextInt(endPoints.size()));
            int x = pos.getX() + random.nextInt(5) - 2;
            int z = pos.getZ() + random.nextInt(5) - 2;
            final int darkThreshold = 4;
            for (int i = 0; i < 32; i++) {
                BlockPos offPos = new BlockPos(x, pos.getY() - 1 - i, z);
                if (!world.isAirBlock(offPos)) {
                    Block block = world.getBlockState(offPos).getBlock();
                    if (block instanceof BlockBranch || block instanceof BlockMushroom || block instanceof BlockLeaves) {
                        // Skip past Mushrooms and branches on the way down
                        continue;
                    } else if (block instanceof BlockFlower || block instanceof BlockTallGrass || block instanceof BlockDoublePlant) {
                        // Kill Plants
                        if (world.getLightFor(EnumSkyBlock.SKY, offPos) <= darkThreshold) {
                            world.setBlockToAir(pos);
                        }
                        continue;
                    } else if (block == Blocks.DIRT || block == Blocks.GRASS) {
                        // Convert grass or dirt to podzol
                        if (world.getLightFor(EnumSkyBlock.SKY, offPos.up()) <= darkThreshold) {
                            world.setBlockState(offPos, ModBlocks.blockStates.podzol);
                        } else {
                            spreadPodzol(world, pos);
                        }
                    }
                    break;
                }
            }
        }
    }
    return true;
}
Also used : NodeFindEnds(com.ferreusveritas.dynamictrees.systems.nodemappers.NodeFindEnds) BlockBranch(com.ferreusveritas.dynamictrees.blocks.BlockBranch) Random(java.util.Random) EnumSkyBlock(net.minecraft.world.EnumSkyBlock) BlockPos(net.minecraft.util.math.BlockPos) MapSignal(com.ferreusveritas.dynamictrees.api.network.MapSignal)

Example 13 with MapSignal

use of com.ferreusveritas.dynamictrees.api.network.MapSignal 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)

Example 14 with MapSignal

use of com.ferreusveritas.dynamictrees.api.network.MapSignal in project DynamicTrees by DynamicTreesTeam.

the class BlockBranch method destroyBranchFromNode.

/**
 * Destroys all branches recursively not facing the branching direction with the root node
 *
 * @param world     The world
 * @param cutPos    The position of the branch being lobbed
 * @param toolDir   The face that was pounded on when breaking the block at cutPos
 * @param wholeTree Indicates if the whole tree should be destroyed or just the branch
 * @return The volume of the portion of the tree that was destroyed
 */
public BranchDestructionData destroyBranchFromNode(World world, BlockPos cutPos, EnumFacing toolDir, boolean wholeTree) {
    IBlockState blockState = world.getBlockState(cutPos);
    NodeSpecies nodeSpecies = new NodeSpecies();
    // Analyze entire tree network to find root node and species
    MapSignal signal = analyse(blockState, world, cutPos, null, new MapSignal(nodeSpecies));
    // Get the species from the root node
    Species species = nodeSpecies.getSpecies();
    // Analyze only part of the tree beyond the break point and map out the extended block states
    // We can't destroy the branches during this step since we need accurate extended block states that include connections
    NodeExtState extStateMapper = new NodeExtState(cutPos);
    analyse(blockState, world, cutPos, wholeTree ? null : signal.localRootDir, new MapSignal(extStateMapper));
    // Analyze only part of the tree beyond the break point and calculate it's volume, then destroy the branches
    NodeNetVolume volumeSum = new NodeNetVolume();
    NodeDestroyer destroyer = new NodeDestroyer(species);
    destroyMode = EnumDestroyMode.HARVEST;
    analyse(blockState, world, cutPos, wholeTree ? null : signal.localRootDir, new MapSignal(volumeSum, destroyer));
    destroyMode = EnumDestroyMode.SLOPPY;
    // Destroy all the leaves on the branch, store them in a map and convert endpoint coordinates from absolute to relative
    List<BlockPos> endPoints = destroyer.getEnds();
    Map<BlockPos, IBlockState> destroyedLeaves = new HashMap<>();
    List<BlockItemStack> leavesDropsList = new ArrayList<>();
    destroyLeaves(world, cutPos, species, endPoints, destroyedLeaves, leavesDropsList);
    endPoints = endPoints.stream().map(p -> p.subtract(cutPos)).collect(Collectors.toList());
    // Calculate main trunk height
    int trunkHeight = 1;
    for (BlockPos iter = new BlockPos(0, 1, 0); extStateMapper.getExtStateMap().containsKey(iter); iter = iter.up()) {
        trunkHeight++;
    }
    EnumFacing cutDir = signal.localRootDir;
    if (cutDir == null) {
        cutDir = EnumFacing.DOWN;
    }
    return new BranchDestructionData(species, extStateMapper.getExtStateMap(), destroyedLeaves, leavesDropsList, endPoints, volumeSum.getVolume(), cutPos, cutDir, toolDir, trunkHeight);
}
Also used : NodeSpecies(com.ferreusveritas.dynamictrees.systems.nodemappers.NodeSpecies) NodeNetVolume(com.ferreusveritas.dynamictrees.systems.nodemappers.NodeNetVolume) NodeExtState(com.ferreusveritas.dynamictrees.systems.nodemappers.NodeExtState) IBlockState(net.minecraft.block.state.IBlockState) EnumFacing(net.minecraft.util.EnumFacing) BranchDestructionData(com.ferreusveritas.dynamictrees.util.BranchDestructionData) NodeDestroyer(com.ferreusveritas.dynamictrees.systems.nodemappers.NodeDestroyer) MutableBlockPos(net.minecraft.util.math.BlockPos.MutableBlockPos) BlockPos(net.minecraft.util.math.BlockPos) NodeSpecies(com.ferreusveritas.dynamictrees.systems.nodemappers.NodeSpecies) Species(com.ferreusveritas.dynamictrees.trees.Species) MapSignal(com.ferreusveritas.dynamictrees.api.network.MapSignal)

Example 15 with MapSignal

use of com.ferreusveritas.dynamictrees.api.network.MapSignal in project DynamicTrees by DynamicTreesTeam.

the class TreeHelper method findRootNode.

/**
 * Find the root node of a tree.
 *
 * @param world The world
 * @param pos   The position being analyzed
 * @return The position of the root node of the tree or BlockPos.ORIGIN if nothing was found.
 */
public static BlockPos findRootNode(World world, BlockPos pos) {
    pos = dereferenceTrunkShell(world, pos);
    IBlockState state = world.getBlockState(pos);
    ITreePart treePart = TreeHelper.getTreePart(state);
    switch(treePart.getTreePartType()) {
        case BRANCH:
            // Analyze entire tree network to find root node
            MapSignal signal = treePart.analyse(state, world, pos, null, new MapSignal());
            if (signal.found) {
                return signal.root;
            }
            break;
        case ROOT:
            return pos;
        default:
            return BlockPos.ORIGIN;
    }
    return BlockPos.ORIGIN;
}
Also used : ITreePart(com.ferreusveritas.dynamictrees.api.treedata.ITreePart) IBlockState(net.minecraft.block.state.IBlockState) MapSignal(com.ferreusveritas.dynamictrees.api.network.MapSignal)

Aggregations

MapSignal (com.ferreusveritas.dynamictrees.api.network.MapSignal)15 IBlockState (net.minecraft.block.state.IBlockState)10 BlockPos (net.minecraft.util.math.BlockPos)9 BlockBranch (com.ferreusveritas.dynamictrees.blocks.BlockBranch)6 Species (com.ferreusveritas.dynamictrees.trees.Species)5 BlockRooty (com.ferreusveritas.dynamictrees.blocks.BlockRooty)4 NodeFindEnds (com.ferreusveritas.dynamictrees.systems.nodemappers.NodeFindEnds)4 MutableBlockPos (net.minecraft.util.math.BlockPos.MutableBlockPos)4 Block (net.minecraft.block.Block)3 ILeavesProperties (com.ferreusveritas.dynamictrees.api.treedata.ILeavesProperties)2 NodeCollector (com.ferreusveritas.dynamictrees.systems.nodemappers.NodeCollector)2 NodeNetVolume (com.ferreusveritas.dynamictrees.systems.nodemappers.NodeNetVolume)2 NodeTransform (com.ferreusveritas.dynamictrees.systems.nodemappers.NodeTransform)2 SimpleVoxmap (com.ferreusveritas.dynamictrees.util.SimpleVoxmap)2 Cell (com.ferreusveritas.dynamictrees.util.SimpleVoxmap.Cell)2 EnumFacing (net.minecraft.util.EnumFacing)2 WeightedList (net.minecraft.util.WeightedList)2 INodeInspector (com.ferreusveritas.dynamictrees.api.network.INodeInspector)1 ITreePart (com.ferreusveritas.dynamictrees.api.treedata.ITreePart)1 BlockDynamicLeaves (com.ferreusveritas.dynamictrees.blocks.BlockDynamicLeaves)1