mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-24 05:47:59 +01:00
Ssome more cleanup
This commit is contained in:
parent
312afe3d46
commit
5c2e156392
4 changed files with 174 additions and 178 deletions
|
@ -16,33 +16,49 @@ import net.minecraft.world.World;
|
|||
|
||||
public class TreeTraverser {
|
||||
|
||||
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<BlockPos>(), w, pos, log, 0).get(), 0);
|
||||
if (Measurer.measureTree(w, log, pos) > 0) {
|
||||
removeTreePart(w, log, Ascender.ascendTrunk(new HashSet<BlockPos>(), 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);
|
||||
}
|
||||
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<BlockPos> ascendTrunk(Set<BlockPos> done, World w, BlockPos pos, BlockState log, int level) {
|
||||
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;
|
||||
}
|
||||
|
||||
if (remove) {
|
||||
breakBlock(w, pos, breaks++ < 10);
|
||||
}
|
||||
pos = pos.up();
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
static Optional<BlockPos> ascendTrunk(Set<BlockPos> done, World w, BlockPos pos, BlockState log, int level) {
|
||||
if (level < 3 && !done.contains(pos)) {
|
||||
done.add(pos);
|
||||
|
||||
|
@ -60,30 +76,12 @@ public class TreeTraverser {
|
|||
}
|
||||
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);
|
||||
}
|
||||
breaks++;
|
||||
}
|
||||
pos = pos.up();
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
public static class Descender {
|
||||
/**
|
||||
* Recursively locates the base of the tree.
|
||||
*/
|
||||
public static Optional<BlockPos> descendTree(World w, BlockState log, BlockPos pos) {
|
||||
return descendTreePart(new HashSet<BlockPos>(), w, log, new BlockPos.Mutable(pos.getX(), pos.getY(), pos.getZ()));
|
||||
}
|
||||
|
@ -105,7 +103,12 @@ public class TreeTraverser {
|
|||
done.add(pos.toImmutable());
|
||||
return Optional.of(pos.toImmutable());
|
||||
}
|
||||
}
|
||||
|
||||
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<BlockPos> logs = new HashSet<>();
|
||||
Set<BlockPos> leaves = new HashSet<>();
|
||||
|
@ -137,6 +140,16 @@ public class TreeTraverser {
|
|||
}, 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);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isWoodOrLeaf(World w, BlockState log, BlockPos pos) {
|
||||
BlockState state = w.getBlockState(pos);
|
||||
|
|
|
@ -81,8 +81,8 @@ public class EarthPonyStompAbility implements Ability<Multi> {
|
|||
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<Multi> {
|
|||
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<Multi> {
|
|||
|
||||
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<ItemEntity> capturedDrops = Lists.newArrayList();
|
||||
|
@ -244,7 +244,7 @@ public class EarthPonyStompAbility implements Ability<Multi> {
|
|||
private static void dropApplesPart(List<ItemEntity> drops, List<BlockPos> 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);
|
||||
|
||||
|
|
|
@ -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<BlockPos> consumer, Direction... directions) {
|
||||
static boolean any(BlockPos origin, Predicate<BlockPos> consumer, Direction... directions) {
|
||||
for (Direction facing : directions) {
|
||||
if (consumer.test(origin.offset(facing))) {
|
||||
return true;
|
||||
|
@ -49,17 +48,15 @@ public interface PosHelper {
|
|||
}
|
||||
|
||||
static Stream<BlockPos> adjacentNeighbours(BlockPos origin) {
|
||||
BlockPos.Mutable pos = new BlockPos.Mutable(origin.getX(), origin.getY(), origin.getZ());
|
||||
List<Direction> directions = Lists.newArrayList(Direction.values());
|
||||
Iterator<Direction> iter = directions.iterator();
|
||||
return StreamSupport.stream(new AbstractSpliterator<BlockPos>(directions.size(), Spliterator.SIZED) {
|
||||
return StreamSupport.stream(new AbstractSpliterator<BlockPos>(Direction.values().length, Spliterator.SIZED) {
|
||||
private final BlockPos.Mutable pos = new BlockPos.Mutable();
|
||||
private final Iterator<Direction> iter = Lists.newArrayList(Direction.values()).iterator();
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(Consumer<? super BlockPos> 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;
|
||||
|
|
|
@ -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,62 +14,64 @@ 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 <T extends Entity> Optional<T> findEntity(Entity e, double distance) {
|
||||
return doTrace(e, distance, 1).getEntity();
|
||||
}
|
||||
|
||||
public static <T extends Entity> Optional<T> findEntity(Entity e, double distance, float partialTick, Predicate<Entity> 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 <T extends Entity> Optional<T> findEntity(Entity e, double distance, float tickDelta, Predicate<Entity> 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.
|
||||
* <p>
|
||||
* 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 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<Entity> predicate) {
|
||||
HitResult tracedBlock = traceBlocks(e, distance, partialTick, false);
|
||||
|
||||
double totalTraceDistance = distance;
|
||||
|
||||
Vec3d pos = e.getCameraPosVec(partialTick);
|
||||
|
||||
if (tracedBlock != null) {
|
||||
totalTraceDistance = tracedBlock.getPos().distanceTo(pos);
|
||||
public static Trace doTrace(Entity e, double distance, float tickDelta) {
|
||||
return doTrace(e, distance, tickDelta, EntityPredicates.EXCEPT_SPECTATOR);
|
||||
}
|
||||
|
||||
Vec3d look = e.getRotationVec(partialTick);
|
||||
Vec3d ray = pos.add(look.multiply(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<Entity> predicate) {
|
||||
HitResult tracedBlock = e.rayTrace(distance, tickDelta, false);
|
||||
|
||||
final Vec3d start = e.getCameraPosVec(tickDelta);
|
||||
|
||||
final double totalTraceDistance = tracedBlock == null ? distance : tracedBlock.getPos().distanceTo(start);
|
||||
|
||||
final Vec3d ray = e.getRotationVec(tickDelta).multiply(distance);
|
||||
final Vec3d end = start.add(ray);
|
||||
|
||||
Vec3d hit = null;
|
||||
Entity pointedEntity = null;
|
||||
List<Entity> 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()) {
|
||||
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<Vec3d> intercept = entityAABB.rayTrace(pos, ray);
|
||||
Optional<Vec3d> intercept = entityAABB.rayTrace(start, end);
|
||||
|
||||
if (entityAABB.contains(pos)) {
|
||||
if (entityAABB.contains(start)) {
|
||||
if (traceDistance <= 0) {
|
||||
pointedEntity = entity;
|
||||
hit = intercept.orElse(null);
|
||||
|
@ -78,7 +79,7 @@ public class RayTraceHelper {
|
|||
}
|
||||
} else if (intercept.isPresent()) {
|
||||
Vec3d inter = intercept.get();
|
||||
double distanceToHit = pos.distanceTo(inter);
|
||||
double distanceToHit = start.distanceTo(inter);
|
||||
|
||||
if (distanceToHit < traceDistance || traceDistance == 0) {
|
||||
if (entity.getRootVehicle() == e.getRootVehicle()) {
|
||||
|
@ -94,7 +95,6 @@ public class RayTraceHelper {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pointedEntity != null && (traceDistance < totalTraceDistance || tracedBlock == null)) {
|
||||
return new Trace(new EntityHitResult(pointedEntity, hit));
|
||||
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue