Support latched tree felling

- Add a run hook controlling continued sneaking.
- Preserve latched runs when players release sneak.
This commit is contained in:
Brian Neumann-Fopiano
2026-09-28 07:03:58 -04:00
parent c706eab60f
commit 241260a762
3 changed files with 32 additions and 5 deletions
@@ -1,6 +1,10 @@
package art.arcane.iris.api.tree;
public interface TreeFellerRunHooks {
default boolean requiresSneaking() {
return true;
}
TreeFellerRunHooks NONE = new TreeFellerRunHooks() {
@Override
public void onActivationAccepted() {
@@ -219,7 +219,7 @@ public class TreeFellerSVC implements IrisService, IrisTreeFellerService {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void haltWhenSneakingStops(PlayerToggleSneakEvent event) {
if (!event.isSneaking()) {
runner.finishRuns(event.getPlayer().getUniqueId());
runner.finishSneakRuns(event.getPlayer().getUniqueId());
}
}
@@ -523,10 +523,15 @@ final class TreeFellingRunner {
}
private boolean isRunControlActive(FellingRun run, Player player) {
return player.isOnline()
&& player.getGameMode() == GameMode.SURVIVAL
&& player.isSneaking()
&& player.getWorld().equals(run.candidate.world());
try {
return player.isOnline()
&& player.getGameMode() == GameMode.SURVIVAL
&& (!run.runHooks.requiresSneaking() || player.isSneaking())
&& player.getWorld().equals(run.candidate.world());
} catch (RuntimeException error) {
IrisLogging.reportError("An Iris tree-feller integration control check failed.", error);
return false;
}
}
private boolean reserveLogCost(FellingRun run) {
@@ -622,6 +627,24 @@ final class TreeFellingRunner {
}
}
void finishSneakRuns(UUID playerId) {
Set<FellingRun> runs = service.activeRuns.get(playerId);
if (runs == null) {
return;
}
for (FellingRun run : List.copyOf(runs)) {
try {
if (!run.runHooks.requiresSneaking()) {
continue;
}
} catch (RuntimeException error) {
IrisLogging.reportError("An Iris tree-feller integration control check failed.", error);
}
run.abortReason = "halted";
finish(run);
}
}
private Map<ChunkPosition, List<TreeMarkerTraversal.Position>> groupByChunk(
List<TreeMarkerTraversal.Position> positions
) {