Skip to content

Commit

Permalink
Respect leaves breaking in falling animation (#658)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rakambda authored Jan 5, 2024
1 parent 15f7a67 commit 22ddf43
Showing 1 changed file with 110 additions and 107 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,112 +15,115 @@

@Log4j2
@RequiredArgsConstructor
public class FallingAnimationTreeBreakingHandler implements ITreeBreakingHandler {
private final static Map<Map.Entry<Boolean, Boolean>, FallingAnimationTreeBreakingHandler> INSTANCE = new ConcurrentHashMap<>();

private final FallingTreeCommon<?> mod;
private final boolean dropLogsAsItems;
private final boolean dropLeavesAsItems;
private final LeafForceBreaker leafForceBreaker;

@Override
public boolean breakTree(@NotNull IPlayer player, @NotNull Tree tree) throws BreakTreeTooBigException {
var tool = player.getMainHandItem();
var level = tree.getLevel();
var toolHandler = new ToolDamageHandler(tool,
mod.getConfiguration().getTools().getDamageMultiplicand(),
mod.getConfiguration().getTools().isPreserve(),
tree.getBreakableCount(),
mod.getConfiguration().getTrees().getMaxSize(),
mod.getConfiguration().getTrees().getMaxSizeAction(),
mod.getConfiguration().getTools().getDamageRounding());

if (mod.getConfiguration().getTools().isPreserve() && toolHandler.getMaxBreakCount() <= 0) {
log.debug("Didn't break tree at {} as {}'s tool was about to break", tree.getHitPos(), player);
mod.notifyPlayer(player, mod.translate("chat.fallingtree.prevented_break_tool"));
return false;
}

var scannedLeaves = new LinkedList<IBlockPos>();
var brokenCount = tree.getParts().stream()
.sorted(mod.getConfiguration().getTrees().getBreakOrder().getComparator())
.limit(toolHandler.getMaxBreakCount())
.mapToInt(part -> {
var logBlockPos = part.blockPos();
var logState = level.getBlockState(logBlockPos);

if (!tree.getHitPos().equals(logBlockPos) && !mod.checkCanBreakBlock(level, logBlockPos, logState, player)) {
return 0;
}

player.awardItemUsed(tool.getItem());
if (dropLogsAsItems && (!player.isCreative() || mod.getConfiguration().isLootInCreative())) {
logState.getBlock().playerDestroy(level, player, logBlockPos, logState, level.getBlockEntity(logBlockPos), tool);
}

level.fallBlock(logBlockPos, !dropLogsAsItems,
public class FallingAnimationTreeBreakingHandler implements ITreeBreakingHandler{
private final static Map<Map.Entry<Boolean, Boolean>, FallingAnimationTreeBreakingHandler> INSTANCE = new ConcurrentHashMap<>();
private final FallingTreeCommon<?> mod;
private final boolean dropLogsAsItems;
private final boolean dropLeavesAsItems;
private final LeafForceBreaker leafForceBreaker;
@Override
public boolean breakTree(@NotNull IPlayer player, @NotNull Tree tree) throws BreakTreeTooBigException{
var tool = player.getMainHandItem();
var level = tree.getLevel();
var toolHandler = new ToolDamageHandler(tool,
mod.getConfiguration().getTools().getDamageMultiplicand(),
mod.getConfiguration().getTools().isPreserve(),
tree.getBreakableCount(),
mod.getConfiguration().getTrees().getMaxSize(),
mod.getConfiguration().getTrees().getMaxSizeAction(),
mod.getConfiguration().getTools().getDamageRounding());
if(mod.getConfiguration().getTools().isPreserve() && toolHandler.getMaxBreakCount() <= 0){
log.debug("Didn't break tree at {} as {}'s tool was about to break", tree.getHitPos(), player);
mod.notifyPlayer(player, mod.translate("chat.fallingtree.prevented_break_tool"));
return false;
}
var scannedLeaves = new LinkedList<IBlockPos>();
var brokenCount = tree.getParts().stream()
.sorted(mod.getConfiguration().getTrees().getBreakOrder().getComparator())
.limit(toolHandler.getMaxBreakCount())
.mapToInt(part -> {
var logBlockPos = part.blockPos();
var logState = level.getBlockState(logBlockPos);
if(!tree.getHitPos().equals(logBlockPos) && !mod.checkCanBreakBlock(level, logBlockPos, logState, player)){
return 0;
}
player.awardItemUsed(tool.getItem());
if(dropLogsAsItems && (!player.isCreative() || mod.getConfiguration().isLootInCreative())){
logState.getBlock().playerDestroy(level, player, logBlockPos, logState, level.getBlockEntity(logBlockPos), tool);
}
level.fallBlock(logBlockPos, !dropLogsAsItems,
0, 0.5, 0,
(level.getRandom().nextDouble() - 0.5) * 0.4, 0, (level.getRandom().nextDouble() - 0.5) * 0.4);

fallLeaf(scannedLeaves, player, level, 5, logBlockPos.below());
fallLeaf(scannedLeaves, player, level, 5, logBlockPos.north());
fallLeaf(scannedLeaves, player, level, 5, logBlockPos.east());
fallLeaf(scannedLeaves, player, level, 5, logBlockPos.south());
fallLeaf(scannedLeaves, player, level, 5, logBlockPos.west());
fallLeaf(scannedLeaves, player, level, 5, logBlockPos.above());

var isRemoved = level.removeBlock(logBlockPos, false);

return part.treePartType().isBreakable() && isRemoved ? 1 : 0;
})
.sum();

var toolDamage = toolHandler.getActualDamage(brokenCount) - 1;
if (toolDamage > 0) {
tool.damage(toolDamage, player);
}

if (brokenCount >= toolHandler.getMaxBreakCount()) {
leafForceBreaker.forceBreakDecayLeaves(player, tree, level);
}
return true;
}

private void fallLeaf(LinkedList<IBlockPos> scannedLeaves, @NotNull IPlayer player, @NotNull ILevel level, int distance, @NotNull IBlockPos blockPos) {
if (distance == 0) {
return;
}

fallLeaf(scannedLeaves, player, level, distance - 1, blockPos.below());

if(scannedLeaves.contains(blockPos)) {
return;
}
scannedLeaves.add(blockPos);

var blockState = level.getBlockState(blockPos);
if (!mod.isLeafBlock(blockState.getBlock())) {
return;
}

if (dropLeavesAsItems && (!player.isCreative() || mod.getConfiguration().isLootInCreative())) {
blockState.getBlock().playerDestroy(level, player, blockPos, blockState, level.getBlockEntity(blockPos), mod.getEmptyItemStack());
}
level.fallBlock(blockPos, !dropLeavesAsItems,
0, 0.5, 0,
(level.getRandom().nextDouble() - 0.5) * 0.4, 0, (level.getRandom().nextDouble() - 0.5) * 0.4);
level.removeBlock(blockPos, false);

fallLeaf(scannedLeaves, player, level, distance - 1, blockPos.north());
fallLeaf(scannedLeaves, player, level, distance - 1, blockPos.east());
fallLeaf(scannedLeaves, player, level, distance - 1, blockPos.south());
fallLeaf(scannedLeaves, player, level, distance - 1, blockPos.west());

fallLeaf(scannedLeaves, player, level, distance - 1, blockPos.above());
}

@NotNull
public static FallingAnimationTreeBreakingHandler getInstance(@NotNull FallingTreeCommon<?> mod, boolean dropLogsAsItems, boolean dropLeavesAsItems) {
return INSTANCE.computeIfAbsent(Map.entry(dropLogsAsItems, dropLeavesAsItems), key -> new FallingAnimationTreeBreakingHandler(mod, key.getKey(), key.getValue(), new LeafForceBreaker(mod)));
}
(level.getRandom().nextDouble() - 0.5) * 0.4, 0, (level.getRandom().nextDouble() - 0.5) * 0.4);

fallLeaf(scannedLeaves, player, level, 5, logBlockPos.below());
fallLeaf(scannedLeaves, player, level, 5, logBlockPos.north());
fallLeaf(scannedLeaves, player, level, 5, logBlockPos.east());
fallLeaf(scannedLeaves, player, level, 5, logBlockPos.south());
fallLeaf(scannedLeaves, player, level, 5, logBlockPos.west());
fallLeaf(scannedLeaves, player, level, 5, logBlockPos.above());

var isRemoved = level.removeBlock(logBlockPos, false);

return part.treePartType().isBreakable() && isRemoved ? 1 : 0;
})
.sum();

var toolDamage = toolHandler.getActualDamage(brokenCount) - 1;
if(toolDamage > 0){
tool.damage(toolDamage, player);
}

if(brokenCount >= toolHandler.getMaxBreakCount()){
leafForceBreaker.forceBreakDecayLeaves(player, tree, level);
}
return true;
}

private void fallLeaf(LinkedList<IBlockPos> scannedLeaves, @NotNull IPlayer player, @NotNull ILevel level, int distance, @NotNull IBlockPos blockPos){
if(!mod.getConfiguration().getTrees().isLeavesBreaking()){
return;
}
if(distance == 0){
return;
}

fallLeaf(scannedLeaves, player, level, distance - 1, blockPos.below());

if(scannedLeaves.contains(blockPos)){
return;
}
scannedLeaves.add(blockPos);

var blockState = level.getBlockState(blockPos);
if(!mod.isLeafBlock(blockState.getBlock())){
return;
}

if(dropLeavesAsItems && (!player.isCreative() || mod.getConfiguration().isLootInCreative())){
blockState.getBlock().playerDestroy(level, player, blockPos, blockState, level.getBlockEntity(blockPos), mod.getEmptyItemStack());
}
level.fallBlock(blockPos, !dropLeavesAsItems,
0, 0.5, 0,
(level.getRandom().nextDouble() - 0.5) * 0.4, 0, (level.getRandom().nextDouble() - 0.5) * 0.4);
level.removeBlock(blockPos, false);

fallLeaf(scannedLeaves, player, level, distance - 1, blockPos.north());
fallLeaf(scannedLeaves, player, level, distance - 1, blockPos.east());
fallLeaf(scannedLeaves, player, level, distance - 1, blockPos.south());
fallLeaf(scannedLeaves, player, level, distance - 1, blockPos.west());

fallLeaf(scannedLeaves, player, level, distance - 1, blockPos.above());
}

@NotNull
public static FallingAnimationTreeBreakingHandler getInstance(@NotNull FallingTreeCommon<?> mod, boolean dropLogsAsItems, boolean dropLeavesAsItems){
return INSTANCE.computeIfAbsent(Map.entry(dropLogsAsItems, dropLeavesAsItems), key -> new FallingAnimationTreeBreakingHandler(mod, key.getKey(), key.getValue(), new LeafForceBreaker(mod)));
}
}

0 comments on commit 22ddf43

Please sign in to comment.