From 2e52db6e932abc310a3bbaa391ab492a5486847e Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sat, 27 Jul 2024 12:43:48 -0400 Subject: [PATCH] Apply some simple optimizations for vanilla section meshing --- .../perf/chunk_meshing/RebuildTaskMixin.java | 31 +++++++++++++++ .../blockpos/SectionBlockPosIterator.java | 39 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/chunk_meshing/RebuildTaskMixin.java create mode 100644 common/src/main/java/org/embeddedt/modernfix/util/blockpos/SectionBlockPosIterator.java diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/chunk_meshing/RebuildTaskMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/chunk_meshing/RebuildTaskMixin.java new file mode 100644 index 00000000..b10b557b --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/chunk_meshing/RebuildTaskMixin.java @@ -0,0 +1,31 @@ +package org.embeddedt.modernfix.common.mixin.perf.chunk_meshing; + +import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.client.renderer.chunk.RenderChunkRegion; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.state.BlockState; +import org.embeddedt.modernfix.util.blockpos.SectionBlockPosIterator; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(targets = { "net/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk$RebuildTask"}, priority = 2000) +public class RebuildTaskMixin { + /** + * @author embeddedt + * @reason Use a much faster iterator implementation than vanilla's Guava-based one. + */ + @Redirect(method = "compile", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/BlockPos;betweenClosed(Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/BlockPos;)Ljava/lang/Iterable;")) + private Iterable fastBetweenClosed(BlockPos firstPos, BlockPos secondPos) { + return () -> new SectionBlockPosIterator(firstPos); + } + + /** + * @author embeddedt + * @reason RenderChunkRegion.getBlockState is expensive, avoid calling it multiple times for the same position + */ + @Redirect(method = "compile", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/chunk/RenderChunkRegion;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;", ordinal = 1)) + private BlockState useExistingBlockState(RenderChunkRegion instance, BlockPos pos, @Local(ordinal = 0) BlockState state) { + return state; + } +} diff --git a/common/src/main/java/org/embeddedt/modernfix/util/blockpos/SectionBlockPosIterator.java b/common/src/main/java/org/embeddedt/modernfix/util/blockpos/SectionBlockPosIterator.java new file mode 100644 index 00000000..3521680d --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/util/blockpos/SectionBlockPosIterator.java @@ -0,0 +1,39 @@ +package org.embeddedt.modernfix.util.blockpos; + +import net.minecraft.core.BlockPos; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class SectionBlockPosIterator implements Iterator { + private final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); + private int index = 0; + private final int baseX, baseY, baseZ; + + public SectionBlockPosIterator(int baseX, int baseY, int baseZ) { + this.baseX = baseX; + this.baseY = baseY; + this.baseZ = baseZ; + } + + public SectionBlockPosIterator(BlockPos pos) { + this(pos.getX(), pos.getY(), pos.getZ()); + } + + @Override + public boolean hasNext() { + return index < 4096; + } + + @Override + public BlockPos next() { + int i = index; + if (i >= 4096) { + throw new NoSuchElementException(); + } + index = i + 1; + var pos = this.pos; + pos.set(this.baseX + (i & 15), this.baseY + ((i >> 8) & 15), this.baseZ + ((i >> 4) & 15)); + return pos; + } +}