From 8438b4a82b4575caa96b38cd6e6fe4d90c1674b0 Mon Sep 17 00:00:00 2001 From: Matt Date: Fri, 16 Jan 2026 11:50:24 -0500 Subject: [PATCH] Optimize memory allocation for checking entity fluid collisions. Backport of #10745 (#10751) Co-authored-by: LexManos --- .../minecraft/world/entity/Entity.java.patch | 107 +++++++++++------- 1 file changed, 67 insertions(+), 40 deletions(-) diff --git a/patches/minecraft/net/minecraft/world/entity/Entity.java.patch b/patches/minecraft/net/minecraft/world/entity/Entity.java.patch index 45189f1a90..2633b05a4b 100644 --- a/patches/minecraft/net/minecraft/world/entity/Entity.java.patch +++ b/patches/minecraft/net/minecraft/world/entity/Entity.java.patch @@ -324,7 +324,7 @@ public boolean isPushedByFluid() { return true; } -@@ -3307,9 +_,17 @@ +@@ -3307,9 +_,26 @@ return Mth.lerp(p_344421_, this.yRotO, this.yRot); } @@ -334,20 +334,32 @@ + if(p_204032_ == FluidTags.WATER) return this.isInFluidType(net.minecraftforge.common.ForgeMod.WATER_TYPE.get()); + else if (p_204032_ == FluidTags.LAVA) return this.isInFluidType(net.minecraftforge.common.ForgeMod.LAVA_TYPE.get()); + else return false; -+ } ++ } + -+ public void updateFluidHeightAndDoFluidPushing(Predicate shouldUpdate) { ++ private static final class FluidCalcs { ++ double height = 0.0D; ++ Vec3 direction = Vec3.ZERO; ++ int count = 0; ++ double height(double height) { ++ return (this.height = this.height >= height ? this.height : height); ++ } ++ } ++ ++ public void updateFluidHeightAndDoFluidPushing(Predicate shouldUpdate) { if (this.touchingUnloadedChunk()) { - return false; + return; } else { AABB aabb = this.getBoundingBox().deflate(0.001); int i = Mth.floor(aabb.minX); -@@ -3324,25 +_,28 @@ - Vec3 vec3 = Vec3.ZERO; - int k1 = 0; +@@ -3321,28 +_,32 @@ + double d0 = 0.0; + boolean flag = this.isPushedByFluid(); + boolean flag1 = false; +- Vec3 vec3 = Vec3.ZERO; +- int k1 = 0; BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos(); -+ var interimCalcs = new it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap>(net.minecraftforge.fluids.FluidType.SIZE.get() - 1); ++ it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap fluidPushCalcs = null; for (int l1 = i; l1 < j; l1++) { for (int i2 = k; i2 < l; i2++) { @@ -355,66 +367,81 @@ blockpos$mutableblockpos.set(l1, i2, j2); FluidState fluidstate = this.level().getFluidState(blockpos$mutableblockpos); - if (fluidstate.is(p_204032_)) { +- double d1 = (double)((float)i2 + fluidstate.getHeight(this.level(), blockpos$mutableblockpos)); + net.minecraftforge.fluids.FluidType fluidType = fluidstate.getFluidType(); + if (!fluidType.isAir() && shouldUpdate.test(fluidstate)) { - double d1 = (double)((float)i2 + fluidstate.getHeight(this.level(), blockpos$mutableblockpos)); ++ double d1 = i2 + fluidstate.getHeight(this.level(), blockpos$mutableblockpos); if (d1 >= aabb.minY) { flag1 = true; - d0 = Math.max(d1 - aabb.minY, d0); -- if (flag) { -+ var interim = interimCalcs.computeIfAbsent(fluidType, t -> org.apache.commons.lang3.tuple.MutableTriple.of(0.0D, Vec3.ZERO, 0)); -+ interim.setLeft(Math.max(d1 - aabb.minY, interim.getLeft())); -+ if (this.isPushedByFluid(fluidType)) { ++ if (fluidPushCalcs == null) ++ fluidPushCalcs = new it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap(2); ++ var interim = fluidPushCalcs.computeIfAbsent(fluidType, type -> new FluidCalcs()); ++ d0 = interim.height(d1 - aabb.minY); ++ flag = this.isPushedByFluid(fluidType); + if (flag) { Vec3 vec31 = fluidstate.getFlow(this.level(), blockpos$mutableblockpos); -- if (d0 < 0.4) { -- vec31 = vec31.scale(d0); -+ if (interim.getLeft() < 0.4D) { -+ vec31 = vec31.scale(interim.getLeft()); + if (d0 < 0.4) { + vec31 = vec31.scale(d0); } - vec3 = vec3.add(vec31); - k1++; -+ interim.setMiddle(interim.getMiddle().add(vec31)); -+ interim.setRight(interim.getRight() + 1); ++ interim.direction = interim.direction.add(vec31); ++ interim.count++; } } } -@@ -3350,27 +_,28 @@ +@@ -3350,27 +_,32 @@ } } - if (vec3.length() > 0.0) { - if (k1 > 0) { - vec3 = vec3.scale(1.0 / (double)k1); -+ interimCalcs.forEach((fluidType, interim) -> { -+ if (interim.getMiddle().length() > 0.0D) { -+ if (interim.getRight() > 0) { -+ interim.setMiddle(interim.getMiddle().scale(1.0D / (double)interim.getRight())); - } - - if (!(this instanceof Player)) { +- } +- +- if (!(this instanceof Player)) { - vec3 = vec3.normalize(); -+ interim.setMiddle(interim.getMiddle().normalize()); - } - - Vec3 vec32 = this.getDeltaMovement(); +- } +- +- Vec3 vec32 = this.getDeltaMovement(); - vec3 = vec3.scale(p_204033_); -+ interim.setMiddle(interim.getMiddle().scale(this.getFluidMotionScale(fluidType))); - double d2 = 0.003; +- double d2 = 0.003; - if (Math.abs(vec32.x) < 0.003 && Math.abs(vec32.z) < 0.003 && vec3.length() < 0.0045000000000000005) { - vec3 = vec3.normalize().scale(0.0045000000000000005); -+ if (Math.abs(vec32.x) < 0.003 && Math.abs(vec32.z) < 0.003 && interim.getMiddle().length() < 0.0045000000000000005) { -+ interim.setMiddle(interim.getMiddle().normalize().scale(0.0045000000000000005)); - } - +- } +- - this.setDeltaMovement(this.getDeltaMovement().add(vec3)); -+ this.setDeltaMovement(this.getDeltaMovement().add(interim.getMiddle())); ++ if (fluidPushCalcs == null) return; ++ for (var entry : fluidPushCalcs.entrySet()) { ++ var vec3 = entry.getValue().direction; ++ var k1 = entry.getValue().count; ++ if (vec3.length() > 0.0) { ++ if (k1 > 0) { ++ vec3 = vec3.scale(1.0 / k1); ++ } ++ ++ if (!(this instanceof Player)) { ++ vec3 = vec3.normalize(); ++ } ++ ++ Vec3 vec32 = this.getDeltaMovement(); ++ var p_204033_ = this.getFluidMotionScale(entry.getKey()); ++ vec3 = vec3.scale(p_204033_); ++ double d2 = 0.003; ++ if (Math.abs(vec32.x) < 0.003 && Math.abs(vec32.z) < 0.003 && vec3.length() < 0.0045000000000000005) { ++ vec3 = vec3.normalize().scale(0.0045000000000000005); ++ } ++ ++ this.setDeltaMovement(this.getDeltaMovement().add(vec3)); ++ } ++ ++ this.setFluidTypeHeight(entry.getKey(), entry.getValue().height); } - +- - this.fluidHeight.put(p_204032_, d0); - return flag1; -+ this.setFluidTypeHeight(fluidType, interim.getLeft()); -+ }); } }