From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Samsuik Date: Fri, 8 Nov 2024 19:35:49 +0000 Subject: [PATCH] Optimise check inside blocks and traverse blocks diff --git a/src/main/java/me/samsuik/sakura/utils/BlockPosIterator.java b/src/main/java/me/samsuik/sakura/utils/BlockPosIterator.java new file mode 100644 index 0000000000000000000000000000000000000000..e00c07c614e007c007076e3dbe8bd8ccf6c6572d --- /dev/null +++ b/src/main/java/me/samsuik/sakura/utils/BlockPosIterator.java @@ -0,0 +1,60 @@ +package me.samsuik.sakura.utils; + +import com.google.common.collect.AbstractIterator; +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.AABB; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + +@NullMarked +public final class BlockPosIterator extends AbstractIterator { + private final int startX; + private final int startY; + private final int startZ; + private final int endX; + private final int endY; + private final int endZ; + private @Nullable MutableBlockPos pos = null; + + public static Iterable iterable(AABB bb) { + return () -> new BlockPosIterator(bb); + } + + public BlockPosIterator(AABB bb) { + this.startX = Mth.floor(bb.minX); + this.startY = Mth.floor(bb.minY); + this.startZ = Mth.floor(bb.minZ); + this.endX = Mth.floor(bb.maxX); + this.endY = Mth.floor(bb.maxY); + this.endZ = Mth.floor(bb.maxZ); + } + + @Override + protected BlockPos computeNext() { + MutableBlockPos pos = this.pos; + if (pos == null) { + return this.pos = new MutableBlockPos(this.startX, this.startY, this.startZ); + } else { + int x = pos.getX(); + int y = pos.getY(); + int z = pos.getZ(); + + if (y < this.endY) { + y += 1; + } else if (x < this.endX) { + x += 1; + y = this.startY; + } else if (z < this.endZ) { + z += 1; + x = this.startX; + } else { + return this.endOfData(); + } + + pos.set(x, y, z); + return pos; + } + } +} diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java index 95f4854ca21a6b34ad1ab95a1cb38f7d2dfd24c3..7d35952cdf48150f43b103b765358b7760411c9d 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -2061,6 +2061,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } final Iterator iterator1 = positions.iterator(); // Sakura end - physics version api + // Sakura start - optimise check inside blocks + int lastChunkX = Integer.MIN_VALUE; + int lastChunkZ = Integer.MIN_VALUE; + net.minecraft.world.level.chunk.ChunkAccess chunk = null; + // Sakura end - optimise check inside blocks while (iterator1.hasNext()) { BlockPos blockposition = (BlockPos) iterator1.next(); @@ -2069,7 +2074,19 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return; } - BlockState iblockdata = this.level().getBlockState(blockposition); + // Sakura start - optimise check inside blocks + int chunkX = blockposition.getX() >> 4; + int chunkZ = blockposition.getZ() >> 4; + if (chunk == null || chunkX != lastChunkX || chunkZ != lastChunkZ) { + chunk = this.level.getChunkIfLoadedImmediately(chunkX, chunkZ); + if (chunk == null) { + continue; + } + lastChunkX = chunkX; + lastChunkZ = chunkZ; + } + BlockState iblockdata = chunk.getBlockState(blockposition); + // Sakura end - optimise check inside blocks if (!iblockdata.isAir() && longset.add(blockposition.asLong())) { try { diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java index 62719778c62d6632a8eb6f2bc670956c15a247de..ecdb8769c1a388827bf5c4565c82f8e32672c5d7 100644 --- a/src/main/java/net/minecraft/world/level/BlockGetter.java +++ b/src/main/java/net/minecraft/world/level/BlockGetter.java @@ -215,11 +215,18 @@ public interface BlockGetter extends LevelHeightAccessor { static Iterable boxTraverseBlocks(Vec3 oldPos, Vec3 newPos, AABB boundingBox) { Vec3 vec3d2 = newPos.subtract(oldPos); - Iterable iterable = BlockPos.betweenClosed(boundingBox); - + // Sakura start - optimise check inside blocks if (vec3d2.lengthSqr() < (double) Mth.square(0.99999F)) { - return iterable; + return me.samsuik.sakura.utils.BlockPosIterator.iterable(boundingBox); } else { + boolean xZero = vec3d2.x() == 0.0; + boolean yZero = vec3d2.y() == 0.0; + boolean zZero = vec3d2.z() == 0.0; + if (xZero && yZero || yZero && zZero || xZero && zZero) { + return traverseAreaFast(vec3d2, boundingBox); + } + Iterable iterable = BlockPos.betweenClosed(boundingBox); + // Sakura end - optimise check inside blocks Set set = new ObjectLinkedOpenHashSet(); Vec3 vec3d3 = boundingBox.getMinPosition(); Vec3 vec3d4 = vec3d3.subtract(vec3d2); @@ -237,6 +244,16 @@ public interface BlockGetter extends LevelHeightAccessor { } } + // Sakura start - optimise check inside blocks + private static Iterable traverseAreaFast(Vec3 vec, AABB boundingBox) { + double toTravel = Math.min(16.0 / vec.length(), 1.0); + Vec3 movement = vec.scale(toTravel); + AABB fromBB = boundingBox.move(-vec.x, -vec.y, -vec.z); + AABB searchArea = fromBB.expandTowards(movement); + return me.samsuik.sakura.utils.BlockPosIterator.iterable(searchArea); + } + // Sakura end - optimise check inside blocks + private static void addCollisionsAlongTravel(Set result, Vec3 oldPos, Vec3 newPos, AABB boundingBox) { Vec3 vec3d2 = newPos.subtract(oldPos); int i = Mth.floor(oldPos.x);