diff --git a/common/src/main/java/fr/rakambda/fallingtree/common/config/ITreeConfiguration.java b/common/src/main/java/fr/rakambda/fallingtree/common/config/ITreeConfiguration.java index 1be48716..9e26e274 100644 --- a/common/src/main/java/fr/rakambda/fallingtree/common/config/ITreeConfiguration.java +++ b/common/src/main/java/fr/rakambda/fallingtree/common/config/ITreeConfiguration.java @@ -45,6 +45,8 @@ public interface ITreeConfiguration{ int getMaxSize(); + int getMaxLeafDistanceFromLog(); + @NotNull MaxSizeAction getMaxSizeAction(); diff --git a/common/src/main/java/fr/rakambda/fallingtree/common/config/proxy/TreeProxyConfiguration.java b/common/src/main/java/fr/rakambda/fallingtree/common/config/proxy/TreeProxyConfiguration.java index 8d823726..2595d6f2 100644 --- a/common/src/main/java/fr/rakambda/fallingtree/common/config/proxy/TreeProxyConfiguration.java +++ b/common/src/main/java/fr/rakambda/fallingtree/common/config/proxy/TreeProxyConfiguration.java @@ -97,6 +97,11 @@ public int getMaxSize(){ return delegate.getMaxSize(); } + @Override + public int getMaxLeafDistanceFromLog(){ + return delegate.getMaxLeafDistanceFromLog(); + } + @Override @NotNull public MaxSizeAction getMaxSizeAction(){ diff --git a/common/src/main/java/fr/rakambda/fallingtree/common/config/real/TreeConfiguration.java b/common/src/main/java/fr/rakambda/fallingtree/common/config/real/TreeConfiguration.java index f78abdb5..cc204a3d 100644 --- a/common/src/main/java/fr/rakambda/fallingtree/common/config/real/TreeConfiguration.java +++ b/common/src/main/java/fr/rakambda/fallingtree/common/config/real/TreeConfiguration.java @@ -47,6 +47,8 @@ public class TreeConfiguration implements ITreeConfiguration, IResettable{ @Expose private int maxSize = 100; @Expose + private int maxLeafDistanceFromLog = 15; + @Expose @NotNull private MaxSizeAction maxSizeAction = MaxSizeAction.ABORT; @Expose diff --git a/common/src/main/java/fr/rakambda/fallingtree/common/tree/TreePartType.java b/common/src/main/java/fr/rakambda/fallingtree/common/tree/TreePartType.java index b49119c3..e2ebd6c1 100644 --- a/common/src/main/java/fr/rakambda/fallingtree/common/tree/TreePartType.java +++ b/common/src/main/java/fr/rakambda/fallingtree/common/tree/TreePartType.java @@ -6,15 +6,17 @@ @Getter @RequiredArgsConstructor public enum TreePartType{ - LEAF(false), - LEAF_NEED_BREAK(true), - LOG(true), - NETHER_WART(true), - MANGROVE_ROOTS(true), - OTHER(false); + LEAF(false, true, false), + LEAF_NEED_BREAK(true, true, true), + LOG(true, false, true), + NETHER_WART(true, false, true), + MANGROVE_ROOTS(true, false, true), + OTHER(false, false, false); @Getter private static final TreePartType[] values = values(); private final boolean breakable; + private final boolean edge; + private final boolean includeInTree; } diff --git a/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/ToAnalyzePos.java b/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/ToAnalyzePos.java index a3ffd589..9fb4129a 100644 --- a/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/ToAnalyzePos.java +++ b/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/ToAnalyzePos.java @@ -14,7 +14,8 @@ public record ToAnalyzePos(@NotNull IPositionFetcher positionFetcher, @NotNull IBlockPos checkPos, @NotNull IBlock checkBlock, @NotNull TreePartType treePartType, - int sequence) + int sequence, + int sequenceSinceLastLog) implements Comparable{ @Override diff --git a/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/TreeBuilder.java b/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/TreeBuilder.java index 2c28dc6e..c1e0ff26 100644 --- a/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/TreeBuilder.java +++ b/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/TreeBuilder.java @@ -43,7 +43,7 @@ public Optional getTree(@NotNull IPlayer player, @NotNull ILevel level, @N var toAnalyzePos = new PriorityQueue(); var analyzedPos = new HashSet(); var tree = new Tree(level, originPos); - toAnalyzePos.add(new ToAnalyzePos(getFirstPositionFetcher(), originPos, originBlock, originPos, originBlock, TreePartType.LOG, 0)); + toAnalyzePos.add(new ToAnalyzePos(getFirstPositionFetcher(), originPos, originBlock, originPos, originBlock, TreePartType.LOG, 0, 0)); var boundingBoxSearch = getBoundingBoxSearch(originPos); var adjacentPredicate = getAdjacentPredicate(); @@ -53,13 +53,18 @@ public Optional getTree(@NotNull IPlayer player, @NotNull ILevel level, @N while(!toAnalyzePos.isEmpty()){ var analyzingPos = toAnalyzePos.remove(); - tree.addPart(analyzingPos.toTreePart()); + if(analyzingPos.toTreePart().treePartType().isIncludeInTree()){ + tree.addPart(analyzingPos.toTreePart()); + } analyzedPos.add(analyzingPos); if(tree.getSize() > maxScanSize){ log.debug("Tree at {} reached max scan size of {}", tree.getHitPos(), maxScanSize); throw new TreeTooBigException(); } + if(analyzingPos.treePartType().isEdge() && analyzingPos.sequenceSinceLastLog() >= mod.getConfiguration().getTrees().getMaxLeafDistanceFromLog()){ + continue; + } var potentialPositions = analyzingPos.positionFetcher().getPositions(level, originPos, analyzingPos); var nextPositions = filterPotentialPos(boundingBoxSearch, adjacentPredicate, level, originPos, originBlock, analyzingPos, potentialPositions, analyzedPos); @@ -134,9 +139,9 @@ private Predicate getBoundingBoxSearch(@NotNull IBlockPos originPos){ var maxZ = originPos.getZ() + radius; return pos -> minX <= pos.getX() - && maxX >= pos.getX() - && minZ <= pos.getZ() - && maxZ >= pos.getZ(); + && maxX >= pos.getX() + && minZ <= pos.getZ() + && maxZ >= pos.getZ(); } @NotNull @@ -194,6 +199,9 @@ private long getLeavesAround(@NotNull ILevel level, @NotNull IBlockPos blockPos) } private boolean shouldIncludeInChain(@NotNull Predicate boundingBoxSearch, @NotNull IBlockPos originPos, @NotNull IBlock originBlock, @NotNull ToAnalyzePos parent, @NotNull ToAnalyzePos check){ + if(parent.treePartType().isEdge() && !check.treePartType().isEdge()){ + return false; + } if(parent.treePartType() == TreePartType.LOG && isSameTree(originBlock, check) && boundingBoxSearch.test(check.checkPos())){ return true; } @@ -210,7 +218,7 @@ private boolean shouldIncludeInChain(@NotNull Predicate boundingBoxSe return true; } } - return check.treePartType() == TreePartType.LEAF_NEED_BREAK; + return check.treePartType().isEdge(); } private boolean isSameTree(@NotNull IBlock parentLogBlock, @NotNull ToAnalyzePos check){ diff --git a/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/position/AbovePositionFetcher.java b/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/position/AbovePositionFetcher.java index 9537391e..01817172 100644 --- a/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/position/AbovePositionFetcher.java +++ b/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/position/AbovePositionFetcher.java @@ -1,5 +1,6 @@ package fr.rakambda.fallingtree.common.tree.builder.position; +import fr.rakambda.fallingtree.common.tree.TreePartType; import fr.rakambda.fallingtree.common.tree.builder.ToAnalyzePos; import fr.rakambda.fallingtree.common.FallingTreeCommon; import fr.rakambda.fallingtree.common.wrapper.IBlockPos; @@ -33,7 +34,9 @@ public Collection getPositions(@NotNull ILevel level, @NotNull IBl return parentPos.betweenClosedStream(parentPos.above().north().east(), lowerPosProvider.apply(parentPos).south().west()) .map(checkPos -> { var checkBlock = level.getBlockState(checkPos).getBlock(); - return new ToAnalyzePos(positionFetcherSupplier.get(), parentPos, parentBlock, checkPos.immutable(), checkBlock, mod.getTreePart(checkBlock), parent.sequence() + 1); + var treePart = mod.getTreePart(checkBlock); + var logSequence = treePart == TreePartType.LOG ? 0 : (parent.sequenceSinceLastLog() + 1); + return new ToAnalyzePos(this, parentPos, parentBlock, checkPos.immutable(), checkBlock, treePart, parent.sequence() + 1, logSequence); }) .collect(toList()); } diff --git a/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/position/AboveYFetcher.java b/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/position/AboveYFetcher.java index 53be5e25..8819804d 100644 --- a/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/position/AboveYFetcher.java +++ b/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/position/AboveYFetcher.java @@ -1,5 +1,6 @@ package fr.rakambda.fallingtree.common.tree.builder.position; +import fr.rakambda.fallingtree.common.tree.TreePartType; import fr.rakambda.fallingtree.common.tree.builder.ToAnalyzePos; import fr.rakambda.fallingtree.common.FallingTreeCommon; import fr.rakambda.fallingtree.common.wrapper.IBlockPos; @@ -27,7 +28,9 @@ public Collection getPositions(@NotNull ILevel level, @NotNull IBl .filter(pos -> pos.getY() > originPos.getY()) .map(checkPos -> { var checkBlock = level.getBlockState(checkPos).getBlock(); - return new ToAnalyzePos(this, parentPos, parentBlock, checkPos.immutable(), checkBlock, mod.getTreePart(checkBlock), parent.sequence() + 1); + var treePart = mod.getTreePart(checkBlock); + var logSequence = treePart == TreePartType.LOG ? 0 : (parent.sequenceSinceLastLog() + 1); + return new ToAnalyzePos(this, parentPos, parentBlock, checkPos.immutable(), checkBlock, treePart, parent.sequence() + 1, logSequence); }) .collect(toList()); } diff --git a/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/position/BasicPositionFetcher.java b/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/position/BasicPositionFetcher.java index b408eb2c..cc40fabb 100644 --- a/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/position/BasicPositionFetcher.java +++ b/common/src/main/java/fr/rakambda/fallingtree/common/tree/builder/position/BasicPositionFetcher.java @@ -1,5 +1,6 @@ package fr.rakambda.fallingtree.common.tree.builder.position; +import fr.rakambda.fallingtree.common.tree.TreePartType; import fr.rakambda.fallingtree.common.tree.builder.ToAnalyzePos; import fr.rakambda.fallingtree.common.FallingTreeCommon; import fr.rakambda.fallingtree.common.wrapper.IBlockPos; @@ -26,7 +27,9 @@ public Collection getPositions(@NotNull ILevel level, @NotNull IBl return parentPos.betweenClosedStream(parentPos.above().north().east(), parentPos.below().south().west()) .map(checkPos -> { var checkBlock = level.getBlockState(checkPos).getBlock(); - return new ToAnalyzePos(this, parentPos, parentBlock, checkPos.immutable(), checkBlock, mod.getTreePart(checkBlock), parent.sequence() + 1); + var treePart = mod.getTreePart(checkBlock); + var logSequence = treePart == TreePartType.LOG ? 0 : (parent.sequenceSinceLastLog() + 1); + return new ToAnalyzePos(this, parentPos, parentBlock, checkPos.immutable(), checkBlock, treePart, parent.sequence() + 1, logSequence); }) .collect(toList()); } diff --git a/common/src/main/resources/assets/fallingtree/lang/en_us.json b/common/src/main/resources/assets/fallingtree/lang/en_us.json index 6892a773..23a8b599 100644 --- a/common/src/main/resources/assets/fallingtree/lang/en_us.json +++ b/common/src/main/resources/assets/fallingtree/lang/en_us.json @@ -34,6 +34,8 @@ "text.autoconfig.fallingtree.option.trees.maxSize.@Tooltip": "The maximum size of a tree. If there's more logs than this value max size action will be applied.", "text.autoconfig.fallingtree.option.trees.maxSizeAction": "Max size action", "text.autoconfig.fallingtree.option.trees.maxSizeAction.@Tooltip": "What to do when the max size of a tree is reached.\n\nABORT: Tree won't be cut.\nCUT: Tree will still be cut leaving some of it untouched.", + "text.autoconfig.fallingtree.option.trees.maxLeafDistanceFromLog": "Maximum leaf distance from log", + "text.autoconfig.fallingtree.option.trees.maxLeafDistanceFromLog.@Tooltip": "The maximum distance a leaf can be from the tree. This only affects scanning a tree.", "text.autoconfig.fallingtree.option.trees.breakOrder": "Break order", "text.autoconfig.fallingtree.option.trees.breakOrder.@Tooltip": "In what order logs are broken. This only makes sense if maxSize < maxScanSize.\n\nFURTHEST_FIRST: The furthest log will be broken first.\nCLOSEST_FIRST: The closest log will be broken first.\nLOWEST_FIRST: The lower log will be broken first.\n\nINFO: Only in INSTANTANEOUS mode.", "text.autoconfig.fallingtree.option.trees.minimumLeavesAroundRequired": "Minimum leaves around required", diff --git a/fabric/src/client/java/fr/rakambda/fallingtree/fabric/client/cloth/ClothConfigHook.java b/fabric/src/client/java/fr/rakambda/fallingtree/fabric/client/cloth/ClothConfigHook.java index 8943ed50..96173f88 100644 --- a/fabric/src/client/java/fr/rakambda/fallingtree/fabric/client/cloth/ClothConfigHook.java +++ b/fabric/src/client/java/fr/rakambda/fallingtree/fabric/client/cloth/ClothConfigHook.java @@ -156,6 +156,12 @@ private void fillTreesConfigScreen(@NotNull ConfigBuilder builder, @NotNull Tree .setTooltip(getTooltips("trees", "maxSizeAction")) .setSaveConsumer(config::setMaxSizeAction) .build(); + var maxLeafDistanceFromLogEntry = builder.entryBuilder() + .startIntField(translatable(getFieldName("trees", "maxLeafDistanceFromLog")), config.getMaxLeafDistanceFromLog()) + .setDefaultValue(15) + .setTooltip(getTooltips("trees", "maxLeafDistanceFromLog")) + .setSaveConsumer(config::setMaxLeafDistanceFromLog) + .build(); var breakOrderEntry = builder.entryBuilder() .startEnumSelector(translatable(getFieldName("trees", "breakOrder")), BreakOrder.class, config.getBreakOrder()) .setDefaultValue(BreakOrder.FURTHEST_FIRST) @@ -245,6 +251,7 @@ private void fillTreesConfigScreen(@NotNull ConfigBuilder builder, @NotNull Tree trees.addEntry(maxScanSizeEntry); trees.addEntry(maxSizeEntry); trees.addEntry(maxSizeActionEntry); + trees.addEntry(maxLeafDistanceFromLogEntry); trees.addEntry(breakOrderEntry); trees.addEntry(treeBreakingEntry); trees.addEntry(leavesBreakingEntry); diff --git a/forge/src/main/java/fr/rakambda/fallingtree/forge/client/cloth/ClothConfigHook.java b/forge/src/main/java/fr/rakambda/fallingtree/forge/client/cloth/ClothConfigHook.java index 7500f7d7..1b9438a3 100644 --- a/forge/src/main/java/fr/rakambda/fallingtree/forge/client/cloth/ClothConfigHook.java +++ b/forge/src/main/java/fr/rakambda/fallingtree/forge/client/cloth/ClothConfigHook.java @@ -156,6 +156,12 @@ private void fillTreesConfigScreen(@NotNull ConfigBuilder builder, @NotNull Tree .setTooltip(getTooltips("trees", "maxSizeAction")) .setSaveConsumer(config::setMaxSizeAction) .build(); + var maxLeafDistanceFromLogEntry = builder.entryBuilder() + .startIntField(translatable(getFieldName("trees", "maxLeafDistanceFromLog")), config.getMaxLeafDistanceFromLog()) + .setDefaultValue(15) + .setTooltip(getTooltips("trees", "maxLeafDistanceFromLog")) + .setSaveConsumer(config::setMaxLeafDistanceFromLog) + .build(); var breakOrderEntry = builder.entryBuilder() .startEnumSelector(translatable(getFieldName("trees", "breakOrder")), BreakOrder.class, config.getBreakOrder()) .setDefaultValue(BreakOrder.FURTHEST_FIRST) @@ -245,6 +251,7 @@ private void fillTreesConfigScreen(@NotNull ConfigBuilder builder, @NotNull Tree trees.addEntry(maxScanSizeEntry); trees.addEntry(maxSizeEntry); trees.addEntry(maxSizeActionEntry); + trees.addEntry(maxLeafDistanceFromLogEntry); trees.addEntry(breakOrderEntry); trees.addEntry(treeBreakingEntry); trees.addEntry(leavesBreakingEntry); diff --git a/wiki/Settings---Trees.asciidoc b/wiki/Settings---Trees.asciidoc index c3234334..94a1de23 100644 --- a/wiki/Settings---Trees.asciidoc +++ b/wiki/Settings---Trees.asciidoc @@ -82,6 +82,9 @@ NOTE: Only applied in `Instantaneous` breaking mode. - ABORT: Tree won't be cut. - CUT: Tree will still be cut leaving some of it untouched. +|Maximum leaf distance from log +|The maximum distance a leaf can be from the tree. This only affects scanning a tree. + |Max size order |In what order logs are broken.