From 636e70da8e3346178a38332ac05a7e2ea00a9e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=E1=BA=A7n=20Nguy=E1=BB=85n=20Ng=E1=BB=8Dc=20Quang?= <3d7777456@gmail.com> Date: Wed, 2 Oct 2024 05:13:54 +0700 Subject: [PATCH] Count fluids by their type to avoid unnecessary reads in Entity#updateFluidHeightAndDoFluidPushing We can take fluid counts in a chunk section into account to avoid unnecessary searches as we were only checking for non empty blocks. --- .../fabric/mixin/collisions/EntityMixin.java | 17 +++++ .../mixin/collisions/EntityMixin.java | 6 ++ .../LevelChunkSectionMixin.java | 74 +++++++++++++++++++ .../BlockCountingChunkSection.java | 6 ++ 4 files changed, 103 insertions(+) diff --git a/fabric/src/main/java/ca/spottedleaf/moonrise/fabric/mixin/collisions/EntityMixin.java b/fabric/src/main/java/ca/spottedleaf/moonrise/fabric/mixin/collisions/EntityMixin.java index bc489da3..0c017cbe 100644 --- a/fabric/src/main/java/ca/spottedleaf/moonrise/fabric/mixin/collisions/EntityMixin.java +++ b/fabric/src/main/java/ca/spottedleaf/moonrise/fabric/mixin/collisions/EntityMixin.java @@ -1,8 +1,10 @@ package ca.spottedleaf.moonrise.fabric.mixin.collisions; +import ca.spottedleaf.moonrise.patches.block_counting.BlockCountingChunkSection; import ca.spottedleaf.moonrise.patches.getblock.GetBlockLevel; import it.unimi.dsi.fastutil.objects.Object2DoubleMap; import net.minecraft.core.BlockPos; +import net.minecraft.tags.FluidTags; import net.minecraft.tags.TagKey; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; @@ -107,6 +109,21 @@ public boolean updateFluidHeightAndDoFluidPushing(final TagKey fluid, fin continue; } + final BlockCountingChunkSection blockCountingSection = (BlockCountingChunkSection)section; + final boolean hasFluids; + if (fluid == FluidTags.WATER) { + hasFluids = blockCountingSection.moonrise$hasWaterFluids(); + } else if (fluid == FluidTags.LAVA) { + hasFluids = blockCountingSection.moonrise$hasLavaFluids(); + } else { + hasFluids = blockCountingSection.moonrise$hasFluids(); + } + + if (!hasFluids) { + // also empty + continue; + } + final PalettedContainer blocks = section.states; final int minXIterate = currChunkX == minChunkX ? (minBlockX & 15) : 0; diff --git a/neoforge/src/main/java/ca/spottedleaf/moonrise/neoforge/mixin/collisions/EntityMixin.java b/neoforge/src/main/java/ca/spottedleaf/moonrise/neoforge/mixin/collisions/EntityMixin.java index 6e10f2f5..a51d0f3f 100644 --- a/neoforge/src/main/java/ca/spottedleaf/moonrise/neoforge/mixin/collisions/EntityMixin.java +++ b/neoforge/src/main/java/ca/spottedleaf/moonrise/neoforge/mixin/collisions/EntityMixin.java @@ -1,6 +1,7 @@ package ca.spottedleaf.moonrise.neoforge.mixin.collisions; import ca.spottedleaf.moonrise.neoforge.patches.collisions.FluidPushCalculation; +import ca.spottedleaf.moonrise.patches.block_counting.BlockCountingChunkSection; import ca.spottedleaf.moonrise.patches.getblock.GetBlockLevel; import it.unimi.dsi.fastutil.objects.Reference2ReferenceArrayMap; import it.unimi.dsi.fastutil.objects.Reference2ReferenceMap; @@ -101,6 +102,11 @@ public void updateFluidHeightAndDoFluidPushing() { continue; } + if (!((BlockCountingChunkSection)section).moonrise$hasFluids()) { + // also empty + continue; + } + final PalettedContainer blocks = section.states; final int minXIterate = currChunkX == minChunkX ? (minBlockX & 15) : 0; diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/block_counting/LevelChunkSectionMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/block_counting/LevelChunkSectionMixin.java index 990bd8f5..60189033 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/block_counting/LevelChunkSectionMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/block_counting/LevelChunkSectionMixin.java @@ -9,6 +9,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.shorts.ShortArrayList; import net.minecraft.util.BitStorage; +import net.minecraft.tags.FluidTags; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunkSection; import net.minecraft.world.level.chunk.Palette; @@ -64,6 +65,15 @@ abstract class LevelChunkSectionMixin implements BlockCountingChunkSection { @Unique private short specialCollidingBlocks; + @Unique + private short fluids; + + @Unique + private short lavaFluids; + + @Unique + private short waterFluids; + @Unique private final ShortList tickingBlocks = new ShortList(); @@ -77,6 +87,21 @@ abstract class LevelChunkSectionMixin implements BlockCountingChunkSection { return this.tickingBlocks; } + @Override + public final boolean moonrise$hasFluids() { + return this.fluids != 0; + } + + @Override + public final boolean moonrise$hasLavaFluids() { + return this.lavaFluids != 0; + } + + @Override + public final boolean moonrise$hasWaterFluids() { + return this.waterFluids != 0; + } + /** * @reason Callback used to update block counts on block change. * @author Spottedleaf @@ -122,6 +147,45 @@ private void updateBlockCallback(final int x, final int y, final int z, final Bl tickingBlocks.add(position); } } + + final FluidState oldFluid = oldState.getFluidState(); + final FluidState newFluid = newState.getFluidState(); + final boolean hasOldFluid = !oldFluid.isEmpty(); + final boolean hasNewFluid = !newFluid.isEmpty(); + if (hasOldFluid != hasNewFluid) { + if (hasOldFluid) { + --this.fluids; + } else { + ++this.fluids; + } + } + if (hasOldFluid || hasNewFluid) { + boolean fluidChecked = false; + final boolean isOldWater = oldFluid.is(FluidTags.WATER); + final boolean isNewWater = newFluid.is(FluidTags.WATER); + + if (isOldWater != isNewWater) { + if (isOldWater) { + --this.waterFluids; + } else { + ++this.waterFluids; + } + fluidChecked = true; + } + + if (!fluidChecked) { + final boolean isOldLava = oldFluid.is(FluidTags.LAVA); + final boolean isNewLava = newFluid.is(FluidTags.LAVA); + + if (isOldLava != isNewLava) { + if (isOldLava) { + --this.lavaFluids; + } else { + ++this.lavaFluids; + } + } + } + } } /** @@ -150,6 +214,9 @@ public void recalcBlockCounts() { this.tickingBlockCount = (short)0; this.tickingFluidCount = (short)0; this.specialCollidingBlocks = (short)0; + this.fluids = (short)0; + this.lavaFluids = (short)0; + this.waterFluids = (short)0; this.tickingBlocks.clear(); if (this.maybeHas((final BlockState state) -> !state.isAir())) { @@ -204,6 +271,13 @@ public void recalcBlockCounts() { if (fluid.isRandomlyTicking()) { this.tickingFluidCount += (short)paletteCount; } + this.fluids += (short)paletteCount; + + if (fluid.is(FluidTags.WATER)) { + this.waterFluids += (short)paletteCount; + } else if (fluid.is(FluidTags.LAVA)) { + this.lavaFluids += (short)paletteCount; + } } } } diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/block_counting/BlockCountingChunkSection.java b/src/main/java/ca/spottedleaf/moonrise/patches/block_counting/BlockCountingChunkSection.java index 0d1443a1..7c9a3f5e 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/block_counting/BlockCountingChunkSection.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/block_counting/BlockCountingChunkSection.java @@ -8,4 +8,10 @@ public interface BlockCountingChunkSection { public ShortList moonrise$getTickingBlockList(); + public boolean moonrise$hasFluids(); + + public boolean moonrise$hasLavaFluids(); + + public boolean moonrise$hasWaterFluids(); + }