From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: violetc <58360096+s-yh-china@users.noreply.github.com> Date: Sat, 20 Aug 2022 22:52:31 +0800 Subject: [PATCH] Reduce entity fluid lookups if no fluids This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java index b058ccd484fdf8294a3be203fdfec5ed67ef5a42..80dc0fa45c8c7ad157e7b456cbe65665dda0bd95 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -4074,16 +4074,18 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { } public boolean updateFluidHeightAndDoFluidPushing(TagKey tag, double speed) { - if (this.touchingUnloadedChunk()) { + if (!top.leavesmc.leaves.LeavesConfig.reduceEntityFluidLookup && this.touchingUnloadedChunk()) { // Leaves - cost of a lookup here is the same cost as below, so skip return false; } else { AABB axisalignedbb = this.getBoundingBox().deflate(0.001D); - int i = Mth.floor(axisalignedbb.minX); - int j = Mth.ceil(axisalignedbb.maxX); - int k = Mth.floor(axisalignedbb.minY); - int l = Mth.ceil(axisalignedbb.maxY); - int i1 = Mth.floor(axisalignedbb.minZ); - int j1 = Mth.ceil(axisalignedbb.maxZ); + // Leaves start - rename + int minBlockX = Mth.floor(axisalignedbb.minX); + int maxBlockX = Mth.ceil(axisalignedbb.maxX); + int minBlockY = Mth.floor(axisalignedbb.minY); + int maxBlockY = Mth.ceil(axisalignedbb.maxY); + int minBlockZ = Mth.floor(axisalignedbb.minZ); + int maxBlockZ = Mth.ceil(axisalignedbb.maxZ); + // Leaves end double d1 = 0.0D; boolean flag = this.isPushedByFluid(); boolean flag1 = false; @@ -4091,38 +4093,123 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { int k1 = 0; BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); - for (int l1 = i; l1 < j; ++l1) { - for (int i2 = k; i2 < l; ++i2) { - for (int j2 = i1; j2 < j1; ++j2) { - blockposition_mutableblockposition.set(l1, i2, j2); - FluidState fluid = this.level.getFluidState(blockposition_mutableblockposition); + // Leaves start - based off CollisionUtil.getCollisionsForBlocksOrWorldBorder + if (top.leavesmc.leaves.LeavesConfig.reduceEntityFluidLookup) { + final int minSection = io.papermc.paper.util.WorldUtil.getMinSection(this.level); + final int maxSection = io.papermc.paper.util.WorldUtil.getMaxSection(this.level); + final int minBlock = minSection << 4; + final int maxBlock = (maxSection << 4) | 15; - if (fluid.is(tag)) { - double d2 = (double) ((float) i2 + fluid.getHeight(this.level, blockposition_mutableblockposition)); + // special cases: + if (minBlockY > maxBlock || maxBlockY < minBlock) { + // no point in checking + return false; + } - if (d2 >= axisalignedbb.minY) { - flag1 = true; - d1 = Math.max(d2 - axisalignedbb.minY, d1); - if (flag) { - Vec3 vec3d1 = fluid.getFlow(this.level, blockposition_mutableblockposition); + int minYIterate = Math.max(minBlock, minBlockY); + int maxYIterate = Math.min(maxBlock, maxBlockY); - if (d1 < 0.4D) { - vec3d1 = vec3d1.scale(d1); - } + int minChunkX = minBlockX >> 4; + int maxChunkX = maxBlockX >> 4; + + int minChunkZ = minBlockZ >> 4; + int maxChunkZ = maxBlockZ >> 4; + + for (int currChunkZ = minChunkZ; currChunkZ <= maxChunkZ; ++currChunkZ) { + int minZ = currChunkZ == minChunkZ ? minBlockZ & 15 : 0; // coordinate in chunk + int maxZ = currChunkZ == maxChunkZ ? maxBlockZ & 15 : 16; // coordinate in chunk + + for (int currChunkX = minChunkX; currChunkX <= maxChunkX; ++currChunkX) { + int minX = currChunkX == minChunkX ? minBlockX & 15 : 0; // coordinate in chunk + int maxX = currChunkX == maxChunkX ? maxBlockX & 15 : 16; // coordinate in chunk + + net.minecraft.world.level.chunk.ChunkAccess chunk = this.level.getChunkIfLoadedImmediately(currChunkX, currChunkZ); + if (chunk == null) { + return false; // if we're touching an unloaded chunk then it's false + } + + net.minecraft.world.level.chunk.LevelChunkSection[] sections = chunk.getSections(); + + for (int currY = minYIterate; currY < maxYIterate; ++currY) { + net.minecraft.world.level.chunk.LevelChunkSection section = sections[(currY >> 4) - minSection]; - vec3d = vec3d.add(vec3d1); - ++k1; + if (section == null || section.hasOnlyAir() || section.fluidStateCount == 0) { // if no fluids, nothing in this section + // empty + // skip to next section + currY = (currY & ~(15)) + 15; // increment by 15: iterator loop increments by the extra one + continue; + } + + net.minecraft.world.level.chunk.PalettedContainer blocks = section.states; + + for (int currZ = minZ; currZ < maxZ; ++currZ) { + for (int currX = minX; currX < maxX; ++currX) { + FluidState fluid = blocks.get(currX & 15, currY & 15, currZ & 15).getFluidState(); + + if (fluid.is(tag)) { + blockposition_mutableblockposition.set((currChunkX << 4) + currX, currY, (currChunkZ << 4) + currZ); + double d2 = (double) ((float) currY + fluid.getHeight(this.level, blockposition_mutableblockposition)); + + if (d2 >= axisalignedbb.minY) { + flag1 = true; + d1 = Math.max(d2 - axisalignedbb.minY, d1); + if (flag) { + Vec3 vec3d1 = fluid.getFlow(this.level, blockposition_mutableblockposition); + + if (d1 < 0.4D) { + vec3d1 = vec3d1.scale(d1); + } + + vec3d = vec3d.add(vec3d1); + ++k1; + } + // CraftBukkit start - store last lava contact location + if (tag == FluidTags.LAVA) { + this.lastLavaContact = blockposition_mutableblockposition.immutable(); + } + // CraftBukkit end + } + } } - // CraftBukkit start - store last lava contact location - if (tag == FluidTags.LAVA) { - this.lastLavaContact = blockposition_mutableblockposition.immutable(); + } + } + } + } + } else { + for (int l1 = minBlockX; l1 < maxBlockX; ++l1) { + for (int i2 = minBlockY; i2 < maxBlockY; ++i2) { + for (int j2 = minBlockZ; j2 < maxBlockZ; ++j2) { + blockposition_mutableblockposition.set(l1, i2, j2); + FluidState fluid = this.level.getFluidState(blockposition_mutableblockposition); + + if (fluid.is(tag)) { + double d2 = (double) ((float) i2 + fluid.getHeight(this.level, blockposition_mutableblockposition)); + + if (d2 >= axisalignedbb.minY) { + flag1 = true; + d1 = Math.max(d2 - axisalignedbb.minY, d1); + if (flag) { + Vec3 vec3d1 = fluid.getFlow(this.level, blockposition_mutableblockposition); + + if (d1 < 0.4D) { + vec3d1 = vec3d1.scale(d1); + } + + vec3d = vec3d.add(vec3d1); + ++k1; + } + // CraftBukkit start - store last lava contact location + if (tag == FluidTags.LAVA) { + this.lastLavaContact = blockposition_mutableblockposition.immutable(); + } + // CraftBukkit end } - // CraftBukkit end } } } } } + // Leaves end if (vec3d.length() > 0.0D) { if (k1 > 0) { diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java index b0c9fce9d4e06cac139e341d218d0b6aac1f1943..f53fee91b78ba4c1e17360a40d5a94febd11eb21 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java @@ -27,6 +27,7 @@ public class LevelChunkSection { public final PalettedContainer states; // CraftBukkit start - read/write private PalettedContainer> biomes; + public short fluidStateCount; // Leaves public final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper public LevelChunkSection(int i, PalettedContainer datapaletteblock, PalettedContainer> palettedcontainerro) { @@ -198,6 +199,7 @@ public class LevelChunkSection { if (!fluid.isEmpty()) { --this.tickingFluidCount; + --this.fluidStateCount; // Leaves } if (!state.isAir()) { @@ -212,6 +214,7 @@ public class LevelChunkSection { if (!fluid1.isEmpty()) { ++this.tickingFluidCount; + --this.fluidStateCount; // Leaves } this.updateKnownBlockInfo(x | (z << 4) | (y << 8), iblockdata1, state); // Paper @@ -260,6 +263,7 @@ public class LevelChunkSection { if (fluid.isRandomlyTicking()) { this.tickingFluidCount = (short) (this.tickingFluidCount + 1); } + this.fluidStateCount++; // Leaves } }); diff --git a/src/main/java/top/leavesmc/leaves/LeavesConfig.java b/src/main/java/top/leavesmc/leaves/LeavesConfig.java index 1fc965f3f082ec4ab4c4d45458d9512998ebb57b..cbf22dc0723b623f44aab059644c439984e21ec4 100644 --- a/src/main/java/top/leavesmc/leaves/LeavesConfig.java +++ b/src/main/java/top/leavesmc/leaves/LeavesConfig.java @@ -369,6 +369,11 @@ public final class LeavesConfig { } } + public static boolean reduceEntityFluidLookup = true; + private static void reduceEntityFluidLookup() { + reduceEntityFluidLookup = getBoolean("settings.performance.reduce-entity-fluid-lookup", reduceEntityFluidLookup); + } + public static final class WorldConfig { public final String worldName;