Skip to content

Commit

Permalink
Fixed game freezing because of too-large entity AABBs
Browse files Browse the repository at this point in the history
  • Loading branch information
StewStrong committed Oct 21, 2023
1 parent a3c2f4e commit df32e76
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.valkyrienskies.core.util.RateLimiter;
import org.valkyrienskies.mod.common.VSGameUtilsKt;
import org.valkyrienskies.mod.util.BugFixUtil;

@Mixin(Level.class)
public class MixinLevel {
Expand All @@ -28,11 +29,6 @@ public class MixinLevel {
@Unique
private static final RateLimiter LIMITER = new RateLimiter(Duration.ofSeconds(5));

@Unique
private static boolean isCollisionBoxToBig(final AABB aabb) {
return aabb.getXsize() > 1000 || aabb.getYsize() > 1000 || aabb.getZsize() > 1000;
}

@ModifyVariable(
method = "getEntities(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;)Ljava/util/List;",
at = @At("HEAD"),
Expand All @@ -59,7 +55,7 @@ private AABB moveAABB2(final AABB aabb) {
private <T extends Entity> void check1(final EntityTypeTest<Entity, T> entityTypeTest, final AABB area,
final Predicate<? super T> predicate, final CallbackInfoReturnable<List<T>> cir) {

if (isCollisionBoxToBig(area)) {
if (BugFixUtil.INSTANCE.isCollisionBoxToBig(area)) {
LIMITER.maybeRun(() ->
LOGGER.error(new Exception(
"Collision box is too big! " + area + " returning empty list! this might break things")));
Expand All @@ -76,7 +72,7 @@ private <T extends Entity> void check1(final EntityTypeTest<Entity, T> entityTyp
private <T extends Entity> void check2(@Nullable final Entity entity, final AABB area,
final Predicate<? super Entity> predicate, final CallbackInfoReturnable<List<Entity>> cir) {

if (isCollisionBoxToBig(area)) {
if (BugFixUtil.INSTANCE.isCollisionBoxToBig(area)) {
LIMITER.maybeRun(() ->
LOGGER.error(new Exception(
"Collision box is too big! " + area + " returning empty list! this might break things")));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.valkyrienskies.mod.mixin.world.level;

import net.minecraft.core.Cursor3D;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.BlockCollisions;
import net.minecraft.world.level.CollisionGetter;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.valkyrienskies.mod.util.BugFixUtil;

/**
* Fix game freezing when a too-large AABB is used in a BlockCollisions object
*/
@Mixin(BlockCollisions.class)
public class MixinBlockCollisions {
@Shadow
@Final
@Mutable
private AABB box;
@Shadow
@Final
@Mutable
private Cursor3D cursor;
@Shadow
@Final
@Mutable
private VoxelShape entityShape;

@Inject(method = "<init>(Lnet/minecraft/world/level/CollisionGetter;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/AABB;Z)V", at = @At("RETURN"))
private void postInit(final CollisionGetter collisionGetter, final Entity entity, final AABB aabb, final boolean bl, final CallbackInfo ci) {
if (BugFixUtil.INSTANCE.isCollisionBoxToBig(aabb)) {
final AABB newBox = new AABB(aabb.minX, aabb.minY, aabb.minZ, aabb.minX, aabb.minY, aabb.minZ);
this.entityShape = Shapes.create(newBox);
this.box = newBox;
final int i = Mth.floor(newBox.minX - 1.0E-7) - 1;
final int j = Mth.floor(newBox.maxX + 1.0E-7) + 1;
final int k = Mth.floor(newBox.minY - 1.0E-7) - 1;
final int l = Mth.floor(newBox.maxY + 1.0E-7) + 1;
final int m = Mth.floor(newBox.minZ - 1.0E-7) - 1;
final int n = Mth.floor(newBox.maxZ + 1.0E-7) + 1;
this.cursor = new Cursor3D(i, k, m, j, l, n);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import org.valkyrienskies.core.util.extend
import org.valkyrienskies.mod.common.getShipsIntersecting
import org.valkyrienskies.mod.common.shipObjectWorld
import org.valkyrienskies.mod.common.vsCore
import org.valkyrienskies.mod.util.BugFixUtil
import kotlin.math.max

object EntityShipCollisionUtils {
Expand Down Expand Up @@ -116,6 +117,10 @@ object EntityShipCollisionUtils {
shipTransform.worldToShip
)
val entityBoundingBoxInShipCoordinates: AABBdc = entityPolyInShipCoordinates.getEnclosingAABB(AABBd())
if (BugFixUtil.isCollisionBoxToBig(entityBoundingBoxInShipCoordinates.toMinecraft())) {
// Box too large, skip it
continue
}
val shipBlockCollisionStream =
world.getBlockCollisions(entity, entityBoundingBoxInShipCoordinates.toMinecraft())
shipBlockCollisionStream.forEach { voxelShape: VoxelShape ->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.valkyrienskies.mod.util

import net.minecraft.world.phys.AABB

object BugFixUtil {
fun isCollisionBoxToBig(aabb: AABB): Boolean {
return aabb.xsize > 1000 || aabb.ysize > 1000 || aabb.zsize > 1000
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
"world.chunk.MixinLevelChunk",
"world.entity.MixinPlayer",
"world.entity.projectile.ProjectileUtilMixin",
"world.level.MixinBlockCollisions",
"world.level.MixinLevel",
"world.level.chunk.MixinChunkGenerator",
"world.level.levelgen.MixinFlatLevelSource",
Expand Down

0 comments on commit df32e76

Please sign in to comment.