9
0
mirror of https://github.com/LeavesMC/Leaves.git synced 2025-12-19 14:59:32 +00:00
Files
LeavesMC/patches/server/0042-Reduce-entity-fluid-lookups-if-no-fluids.patch
2023-03-19 17:30:46 +08:00

235 lines
13 KiB
Diff

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 06709144f1cd70889e358e4e4a0b0c3a92ac0f7d..3229d81fa7e30f47a7bbee2be109b9d69d973dfb 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -4162,16 +4162,18 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
}
public boolean updateFluidHeightAndDoFluidPushing(TagKey<Fluid> 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;
@@ -4179,38 +4181,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<BlockState> 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 1b80a91fa36c59a31b57ef7ef4a68eacbb0f17f5..62f4e7a2dcd93a5b11fb9f847c70da1bced71015 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<BlockState> states;
// CraftBukkit start - read/write
private PalettedContainer<Holder<Biome>> 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<BlockState> datapaletteblock, PalettedContainer<Holder<Biome>> 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 224ff765c57b65cea7dd46806ed57e82da42a3f8..ac919b7b128e23c12e00956974220872cc3a4848 100644
--- a/src/main/java/top/leavesmc/leaves/LeavesConfig.java
+++ b/src/main/java/top/leavesmc/leaves/LeavesConfig.java
@@ -373,6 +373,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;