Optimise findFreePosition
Ghasts teleporting can perform many voxelshape operations. We can reduce the number of voxelshape operations and use more efficient ones at the same time.
This commit is contained in:
@@ -24,6 +24,8 @@ import net.minecraft.world.level.material.Fluids;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.phys.shapes.BooleanOp;
|
||||
import net.minecraft.world.phys.shapes.Shapes;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
@@ -34,6 +36,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@Mixin(Level.class)
|
||||
@@ -91,6 +94,7 @@ public abstract class LevelMixin implements CollisionLevel, CollisionEntityGette
|
||||
* @author Spottedleaf
|
||||
*/
|
||||
@Overwrite
|
||||
@Override
|
||||
public List<Entity> getEntities(final Entity entity, final AABB boundingBox, final Predicate<? super Entity> predicate) {
|
||||
this.getProfiler().incrementCounter("getEntities");
|
||||
final List<Entity> ret = new ArrayList<>();
|
||||
@@ -171,7 +175,7 @@ public abstract class LevelMixin implements CollisionLevel, CollisionEntityGette
|
||||
* @author Spottedleaf
|
||||
*/
|
||||
@Override
|
||||
public <T extends Entity> List<T> getEntitiesOfClass(final Class<T> entityClass, final AABB boundingBox, final Predicate<? super T> predicate) {
|
||||
public final <T extends Entity> List<T> getEntitiesOfClass(final Class<T> entityClass, final AABB boundingBox, final Predicate<? super T> predicate) {
|
||||
this.getProfiler().incrementCounter("getEntities");
|
||||
final List<T> ret = new ArrayList<>();
|
||||
|
||||
@@ -185,7 +189,7 @@ public abstract class LevelMixin implements CollisionLevel, CollisionEntityGette
|
||||
* @author Spottedleaf
|
||||
*/
|
||||
@Override
|
||||
public List<Entity> getHardCollidingEntities(final Entity entity, final AABB box, final Predicate<? super Entity> predicate) {
|
||||
public final List<Entity> getHardCollidingEntities(final Entity entity, final AABB box, final Predicate<? super Entity> predicate) {
|
||||
this.getProfiler().incrementCounter("getEntities");
|
||||
final List<Entity> ret = new ArrayList<>();
|
||||
|
||||
@@ -200,7 +204,7 @@ public abstract class LevelMixin implements CollisionLevel, CollisionEntityGette
|
||||
* @author Spottedleaf
|
||||
*/
|
||||
@Override
|
||||
public boolean isUnobstructed(final Entity entity) {
|
||||
public final boolean isUnobstructed(final Entity entity) {
|
||||
final AABB boundingBox = entity.getBoundingBox();
|
||||
if (CollisionUtil.isEmpty(boundingBox)) {
|
||||
return false;
|
||||
@@ -370,7 +374,7 @@ public abstract class LevelMixin implements CollisionLevel, CollisionEntityGette
|
||||
* @author Spottedleaf
|
||||
*/
|
||||
@Override
|
||||
public BlockHitResult clip(final ClipContext clipContext) {
|
||||
public final BlockHitResult clip(final ClipContext clipContext) {
|
||||
// can only do this in this class, as not everything that implements BlockGetter can retrieve chunks
|
||||
return fastClip(clipContext.getFrom(), clipContext.getTo(), (Level)(Object)this, clipContext);
|
||||
}
|
||||
@@ -402,4 +406,66 @@ public abstract class LevelMixin implements CollisionLevel, CollisionEntityGette
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private static VoxelShape inflateAABBToVoxel(final AABB aabb, final double x, final double y, final double z) {
|
||||
return Shapes.create(
|
||||
aabb.minX - x,
|
||||
aabb.minY - y,
|
||||
aabb.minZ - z,
|
||||
|
||||
aabb.maxX + x,
|
||||
aabb.maxY + y,
|
||||
aabb.maxZ + z
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @reason Use optimised merge strategy, avoid streams
|
||||
* @author Spottedleaf
|
||||
*/
|
||||
@Override
|
||||
public final Optional<Vec3> findFreePosition(final Entity entity, final VoxelShape boundsShape, final Vec3 fromPosition,
|
||||
final double rangeX, final double rangeY, final double rangeZ) {
|
||||
if (boundsShape.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
final double expandByX = rangeX * 0.5;
|
||||
final double expandByY = rangeY * 0.5;
|
||||
final double expandByZ = rangeZ * 0.5;
|
||||
|
||||
// note: it is useless to look at shapes outside of range / 2.0
|
||||
final AABB collectionVolume = boundsShape.bounds().inflate(expandByX, expandByY, expandByZ);
|
||||
|
||||
final List<AABB> aabbs = new ArrayList<>();
|
||||
final List<VoxelShape> voxels = new ArrayList<>();
|
||||
|
||||
CollisionUtil.getCollisionsForBlocksOrWorldBorder(
|
||||
(Level)(Object)this, entity, collectionVolume, voxels, aabbs,
|
||||
CollisionUtil.COLLISION_FLAG_CHECK_BORDER,
|
||||
null
|
||||
);
|
||||
|
||||
// push voxels into aabbs
|
||||
for (int i = 0, len = voxels.size(); i < len; ++i) {
|
||||
aabbs.addAll(voxels.get(i).toAabbs());
|
||||
}
|
||||
|
||||
// expand AABBs
|
||||
final VoxelShape first = aabbs.isEmpty() ? Shapes.empty() : inflateAABBToVoxel(aabbs.get(0), expandByX, expandByY, expandByZ);
|
||||
final VoxelShape[] rest = new VoxelShape[Math.max(0, aabbs.size() - 1)];
|
||||
|
||||
for (int i = 1, len = aabbs.size(); i < len; ++i) {
|
||||
rest[i - 1] = inflateAABBToVoxel(aabbs.get(i), expandByX, expandByY, expandByZ);
|
||||
}
|
||||
|
||||
// use optimized join
|
||||
final VoxelShape joined = Shapes.or(first, rest);
|
||||
|
||||
// find free space
|
||||
final VoxelShape freeSpace = Shapes.join(boundsShape, joined, BooleanOp.ONLY_FIRST);
|
||||
|
||||
return freeSpace.closestPointTo(fromPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import it.unimi.dsi.fastutil.doubles.DoubleList;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
@@ -31,6 +32,7 @@ import org.spongepowered.asm.mixin.Unique;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Mixin(VoxelShape.class)
|
||||
public abstract class VoxelShapeMixin implements CollisionVoxelShape {
|
||||
@@ -711,4 +713,34 @@ public abstract class VoxelShapeMixin implements CollisionVoxelShape {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @reason Use AABBs cache
|
||||
* @author Spottedleaf
|
||||
*/
|
||||
@Overwrite
|
||||
public Optional<Vec3> closestPointTo(final Vec3 point) {
|
||||
if (this.isEmpty) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Vec3 ret = null;
|
||||
double retDistance = Double.MAX_VALUE;
|
||||
|
||||
final List<AABB> aabbs = this.toAabbs();
|
||||
for (int i = 0, len = aabbs.size(); i < len; ++i) {
|
||||
final AABB aabb = aabbs.get(i);
|
||||
final double x = Mth.clamp(point.x, aabb.minX, aabb.maxX);
|
||||
final double y = Mth.clamp(point.y, aabb.minY, aabb.maxY);
|
||||
final double z = Mth.clamp(point.z, aabb.minZ, aabb.maxZ);
|
||||
|
||||
double dist = point.distanceToSqr(x, y, z);
|
||||
if (dist < retDistance) {
|
||||
ret = new Vec3(x, y, z);
|
||||
retDistance = dist;
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.ofNullable(ret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,17 @@
|
||||
package ca.spottedleaf.moonrise.mixin.util_threading_detector;
|
||||
|
||||
import ca.spottedleaf.concurrentutil.util.ConcurrentUtil;
|
||||
import net.minecraft.util.ThreadingDetector;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@Mixin(ThreadingDetector.class)
|
||||
public abstract class ThreadingDetectorMixin {
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private String name;
|
||||
|
||||
|
||||
@Unique
|
||||
private static final ReentrantLock CANT_USE_NULL_IN_NEW_REDIRECT_MIXIN_WHAT_THE_FUCK_REENTRANTLOCK = new ReentrantLock();
|
||||
|
||||
@@ -57,38 +48,17 @@ public abstract class ThreadingDetectorMixin {
|
||||
return CANT_USE_NULL_IN_NEW_REDIRECT_MIXIN_WHAT_THE_FUCK_SEMAPHORE;
|
||||
}
|
||||
|
||||
// why bother with all of that locking crap when a single CAS works?
|
||||
|
||||
// no unique to prevent renames
|
||||
private volatile Thread moonriseCurrThread;
|
||||
|
||||
@Unique
|
||||
private static final VarHandle CURR_THREAD_HANDLE = ConcurrentUtil.getVarHandle(ThreadingDetector.class, "moonriseCurrThread", Thread.class);
|
||||
|
||||
/**
|
||||
* @reason Replace with optimised version
|
||||
* @reason Remove
|
||||
* @author Spottedleaf
|
||||
*/
|
||||
@Overwrite
|
||||
public void checkAndLock() {
|
||||
final Thread prev = (Thread)CURR_THREAD_HANDLE.compareAndExchange((ThreadingDetector)(Object)this, (Thread)null, (Thread)Thread.currentThread());
|
||||
if (prev != null) {
|
||||
throw ThreadingDetector.makeThreadingException(this.name, prev);
|
||||
}
|
||||
}
|
||||
public void checkAndLock() {}
|
||||
|
||||
/**
|
||||
* @reason Replace with optimised version
|
||||
* @reason Remove
|
||||
* @author Spottedleaf
|
||||
*/
|
||||
@Overwrite
|
||||
public void checkAndUnlock() {
|
||||
final Thread expect = Thread.currentThread();
|
||||
|
||||
final Thread prev = (Thread)CURR_THREAD_HANDLE.compareAndExchange((ThreadingDetector)(Object)this, expect, (Thread)null);
|
||||
|
||||
if (prev != expect) {
|
||||
throw ThreadingDetector.makeThreadingException(this.name, prev);
|
||||
}
|
||||
}
|
||||
public void checkAndUnlock() {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user