9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-19 15:09:25 +00:00
Files
Leaf/leaf-server/minecraft-patches/features/0291-optimize-checkInsideBlocks.patch
2025-10-01 10:03:59 -04:00

290 lines
14 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: hayanesuru <hayanesuru@outlook.jp>
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 78d204451266ae3e9d6b5491bb0962ca1c9998cd..20f558f49bcda32373a409eb5137d5b67f6a0404 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -1819,72 +1819,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<Entity>[] effectsInStep = new Consumer[APPLY_ORDER.length];
private final List<Consumer<Entity>>[] beforeEffectsInStep = new List[APPLY_ORDER.length];
@@ -40,13 +41,13 @@ public interface InsideBlockEffectApplier {
private static final List<Consumer<Entity>> EMPTY_LIST = List.of();
- private final List<Consumer<Entity>> finalEffects = new ArrayList<>();
+ private final List<Consumer<Entity>> 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<Consumer<Entity>>[] beforeArr = this.beforeEffectsInStep;
final Consumer<Entity>[] effectArr = this.effectsInStep;
@@ -107,6 +112,9 @@ public interface InsideBlockEffectApplier {
final List<Consumer<Entity>> finalList = this.finalEffects;
for (int i = 0; i < len; i++) {
+ if (((1 << i) & flags) == 0) {
+ continue;
+ }
// Process before effects
List<Consumer<Entity>> 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<Entity> 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<Entity> 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);