From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sat, 9 Aug 2025 18:12:11 +0900 Subject: [PATCH] optimize checkInsideBlocks diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java index 4689764a580d7dca468cdfa2b0fef7e70c57687f..e4c2c0b4ea2b153266c2bb35574167364029bc7c 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java @@ -1723,72 +1723,57 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess private void checkInsideBlocks(Vec3 vec3, Vec3 vec31, InsideBlockEffectApplier.StepBasedCollector stepBasedCollector, LongSet set) { final Level level = this.level(); AABB aabb = this.getBoundingBox().move(vec31.subtract(this.position())).deflate(1.0E-5F); - final net.minecraft.world.level.chunk.ChunkAccess[] cachedChunk = { null }; - final long[] cachedChunkPos = { Long.MIN_VALUE }; - BlockGetter.forEachBlockIntersectedBetween( + BlockGetter.leaf$forEachBlockIntersectedBetween( + set, vec3, vec31, aabb, (pos, index) -> { + final int posX = pos.getX(); + final int posY = pos.getY(); + final int posZ = pos.getZ(); + BlockState blockState = level.getBlockStateIfLoadedUnchecked(posX, posY, posZ); + if (blockState == null) { + blockState = level.getBlockState(pos); + } + if (blockState.isAir()) { + this.debugBlockIntersection(pos, false, false); + return true; + } if (!this.isAlive()) { return false; - } else { - final int chunkX = pos.getX() >> 4; - final int chunkZ = pos.getZ() >> 4; - final long currentChunkPos = ChunkPos.asLong(chunkX, chunkZ); - BlockState blockState; - - if (cachedChunkPos[0] != currentChunkPos) {cachedChunk[0] = level.getChunkIfLoaded(chunkX, chunkZ);cachedChunkPos[0] = currentChunkPos;} - - if (cachedChunk[0] != null) {blockState = cachedChunk[0].getBlockState(pos); - } else { - blockState = level.getBlockStateIfLoaded(pos); - if (blockState == null) {blockState = Blocks.AIR.defaultBlockState();} + } + VoxelShape entityInsideCollisionShape = blockState.getEntityInsideCollisionShape(level, pos, this); + boolean flag = entityInsideCollisionShape == Shapes.block() + || this.collidedWithShapeMovingFrom(vec3, vec31, entityInsideCollisionShape.move(new Vec3(pos)).toAabbs()); + if (flag) { + try { + stepBasedCollector.advanceStep(index, pos); // Paper - track position inside effect was triggered on + blockState.entityInside(level, pos, this, stepBasedCollector); + this.onInsideBlock(blockState); + } catch (Throwable var14) { + CrashReport crashReport = CrashReport.forThrowable(var14, "Colliding entity with block"); + CrashReportCategory crashReportCategory = crashReport.addCategory("Block being collided with"); + CrashReportCategory.populateBlockDetails(crashReportCategory, level, pos, blockState); + CrashReportCategory crashReportCategory1 = crashReport.addCategory("Entity being checked for collision"); + this.fillCrashReportCategory(crashReportCategory1); + throw new ReportedException(crashReport); } + } - final long posLong = pos.asLong(); - if (blockState.isAir()) { - this.debugBlockIntersection(pos, false, false); - return true; - } else if (!set.add(posLong)) { - return true; - } else { - VoxelShape entityInsideCollisionShape = blockState.getEntityInsideCollisionShape(level, pos, this); - boolean flag = entityInsideCollisionShape == Shapes.block() - || this.collidedWithShapeMovingFrom(vec3, vec31, entityInsideCollisionShape.move(new Vec3(pos)).toAabbs()); - - if (flag) { - try { - stepBasedCollector.advanceStep(index, pos); // Paper - track position inside effect was triggered on - blockState.entityInside(level, pos, this, stepBasedCollector); - this.onInsideBlock(blockState); - } catch (Throwable var14) { - CrashReport crashReport = CrashReport.forThrowable(var14, "Colliding entity with block"); - CrashReportCategory crashReportCategory = crashReport.addCategory("Block being collided with"); - CrashReportCategory.populateBlockDetails(crashReportCategory, level, pos, blockState); - CrashReportCategory crashReportCategory1 = crashReport.addCategory("Entity being checked for collision"); - this.fillCrashReportCategory(crashReportCategory1); - throw new ReportedException(crashReport); - } - } - - final FluidState fluidState = blockState.getFluidState(); - boolean flag1 = !fluidState.isEmpty() && this.collidedWithFluid(fluidState, pos, vec3, vec31); - - if (flag1) { - stepBasedCollector.advanceStep(index, pos); // Paper - track position inside effect was triggered on - fluidState.entityInside(level, pos, this, stepBasedCollector); - } - - this.debugBlockIntersection(pos, flag, flag1); - return true; - } + boolean flag1 = (blockState.tagFlag & org.dreeam.leaf.util.BlockMasks.FLUID) != 0 + && this.collidedWithFluid(blockState.getFluidState(), pos, vec3, vec31); + if (flag1) { + stepBasedCollector.advanceStep(index, pos); // Paper - track position inside effect was triggered on + blockState.getFluidState().entityInside(level, pos, this, stepBasedCollector); } + this.debugBlockIntersection(pos, flag, flag1); + return true; } ); } -// Leaf end - optimize checkInsideBlocks calls + // Leaf end - optimize checkInsideBlocks calls private void debugBlockIntersection(BlockPos blockPos, boolean flag, boolean flag1) { } diff --git a/net/minecraft/world/entity/InsideBlockEffectApplier.java b/net/minecraft/world/entity/InsideBlockEffectApplier.java index 92b9c324cb6aab415abe2e77c5844b74c251a42f..eba3896b73c70f29732388373e89bf7ce3a07c92 100644 --- a/net/minecraft/world/entity/InsideBlockEffectApplier.java +++ b/net/minecraft/world/entity/InsideBlockEffectApplier.java @@ -33,6 +33,7 @@ public interface InsideBlockEffectApplier { // Leaf start - optimize checkInsideBlocks calls private static final InsideBlockEffectType[] APPLY_ORDER = InsideBlockEffectType.values(); private static final int NO_STEP = -1; + private int flags = 0; private final Consumer[] effectsInStep = new Consumer[APPLY_ORDER.length]; private final List>[] beforeEffectsInStep = new List[APPLY_ORDER.length]; @@ -40,13 +41,13 @@ public interface InsideBlockEffectApplier { private static final List> EMPTY_LIST = List.of(); - private final List> finalEffects = new ArrayList<>(); + private final List> finalEffects = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(); private int lastStep = -1; public StepBasedCollector() { for (int i = 0; i < APPLY_ORDER.length; i++) { - beforeEffectsInStep[i] = new ArrayList<>(2); - afterEffectsInStep[i] = new ArrayList<>(2); + beforeEffectsInStep[i] = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(2); + afterEffectsInStep[i] = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(2); } } @@ -100,6 +101,10 @@ public interface InsideBlockEffectApplier { } private void flushStep() { + final int flags = this.flags; + if (flags == 0) { + return; + } final int len = APPLY_ORDER.length; final List>[] beforeArr = this.beforeEffectsInStep; final Consumer[] effectArr = this.effectsInStep; @@ -107,6 +112,9 @@ public interface InsideBlockEffectApplier { final List> finalList = this.finalEffects; for (int i = 0; i < len; i++) { + if (((1 << i) & flags) == 0) { + continue; + } // Process before effects List> beforeList = beforeArr[i]; if (!beforeList.isEmpty()) { @@ -128,21 +136,28 @@ public interface InsideBlockEffectApplier { afterList.clear(); } } + this.flags = 0; } @Override public void apply(InsideBlockEffectType type) { - effectsInStep[type.ordinal()] = recorded(type); + int i = type.ordinal(); + effectsInStep[i] = recorded(type); + this.flags |= 1 << i; } @Override public void runBefore(InsideBlockEffectType type, Consumer effect) { - beforeEffectsInStep[type.ordinal()].add(effect); + int i = type.ordinal(); + beforeEffectsInStep[i].add(effect); + this.flags |= 1 << i; } @Override public void runAfter(InsideBlockEffectType type, Consumer effect) { - afterEffectsInStep[type.ordinal()].add(effect); + int i = type.ordinal(); + afterEffectsInStep[i].add(effect); + this.flags |= 1 << i; } // Paper start - track position inside effect was triggered on diff --git a/net/minecraft/world/level/BlockGetter.java b/net/minecraft/world/level/BlockGetter.java index eeddffbe6a47dc1a42c07f286bfec0cbde33fc17..b0da274c944fcef6aaae39b43f05a79110e4bb16 100644 --- a/net/minecraft/world/level/BlockGetter.java +++ b/net/minecraft/world/level/BlockGetter.java @@ -255,6 +255,81 @@ public interface BlockGetter extends LevelHeightAccessor { } } + // Leaf start + static boolean leaf$forEachBlockIntersectedBetween(it.unimi.dsi.fastutil.longs.LongSet set, Vec3 from, Vec3 to, AABB boundingBox, BlockGetter.BlockStepVisitor visitor) { + Vec3 vec3 = to.subtract(from); + BlockPos.MutableBlockPos cursor = new BlockPos.MutableBlockPos(); + if (vec3.lengthSqr() < Mth.square(0.99999F)) { + int pos1x = Mth.floor(boundingBox.minX); + int pos1y = Mth.floor(boundingBox.minY); + int pos1z = Mth.floor(boundingBox.minZ); + int pos2x = Mth.floor(boundingBox.maxX); + int pos2y = Mth.floor(boundingBox.maxY); + int pos2z = Mth.floor(boundingBox.maxZ); + int x1 = Math.min(pos1x, pos2x); + int y1 = Math.min(pos1y, pos2y); + int z1 = Math.min(pos1z, pos2z); + int i = Math.max(pos1x, pos2x) - x1 + 1; + int i1 = Math.max(pos1y, pos2y) - y1 + 1; + int i2 = Math.max(pos1z, pos2z) - z1 + 1; + int i3 = i * i1 * i2; + int index = 0; + while (index != i3) { + int i4 = index % i; + int i5 = index / i; + int i6 = i5 % i1; + int i7 = i5 / i1; + index++; + int x0 = x1 + i4; + int y0 = y1 + i6; + int z0 = z1 + i7; + if (set.add(BlockPos.asLong(x0, y0, z0)) && !visitor.visit(cursor.set(x0, y0, z0), 0)) { + return false; + } + } + + return true; + } else { + Vec3 minPosition = boundingBox.getMinPosition(); + Vec3 vec31 = minPosition.subtract(vec3); + int i = addCollisionsAlongTravel(set, vec31, minPosition, boundingBox, visitor); + if (i < 0) { + return false; + } else { + int pos1x = Mth.floor(boundingBox.minX); + int pos1y = Mth.floor(boundingBox.minY); + int pos1z = Mth.floor(boundingBox.minZ); + int pos2x = Mth.floor(boundingBox.maxX); + int pos2y = Mth.floor(boundingBox.maxY); + int pos2z = Mth.floor(boundingBox.maxZ); + int x1 = Math.min(pos1x, pos2x); + int y1 = Math.min(pos1y, pos2y); + int z1 = Math.min(pos1z, pos2z); + int j = Math.max(pos1x, pos2x) - x1 + 1; + int i1 = Math.max(pos1y, pos2y) - y1 + 1; + int i2 = Math.max(pos1z, pos2z) - z1 + 1; + int i3 = j * i1 * i2; + int index = 0; + while (index != i3) { + int i4 = index % j; + int i5 = index / j; + int i6 = i5 % i1; + int i7 = i5 / i1; + index++; + int x0 = x1 + i4; + int y0 = y1 + i6; + int z0 = z1 + i7; + if (set.add(BlockPos.asLong(x0, y0, z0)) && !visitor.visit(cursor.set(x0, y0, z0), i + 1)) { + return false; + } + } + + return true; + } + } + } + // Leaf end + private static int addCollisionsAlongTravel(LongSet output, Vec3 from, Vec3 to, AABB boundingBox, BlockGetter.BlockStepVisitor stepVisitor) { Vec3 vec3 = to.subtract(from); int floor = Mth.floor(from.x);