mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-27 23:47:38 +01:00
- Deforester now hits forge hooks for tool break, block break, times used.
-Moved deforester not loosing durability from leaves to DeforesterItem instead of Tree mining - added destroyBlocks method in TreeCutter$Tree for less doubled code - Mechanical Saws currently break the tree with an empty "hand" as they did before - Silktouch and Fortune enchants are now being applied from deforesters
This commit is contained in:
parent
c46e286844
commit
f19c6ab763
5 changed files with 96 additions and 89 deletions
|
@ -5,9 +5,7 @@ import com.simibubi.create.content.contraptions.components.saw.SawBlock;
|
||||||
import com.simibubi.create.content.contraptions.components.saw.SawRenderer;
|
import com.simibubi.create.content.contraptions.components.saw.SawRenderer;
|
||||||
import com.simibubi.create.content.contraptions.components.saw.SawTileEntity;
|
import com.simibubi.create.content.contraptions.components.saw.SawTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||||
import com.simibubi.create.foundation.utility.BlockHelper;
|
|
||||||
import com.simibubi.create.foundation.utility.TreeCutter;
|
import com.simibubi.create.foundation.utility.TreeCutter;
|
||||||
import com.simibubi.create.foundation.utility.TreeCutter.Tree;
|
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
@ -59,14 +57,7 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour {
|
||||||
protected void onBlockBroken(MovementContext context, BlockPos pos, BlockState brokenState) {
|
protected void onBlockBroken(MovementContext context, BlockPos pos, BlockState brokenState) {
|
||||||
if (brokenState.isIn(BlockTags.LEAVES))
|
if (brokenState.isIn(BlockTags.LEAVES))
|
||||||
return;
|
return;
|
||||||
Tree tree = TreeCutter.cutTree(context.world, pos);
|
TreeCutter.findTree(context.world, pos).destroyBlocks(context.world, null, (stack, dropPos) -> dropItemFromCutTree(context, stack, dropPos));
|
||||||
if (tree != null) {
|
|
||||||
for (BlockPos log : tree.logs)
|
|
||||||
BlockHelper.destroyBlock(context.world, log, 1 / 2f, stack -> dropItemFromCutTree(context, log, stack));
|
|
||||||
for (BlockPos leaf : tree.leaves)
|
|
||||||
BlockHelper.destroyBlock(context.world, leaf, 1 / 8f,
|
|
||||||
stack -> dropItemFromCutTree(context, leaf, stack));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dropItemFromCutTree(MovementContext context, BlockPos pos, ItemStack stack) {
|
public void dropItemFromCutTree(MovementContext context, BlockPos pos, ItemStack stack) {
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
package com.simibubi.create.content.contraptions.components.saw;
|
package com.simibubi.create.content.contraptions.components.saw;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -18,9 +15,7 @@ import com.simibubi.create.foundation.item.ItemHelper;
|
||||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour;
|
import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
|
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
|
||||||
import com.simibubi.create.foundation.utility.BlockHelper;
|
|
||||||
import com.simibubi.create.foundation.utility.TreeCutter;
|
import com.simibubi.create.foundation.utility.TreeCutter;
|
||||||
import com.simibubi.create.foundation.utility.TreeCutter.Tree;
|
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
import com.simibubi.create.foundation.utility.recipe.RecipeConditions;
|
import com.simibubi.create.foundation.utility.recipe.RecipeConditions;
|
||||||
import com.simibubi.create.foundation.utility.recipe.RecipeFinder;
|
import com.simibubi.create.foundation.utility.recipe.RecipeFinder;
|
||||||
|
@ -360,13 +355,7 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity {
|
||||||
@Override
|
@Override
|
||||||
public void onBlockBroken(BlockState stateToBreak) {
|
public void onBlockBroken(BlockState stateToBreak) {
|
||||||
super.onBlockBroken(stateToBreak);
|
super.onBlockBroken(stateToBreak);
|
||||||
Tree tree = TreeCutter.cutTree(world, breakingPos);
|
TreeCutter.findTree(world, breakingPos).destroyBlocks(world, null, this::dropItemFromCutTree);
|
||||||
if (tree != null) {
|
|
||||||
for (BlockPos log : tree.logs)
|
|
||||||
BlockHelper.destroyBlock(world, log, 1 / 2f, stack -> dropItemFromCutTree(log, stack));
|
|
||||||
for (BlockPos leaf : tree.leaves)
|
|
||||||
BlockHelper.destroyBlock(world, leaf, 1 / 8f, stack -> dropItemFromCutTree(leaf, stack));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dropItemFromCutTree(BlockPos pos, ItemStack stack) {
|
public void dropItemFromCutTree(BlockPos pos, ItemStack stack) {
|
||||||
|
|
|
@ -2,18 +2,17 @@ package com.simibubi.create.content.curiosities.tools;
|
||||||
|
|
||||||
import com.simibubi.create.AllItems;
|
import com.simibubi.create.AllItems;
|
||||||
import com.simibubi.create.AllTags;
|
import com.simibubi.create.AllTags;
|
||||||
import com.simibubi.create.foundation.utility.BlockHelper;
|
|
||||||
import com.simibubi.create.foundation.utility.TreeCutter;
|
import com.simibubi.create.foundation.utility.TreeCutter;
|
||||||
import com.simibubi.create.foundation.utility.TreeCutter.Tree;
|
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
|
import mcp.MethodsReturnNonnullByDefault;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.item.ItemEntity;
|
import net.minecraft.entity.item.ItemEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.AxeItem;
|
import net.minecraft.item.AxeItem;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.tags.BlockTags;
|
import net.minecraft.tags.BlockTags;
|
||||||
import net.minecraft.util.Hand;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.vector.Vector3d;
|
import net.minecraft.util.math.vector.Vector3d;
|
||||||
import net.minecraft.world.IWorld;
|
import net.minecraft.world.IWorld;
|
||||||
|
@ -23,37 +22,31 @@ import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus;
|
import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus;
|
||||||
|
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
|
|
||||||
|
@ParametersAreNonnullByDefault
|
||||||
|
@MethodsReturnNonnullByDefault
|
||||||
@EventBusSubscriber(bus = Bus.FORGE)
|
@EventBusSubscriber(bus = Bus.FORGE)
|
||||||
public class DeforesterItem extends AxeItem {
|
public class DeforesterItem extends AxeItem {
|
||||||
|
private static boolean deforesting = false; // required as to not run into "recursions" over forge events on tree cutting
|
||||||
|
|
||||||
public DeforesterItem(Properties builder) {
|
public DeforesterItem(Properties builder) {
|
||||||
super(AllToolTiers.RADIANT, 5.0F, -3.1F, builder);
|
super(AllToolTiers.RADIANT, 5.0F, -3.1F, builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Moved away from Item#onBlockDestroyed as it does not get called in Creative
|
// Moved away from Item#onBlockDestroyed as it does not get called in Creative
|
||||||
public static void destroyTree(ItemStack stack, IWorld iWorld, BlockState state, BlockPos pos,
|
public static void destroyTree(IWorld iWorld, BlockState state, BlockPos pos,
|
||||||
PlayerEntity player) {
|
PlayerEntity player) {
|
||||||
if (!(state.isIn(BlockTags.LOGS) || AllTags.AllBlockTags.SLIMY_LOGS.matches(state)) || player.isSneaking() || !(iWorld instanceof World))
|
|
||||||
|
if (deforesting ||!(state.isIn(BlockTags.LOGS) || AllTags.AllBlockTags.SLIMY_LOGS.matches(state)) || player.isSneaking() || !(iWorld instanceof World))
|
||||||
return;
|
return;
|
||||||
World worldIn = (World) iWorld;
|
World worldIn = (World) iWorld;
|
||||||
Tree tree = TreeCutter.cutTree(worldIn, pos);
|
|
||||||
if (tree == null)
|
|
||||||
return;
|
|
||||||
boolean dropBlock = !player.isCreative();
|
|
||||||
|
|
||||||
Vector3d vec = player.getLookVec();
|
Vector3d vec = player.getLookVec();
|
||||||
for (BlockPos log : tree.logs)
|
|
||||||
BlockHelper.destroyBlock(worldIn, log, 1 / 2f, item -> {
|
deforesting = true;
|
||||||
if (dropBlock) {
|
TreeCutter.findTree(worldIn, pos).destroyBlocks(worldIn, player, (dropPos, item) -> dropItemFromCutTree(worldIn, pos, vec, dropPos, item));
|
||||||
dropItemFromCutTree(worldIn, pos, vec, log, item);
|
deforesting = false;
|
||||||
stack.damageItem(1, player, p -> p.sendBreakAnimation(Hand.MAIN_HAND));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
for (BlockPos leaf : tree.leaves)
|
|
||||||
BlockHelper.destroyBlock(worldIn, leaf, 1 / 8f, item -> {
|
|
||||||
if (dropBlock)
|
|
||||||
dropItemFromCutTree(worldIn, pos, vec, leaf, item);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
|
@ -61,7 +54,7 @@ public class DeforesterItem extends AxeItem {
|
||||||
ItemStack heldItemMainhand = event.getPlayer().getHeldItemMainhand();
|
ItemStack heldItemMainhand = event.getPlayer().getHeldItemMainhand();
|
||||||
if (!AllItems.DEFORESTER.isIn(heldItemMainhand))
|
if (!AllItems.DEFORESTER.isIn(heldItemMainhand))
|
||||||
return;
|
return;
|
||||||
destroyTree(heldItemMainhand, event.getWorld(), event.getState(), event.getPos(), event.getPlayer());
|
destroyTree(event.getWorld(), event.getState(), event.getPos(), event.getPlayer());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void dropItemFromCutTree(World world, BlockPos breakingPos, Vector3d fallDirection, BlockPos pos,
|
public static void dropItemFromCutTree(World world, BlockPos breakingPos, Vector3d fallDirection, BlockPos pos,
|
||||||
|
@ -73,4 +66,10 @@ public class DeforesterItem extends AxeItem {
|
||||||
world.addEntity(entity);
|
world.addEntity(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onBlockDestroyed(ItemStack stack, World world, BlockState state, BlockPos pos, LivingEntity entity) {
|
||||||
|
if (!state.isIn(BlockTags.LEAVES))
|
||||||
|
super.onBlockDestroyed(stack, world, state, pos, entity);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,9 @@ import java.util.function.Consumer;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import net.minecraft.stats.Stats;
|
||||||
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
import net.minecraftforge.event.world.BlockEvent;
|
||||||
import org.apache.commons.lang3.mutable.MutableInt;
|
import org.apache.commons.lang3.mutable.MutableInt;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
|
@ -184,16 +187,33 @@ public class BlockHelper {
|
||||||
|
|
||||||
public static void destroyBlock(World world, BlockPos pos, float effectChance,
|
public static void destroyBlock(World world, BlockPos pos, float effectChance,
|
||||||
Consumer<ItemStack> droppedItemCallback) {
|
Consumer<ItemStack> droppedItemCallback) {
|
||||||
|
destroyBlockAs(world, pos, null, ItemStack.EMPTY, effectChance, droppedItemCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void destroyBlockAs(World world, BlockPos pos, @Nullable PlayerEntity player, ItemStack usedTool, float effectChance,
|
||||||
|
Consumer<ItemStack> droppedItemCallback) {
|
||||||
FluidState fluidState = world.getFluidState(pos);
|
FluidState fluidState = world.getFluidState(pos);
|
||||||
BlockState state = world.getBlockState(pos);
|
BlockState state = world.getBlockState(pos);
|
||||||
if (world.rand.nextFloat() < effectChance)
|
if (world.rand.nextFloat() < effectChance)
|
||||||
world.playEvent(2001, pos, Block.getStateId(state));
|
world.playEvent(2001, pos, Block.getStateId(state));
|
||||||
TileEntity tileentity = state.hasTileEntity() ? world.getTileEntity(pos) : null;
|
TileEntity tileentity = state.hasTileEntity() ? world.getTileEntity(pos) : null;
|
||||||
|
if (player != null) {
|
||||||
|
BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(world, pos, state, player);
|
||||||
|
MinecraftForge.EVENT_BUS.post(event);
|
||||||
|
if (event.isCanceled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (event.getExpToDrop() > 0 && world instanceof ServerWorld)
|
||||||
|
state.getBlock().dropXpOnBlockBreak((ServerWorld) world, pos, event.getExpToDrop());
|
||||||
|
|
||||||
|
usedTool.onBlockDestroyed(world, state, pos, player);
|
||||||
|
player.addStat(Stats.BLOCK_MINED.get(state.getBlock()));
|
||||||
|
}
|
||||||
|
|
||||||
if (world instanceof ServerWorld && world.getGameRules()
|
if (world instanceof ServerWorld && world.getGameRules()
|
||||||
.getBoolean(GameRules.DO_TILE_DROPS) && !world.restoringBlockSnapshots) {
|
.getBoolean(GameRules.DO_TILE_DROPS) && !world.restoringBlockSnapshots && (player == null || !player.isCreative())) {
|
||||||
for (ItemStack itemStack : Block.getDrops(state, (ServerWorld) world, pos, tileentity))
|
for (ItemStack itemStack : Block.getDrops(state, (ServerWorld) world, pos, tileentity,
|
||||||
|
player, usedTool))
|
||||||
droppedItemCallback.accept(itemStack);
|
droppedItemCallback.accept(itemStack);
|
||||||
state.spawnAdditionalDrops((ServerWorld) world, pos, ItemStack.EMPTY);
|
state.spawnAdditionalDrops((ServerWorld) world, pos, ItemStack.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,51 +1,41 @@
|
||||||
package com.simibubi.create.foundation.utility;
|
package com.simibubi.create.foundation.utility;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import com.google.common.collect.Iterators;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicates;
|
|
||||||
import com.simibubi.create.AllTags;
|
import com.simibubi.create.AllTags;
|
||||||
|
import net.minecraft.block.*;
|
||||||
import net.minecraft.block.BambooBlock;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.block.Blocks;
|
|
||||||
import net.minecraft.block.CactusBlock;
|
|
||||||
import net.minecraft.block.ChorusFlowerBlock;
|
|
||||||
import net.minecraft.block.ChorusPlantBlock;
|
|
||||||
import net.minecraft.block.KelpBlock;
|
|
||||||
import net.minecraft.block.KelpTopBlock;
|
|
||||||
import net.minecraft.block.LeavesBlock;
|
|
||||||
import net.minecraft.block.SugarCaneBlock;
|
|
||||||
import net.minecraft.tags.BlockTags;
|
import net.minecraft.tags.BlockTags;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.IBlockReader;
|
import net.minecraft.world.IBlockReader;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.event.ForgeEventFactory;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public class TreeCutter {
|
public class TreeCutter {
|
||||||
|
public static final Tree NO_TREE = new Tree(Collections.emptyList(), Collections.emptyList());
|
||||||
|
|
||||||
public static class Tree {
|
|
||||||
public List<BlockPos> logs;
|
|
||||||
public List<BlockPos> leaves;
|
|
||||||
|
|
||||||
public Tree(List<BlockPos> logs, List<BlockPos> leaves) {
|
|
||||||
this.logs = logs;
|
|
||||||
this.leaves = leaves;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds a tree at the given pos. Block at the position should be air
|
* Finds a tree at the given pos. Block at the position should be air
|
||||||
*
|
*
|
||||||
* @param reader
|
* @param reader
|
||||||
* @param pos
|
* @param pos
|
||||||
* @return null if not found or not fully cut
|
* @return null if not found or not fully cut
|
||||||
*/
|
*/
|
||||||
public static Tree cutTree(IBlockReader reader, BlockPos pos) {
|
@Nonnull
|
||||||
|
public static Tree findTree(@Nullable IBlockReader reader, BlockPos pos) {
|
||||||
|
if (reader == null)
|
||||||
|
return NO_TREE;
|
||||||
|
|
||||||
List<BlockPos> logs = new ArrayList<>();
|
List<BlockPos> logs = new ArrayList<>();
|
||||||
List<BlockPos> leaves = new ArrayList<>();
|
List<BlockPos> leaves = new ArrayList<>();
|
||||||
Set<BlockPos> visited = new HashSet<>();
|
Set<BlockPos> visited = new HashSet<>();
|
||||||
|
@ -87,7 +77,7 @@ public class TreeCutter {
|
||||||
|
|
||||||
// Regular Tree
|
// Regular Tree
|
||||||
if (!validateCut(reader, pos))
|
if (!validateCut(reader, pos))
|
||||||
return null;
|
return NO_TREE;
|
||||||
|
|
||||||
visited.add(pos);
|
visited.add(pos);
|
||||||
BlockPos.getAllInBox(pos.add(-1, 0, -1), pos.add(1, 1, 1))
|
BlockPos.getAllInBox(pos.add(-1, 0, -1), pos.add(1, 1, 1))
|
||||||
|
@ -112,9 +102,8 @@ public class TreeCutter {
|
||||||
frontier.addAll(logs);
|
frontier.addAll(logs);
|
||||||
while (!frontier.isEmpty()) {
|
while (!frontier.isEmpty()) {
|
||||||
BlockPos currentPos = frontier.remove(0);
|
BlockPos currentPos = frontier.remove(0);
|
||||||
if (!logs.contains(currentPos))
|
if (!logs.contains(currentPos) && visited.contains(currentPos))
|
||||||
if (visited.contains(currentPos))
|
continue;
|
||||||
continue;
|
|
||||||
visited.add(currentPos);
|
visited.add(currentPos);
|
||||||
|
|
||||||
BlockState blockState = reader.getBlockState(currentPos);
|
BlockState blockState = reader.getBlockState(currentPos);
|
||||||
|
@ -158,15 +147,13 @@ public class TreeCutter {
|
||||||
return true;
|
return true;
|
||||||
if (block instanceof KelpBlock)
|
if (block instanceof KelpBlock)
|
||||||
return true;
|
return true;
|
||||||
if (block instanceof KelpTopBlock)
|
return block instanceof KelpTopBlock;
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether a tree was fully cut by seeing whether the layer above the cut
|
* Checks whether a tree was fully cut by seeing whether the layer above the cut
|
||||||
* is not supported by any more logs.
|
* is not supported by any more logs.
|
||||||
*
|
*
|
||||||
* @param reader
|
* @param reader
|
||||||
* @param pos
|
* @param pos
|
||||||
* @return
|
* @return
|
||||||
|
@ -206,7 +193,7 @@ public class TreeCutter {
|
||||||
|
|
||||||
private static void addNeighbours(BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited) {
|
private static void addNeighbours(BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited) {
|
||||||
BlockPos.getAllInBox(pos.add(-1, -1, -1), pos.add(1, 1, 1))
|
BlockPos.getAllInBox(pos.add(-1, -1, -1), pos.add(1, 1, 1))
|
||||||
.filter(Predicates.not(visited::contains))
|
.filter(((Predicate<BlockPos>) visited::contains).negate())
|
||||||
.forEach(p -> frontier.add(new BlockPos(p)));
|
.forEach(p -> frontier.add(new BlockPos(p)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,4 +209,25 @@ public class TreeCutter {
|
||||||
return state.contains(LeavesBlock.DISTANCE);
|
return state.contains(LeavesBlock.DISTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Tree {
|
||||||
|
private final List<BlockPos> logs;
|
||||||
|
private final List<BlockPos> leaves;
|
||||||
|
|
||||||
|
public Tree(List<BlockPos> logs, List<BlockPos> leaves) {
|
||||||
|
this.logs = logs;
|
||||||
|
this.leaves = leaves;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroyBlocks(World world, @Nullable LivingEntity entity, BiConsumer<BlockPos, ItemStack> drop) {
|
||||||
|
PlayerEntity playerEntity = entity instanceof PlayerEntity ? ((PlayerEntity) entity) : null;
|
||||||
|
ItemStack toDamage = playerEntity != null && !playerEntity.isCreative() ? playerEntity.getHeldItemMainhand() : ItemStack.EMPTY;
|
||||||
|
Iterators.concat(logs.iterator(), leaves.iterator()).forEachRemaining(pos -> {
|
||||||
|
ItemStack usedTool = toDamage.copy();
|
||||||
|
BlockHelper.destroyBlockAs(world, pos, playerEntity, toDamage, 1 / 2f, stack -> drop.accept(pos, stack));
|
||||||
|
if (toDamage.isEmpty() && !usedTool.isEmpty())
|
||||||
|
ForgeEventFactory.onPlayerDestroyItem(playerEntity, usedTool, Hand.MAIN_HAND);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue