From 5c2e156392690162464410e3b4b811c0075f297d Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 10 Oct 2020 16:25:49 +0200 Subject: [PATCH] Ssome more cleanup --- .../unicopia/TreeTraverser.java | 209 ++++++++++-------- .../ability/EarthPonyStompAbility.java | 10 +- .../unicopia/util/PosHelper.java | 15 +- .../unicopia/util/RayTraceHelper.java | 118 +++++----- 4 files changed, 174 insertions(+), 178 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/TreeTraverser.java b/src/main/java/com/minelittlepony/unicopia/TreeTraverser.java index 8a0d93c6..4ef9645f 100644 --- a/src/main/java/com/minelittlepony/unicopia/TreeTraverser.java +++ b/src/main/java/com/minelittlepony/unicopia/TreeTraverser.java @@ -16,125 +16,138 @@ import net.minecraft.world.World; public class TreeTraverser { - public static void removeTree(World w, BlockPos pos) { - BlockState log = w.getBlockState(pos); + public static class Remover { + /** + * Removes the tree located at the given position. + */ + public static void removeTree(World w, BlockPos pos) { + BlockState log = w.getBlockState(pos); - int size = measureTree(w, log, pos); - - if (size > 0) { - removeTreePart(w, log, ascendTrunk(new HashSet(), w, pos, log, 0).get(), 0); - } - } - - private static void removeTreePart(World w, BlockState log, BlockPos pos, int level) { - if (level < 10 && isWoodOrLeaf(w, log, pos)) { - if (level < 5) { - w.breakBlock(pos, true); - } else { - Block.dropStacks(w.getBlockState(pos), w, pos); - w.setBlockState(pos, Blocks.AIR.getDefaultState(), 3); + if (Measurer.measureTree(w, log, pos) > 0) { + removeTreePart(w, log, Ascender.ascendTrunk(new HashSet(), w, pos, log, 0).get(), 0); } + } - PosHelper.all(pos, p -> { - removeTreePart(w, log, p, level + 1); - }, Direction.UP, Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST); + private static void removeTreePart(World w, BlockState log, BlockPos pos, int level) { + if (level < 10 && isWoodOrLeaf(w, log, pos)) { + breakBlock(w, pos, level < 5); + PosHelper.all(pos, p -> { + removeTreePart(w, log, p, level + 1); + }, Direction.UP, Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST); + } } } - private static Optional ascendTrunk(Set done, World w, BlockPos pos, BlockState log, int level) { - if (level < 3 && !done.contains(pos)) { - done.add(pos); - - BlockPos.Mutable result = new BlockPos.Mutable(); - result.set(ascendTree(w, log, pos, true)); - - PosHelper.all(pos, p -> { - if (variantAndBlockEquals(w.getBlockState(pos.east()), log)) { - ascendTrunk(done, w, pos.east(), log, level + 1).filter(a -> a.getY() > result.getY()).ifPresent(result::set); + public static class Ascender { + /** + * Locates the top of the tree's trunk. Usually the point where wood meets leaves. + */ + public static BlockPos ascendTree(World w, BlockState log, BlockPos pos, boolean remove) { + int breaks = 0; + while (variantAndBlockEquals(w.getBlockState(pos.up()), log)) { + if (PosHelper.any(pos, p -> isLeaves(w.getBlockState(p), log), Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST)) { + break; } - }, Direction.EAST, Direction.WEST, Direction.NORTH, Direction.SOUTH); - done.add(result.toImmutable()); - return Optional.of(result.toImmutable()); - } - return Optional.of(pos); - } - - public static BlockPos ascendTree(World w, BlockState log, BlockPos pos, boolean remove) { - int breaks = 0; - BlockState state; - while (variantAndBlockEquals(w.getBlockState(pos.up()), log)) { - if (PosHelper.some(pos, p -> isLeaves(w.getBlockState(p), log), Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST)) { - break; - } - - if (remove) { - if (breaks < 10) { - w.breakBlock(pos, true); - } else { - state = w.getBlockState(pos); - Block.dropStacks(state, w, pos); - w.setBlockState(pos, Blocks.AIR.getDefaultState(), 3); + if (remove) { + breakBlock(w, pos, breaks++ < 10); } - breaks++; + pos = pos.up(); } - pos = pos.up(); + return pos; + } + + static Optional ascendTrunk(Set done, World w, BlockPos pos, BlockState log, int level) { + if (level < 3 && !done.contains(pos)) { + done.add(pos); + + BlockPos.Mutable result = new BlockPos.Mutable(); + result.set(ascendTree(w, log, pos, true)); + + PosHelper.all(pos, p -> { + if (variantAndBlockEquals(w.getBlockState(pos.east()), log)) { + ascendTrunk(done, w, pos.east(), log, level + 1).filter(a -> a.getY() > result.getY()).ifPresent(result::set); + } + }, Direction.EAST, Direction.WEST, Direction.NORTH, Direction.SOUTH); + + done.add(result.toImmutable()); + return Optional.of(result.toImmutable()); + } + return Optional.of(pos); } - return pos; } - public static Optional descendTree(World w, BlockState log, BlockPos pos) { - return descendTreePart(new HashSet(), w, log, new BlockPos.Mutable(pos.getX(), pos.getY(), pos.getZ())); + public static class Descender { + /** + * Recursively locates the base of the tree. + */ + public static Optional descendTree(World w, BlockState log, BlockPos pos) { + return descendTreePart(new HashSet(), w, log, new BlockPos.Mutable(pos.getX(), pos.getY(), pos.getZ())); + } + + private static Optional descendTreePart(Set done, World w, BlockState log, BlockPos.Mutable pos) { + if (done.contains(pos) || !variantAndBlockEquals(w.getBlockState(pos), log)) { + return Optional.empty(); + } + + done.add(pos.toImmutable()); + while (variantAndBlockEquals(w.getBlockState(pos.down()), log)) { + done.add(pos.move(Direction.DOWN).toImmutable()); + } + + PosHelper.all(pos.toImmutable(), p -> { + descendTreePart(done, w, log, new BlockPos.Mutable(p.getX(), p.getY(), p.getZ())).filter(a -> a.getY() < pos.getY()).ifPresent(pos::set); + }, Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST); + + done.add(pos.toImmutable()); + return Optional.of(pos.toImmutable()); + } } - private static Optional descendTreePart(Set done, World w, BlockState log, BlockPos.Mutable pos) { - if (done.contains(pos) || !variantAndBlockEquals(w.getBlockState(pos), log)) { - return Optional.empty(); + public static class Measurer { + /** + * Counts the number of logs and leaves present in the targeted tree. + */ + public static int measureTree(World w, BlockState log, BlockPos pos) { + Set logs = new HashSet<>(); + Set leaves = new HashSet<>(); + + countParts(logs, leaves, w, log, pos); + + return logs.size() <= (leaves.size() / 2) ? logs.size() + leaves.size() : 0; } - done.add(pos.toImmutable()); - while (variantAndBlockEquals(w.getBlockState(pos.down()), log)) { - done.add(pos.move(Direction.DOWN).toImmutable()); + private static void countParts(Set logs, Set leaves, World w, BlockState log, BlockPos pos) { + if (logs.contains(pos) || leaves.contains(pos)) { + return; + } + + BlockState state = w.getBlockState(pos); + boolean yay = false; + + if (isLeaves(state, log) && !state.get(LeavesBlock.PERSISTENT)) { + leaves.add(pos); + yay = true; + } else if (variantAndBlockEquals(state, log)) { + logs.add(pos); + yay = true; + } + + if (yay) { + PosHelper.all(pos, p -> { + countParts(logs, leaves, w, log, p); + }, Direction.UP, Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST); + } } - - PosHelper.all(pos.toImmutable(), p -> { - descendTreePart(done, w, log, new BlockPos.Mutable(p.getX(), p.getY(), p.getZ())).filter(a -> a.getY() < pos.getY()).ifPresent(pos::set); - }, Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST); - - done.add(pos.toImmutable()); - return Optional.of(pos.toImmutable()); } - public static int measureTree(World w, BlockState log, BlockPos pos) { - Set logs = new HashSet<>(); - Set leaves = new HashSet<>(); - - countParts(logs, leaves, w, log, pos); - - return logs.size() <= (leaves.size() / 2) ? logs.size() + leaves.size() : 0; - } - - private static void countParts(Set logs, Set leaves, World w, BlockState log, BlockPos pos) { - if (logs.contains(pos) || leaves.contains(pos)) { - return; - } - - BlockState state = w.getBlockState(pos); - boolean yay = false; - - if (isLeaves(state, log) && !state.get(LeavesBlock.PERSISTENT)) { - leaves.add(pos); - yay = true; - } else if (variantAndBlockEquals(state, log)) { - logs.add(pos); - yay = true; - } - - if (yay) { - PosHelper.all(pos, p -> { - countParts(logs, leaves, w, log, p); - }, Direction.UP, Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST); + private static void breakBlock(World w, BlockPos pos, boolean destroy) { + if (destroy) { + w.breakBlock(pos, true); + } else { + Block.dropStacks(w.getBlockState(pos), w, pos); + w.setBlockState(pos, Blocks.AIR.getDefaultState(), 3); } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java index cb762815..52495dff 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java @@ -81,8 +81,8 @@ public class EarthPonyStompAbility implements Ability { BlockState state = player.getWorld().getBlockState(pos); if (state.getBlock().isIn(BlockTags.LOGS)) { - pos = TreeTraverser.descendTree(player.getWorld(), state, pos).get(); - if (TreeTraverser.measureTree(player.getWorld(), state, pos) > 0) { + pos = TreeTraverser.Descender.descendTree(player.getWorld(), state, pos).get(); + if (TreeTraverser.Measurer.measureTree(player.getWorld(), state, pos) > 0) { return new Multi(pos, 1); } } @@ -164,7 +164,7 @@ public class EarthPonyStompAbility implements Ability { if (harmed || player.world.random.nextInt(5) == 0) { if (!harmed || player.world.random.nextInt(30) == 0) { - TreeTraverser.removeTree(player.world, data.pos()); + TreeTraverser.Remover.removeTree(player.world, data.pos()); } iplayer.subtractEnergyCost(3); @@ -223,7 +223,7 @@ public class EarthPonyStompAbility implements Ability { private int dropApples(World w, BlockPos pos) { BlockState log = w.getBlockState(pos); - int size = TreeTraverser.measureTree(w, log, pos); + int size = TreeTraverser.Measurer.measureTree(w, log, pos); if (size > 0) { List capturedDrops = Lists.newArrayList(); @@ -244,7 +244,7 @@ public class EarthPonyStompAbility implements Ability { private static void dropApplesPart(List drops, List done, World w, BlockState log, BlockPos pos, int level) { if (!done.contains(pos)) { done.add(pos); - pos = TreeTraverser.ascendTree(w, log, pos, false); + pos = TreeTraverser.Ascender.ascendTree(w, log, pos, false); if (level < 10 && TreeTraverser.isWoodOrLeaf(w, log, pos)) { BlockState state = w.getBlockState(pos); diff --git a/src/main/java/com/minelittlepony/unicopia/util/PosHelper.java b/src/main/java/com/minelittlepony/unicopia/util/PosHelper.java index 41af8304..f23222f8 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/PosHelper.java +++ b/src/main/java/com/minelittlepony/unicopia/util/PosHelper.java @@ -1,7 +1,6 @@ package com.minelittlepony.unicopia.util; import java.util.Iterator; -import java.util.List; import java.util.Spliterator; import java.util.Spliterators.AbstractSpliterator; import java.util.function.Consumer; @@ -39,7 +38,7 @@ public interface PosHelper { } } - static boolean some(BlockPos origin, Predicate consumer, Direction... directions) { + static boolean any(BlockPos origin, Predicate consumer, Direction... directions) { for (Direction facing : directions) { if (consumer.test(origin.offset(facing))) { return true; @@ -49,17 +48,15 @@ public interface PosHelper { } static Stream adjacentNeighbours(BlockPos origin) { - BlockPos.Mutable pos = new BlockPos.Mutable(origin.getX(), origin.getY(), origin.getZ()); - List directions = Lists.newArrayList(Direction.values()); - Iterator iter = directions.iterator(); - return StreamSupport.stream(new AbstractSpliterator(directions.size(), Spliterator.SIZED) { + return StreamSupport.stream(new AbstractSpliterator(Direction.values().length, Spliterator.SIZED) { + private final BlockPos.Mutable pos = new BlockPos.Mutable(); + private final Iterator iter = Lists.newArrayList(Direction.values()).iterator(); + @Override public boolean tryAdvance(Consumer consumer) { if (iter.hasNext()) { Direction next = iter.next(); - - pos.set(origin.getX() + next.getOffsetX(), origin.getY() + next.getOffsetY(), origin.getZ() + next.getOffsetZ()); - consumer.accept(pos); + consumer.accept(pos.set(origin.getX() + next.getOffsetX(), origin.getY() + next.getOffsetY(), origin.getZ() + next.getOffsetZ())); return true; } return false; diff --git a/src/main/java/com/minelittlepony/unicopia/util/RayTraceHelper.java b/src/main/java/com/minelittlepony/unicopia/util/RayTraceHelper.java index a4c4c699..587567fc 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/RayTraceHelper.java +++ b/src/main/java/com/minelittlepony/unicopia/util/RayTraceHelper.java @@ -1,6 +1,5 @@ package com.minelittlepony.unicopia.util; -import java.util.List; import java.util.Optional; import java.util.function.Consumer; import java.util.function.Predicate; @@ -15,82 +14,83 @@ import net.minecraft.util.hit.HitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; import net.minecraft.util.math.Vec3d; -import net.minecraft.world.RayTraceContext; public class RayTraceHelper { - public static Optional findEntity(Entity e, double distance) { - return doTrace(e, distance, 1).getEntity(); - } - - public static Optional findEntity(Entity e, double distance, float partialTick, Predicate predicate) { - return doTrace(e, distance, partialTick, EntityPredicates.EXCEPT_SPECTATOR.and(predicate)).getEntity(); - } - - public static Trace doTrace(Entity e, double distance, float partialTick) { - return doTrace(e, distance, partialTick, EntityPredicates.EXCEPT_SPECTATOR); + public static Optional findEntity(Entity e, double distance, float tickDelta, Predicate predicate) { + return doTrace(e, distance, tickDelta, EntityPredicates.EXCEPT_SPECTATOR.and(predicate)).getEntity(); } /** - * Performs a ray trace from the given entity and returns a result for the first Entity that passing the given predicate or block that the ray intercepts. - *

+ * Performs a ray trace from the given entity and returns + * a result for the first Entity or block that the ray intercepts. * * - * @param e Entity to start from - * @param distance Maximum distance - * @param partialTick Client partial ticks - * @param predicate Predicate test to filter entities + * @param e Entity to start from + * @param distance Maximum distance + * @param tickDelta Client partial ticks * - * @return A OptionalHit describing what was found. + * @return A Trace describing what was found. */ - public static Trace doTrace(Entity e, double distance, float partialTick, Predicate predicate) { - HitResult tracedBlock = traceBlocks(e, distance, partialTick, false); + public static Trace doTrace(Entity e, double distance, float tickDelta) { + return doTrace(e, distance, tickDelta, EntityPredicates.EXCEPT_SPECTATOR); + } - double totalTraceDistance = distance; + /** + * Performs a ray trace from the given entity and returns + * a result for the first Entity that passes the given predicate + * or block that the ray intercepts. + * + * + * @param e Entity to start from + * @param distance Maximum distance + * @param tickDelta Client partial ticks + * @param predicate Predicate test to filter entities + * + * @return A Trace describing what was found. + */ + public static Trace doTrace(Entity e, double distance, float tickDelta, Predicate predicate) { + HitResult tracedBlock = e.rayTrace(distance, tickDelta, false); - Vec3d pos = e.getCameraPosVec(partialTick); + final Vec3d start = e.getCameraPosVec(tickDelta); - if (tracedBlock != null) { - totalTraceDistance = tracedBlock.getPos().distanceTo(pos); - } + final double totalTraceDistance = tracedBlock == null ? distance : tracedBlock.getPos().distanceTo(start); - Vec3d look = e.getRotationVec(partialTick); - Vec3d ray = pos.add(look.multiply(distance)); + final Vec3d ray = e.getRotationVec(tickDelta).multiply(distance); + final Vec3d end = start.add(ray); Vec3d hit = null; Entity pointedEntity = null; - List entitiesWithinRange = e.world.getOtherEntities(e, e.getBoundingBox() - .expand(look.x * distance, look.y * distance, look.z * distance) - .expand(1, 1, 1), predicate); double traceDistance = totalTraceDistance; - for (Entity entity : entitiesWithinRange) { - if (entity.collides()) { - Box entityAABB = entity.getBoundingBox().expand(entity.getTargetingMargin()); + for (Entity entity : e.world.getOtherEntities(e, + e.getBoundingBox().expand(ray.x + 1, ray.y + 1, ray.z + 1), + predicate.and(Entity::collides) + )) { + Box entityAABB = entity.getBoundingBox().expand(entity.getTargetingMargin()); - Optional intercept = entityAABB.rayTrace(pos, ray); + Optional intercept = entityAABB.rayTrace(start, end); - if (entityAABB.contains(pos)) { - if (traceDistance <= 0) { - pointedEntity = entity; - hit = intercept.orElse(null); - traceDistance = 0; - } - } else if (intercept.isPresent()) { - Vec3d inter = intercept.get(); - double distanceToHit = pos.distanceTo(inter); + if (entityAABB.contains(start)) { + if (traceDistance <= 0) { + pointedEntity = entity; + hit = intercept.orElse(null); + traceDistance = 0; + } + } else if (intercept.isPresent()) { + Vec3d inter = intercept.get(); + double distanceToHit = start.distanceTo(inter); - if (distanceToHit < traceDistance || traceDistance == 0) { - if (entity.getRootVehicle() == e.getRootVehicle()) { - if (traceDistance == 0) { - pointedEntity = entity; - hit = inter; - } - } else { + if (distanceToHit < traceDistance || traceDistance == 0) { + if (entity.getRootVehicle() == e.getRootVehicle()) { + if (traceDistance == 0) { pointedEntity = entity; hit = inter; - traceDistance = distanceToHit; } + } else { + pointedEntity = entity; + hit = inter; + traceDistance = distanceToHit; } } } @@ -103,20 +103,6 @@ public class RayTraceHelper { return new Trace(tracedBlock); } - /** - * Server-available version of Entity.rayTrace - */ - public static HitResult traceBlocks(Entity e, double maxDistance, float tickDelta, boolean includeFluids) { - Vec3d start = e.getCameraPosVec(tickDelta); - Vec3d end = e.getRotationVec(tickDelta).multiply(maxDistance).add(start); - - return e.world.rayTrace(new RayTraceContext(start, end, - RayTraceContext.ShapeType.OUTLINE, - includeFluids ? RayTraceContext.FluidHandling.ANY : RayTraceContext.FluidHandling.NONE, - e) - ); - } - public static class Trace { @Nullable private final HitResult result;