From f32a08738ea92618a1e1d1146275da956a2b7f21 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Thu, 17 Oct 2024 18:02:22 -0700 Subject: [PATCH] Adjust min/max section optimizations (#55) * Change min/max section optimisations * Correctly init dimension type We need to initialise the field as early as possible in the constructor to avoid problems. Also, do not cache min/max section in EntityLookup. Note that mods that implement worlds with variable heights will not work still, as the entity slices expect a fixed height. * Cache calculated height values --------- Co-authored-by: Spottedleaf --- .../fabric/mixin/collisions/EntityMixin.java | 7 +- .../mixin/collisions/EntityMixin.java | 7 +- .../moonrise/common/util/WorldUtil.java | 8 ++ .../mixin/collisions/EntityMixin.java | 9 +- .../moonrise/mixin/collisions/LevelMixin.java | 8 +- .../moonrise/mixin/getblock/LevelMixin.java | 94 +++++++++++++------ .../level/entity/EntityLookup.java | 8 +- .../patches/collisions/CollisionUtil.java | 6 +- .../patches/getblock/GetBlockLevel.java | 13 --- 9 files changed, 92 insertions(+), 68 deletions(-) delete mode 100644 src/main/java/ca/spottedleaf/moonrise/patches/getblock/GetBlockLevel.java 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..87306ca5 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,6 +1,6 @@ package ca.spottedleaf.moonrise.fabric.mixin.collisions; -import ca.spottedleaf.moonrise.patches.getblock.GetBlockLevel; +import ca.spottedleaf.moonrise.common.util.WorldUtil; import it.unimi.dsi.fastutil.objects.Object2DoubleMap; import net.minecraft.core.BlockPos; import net.minecraft.tags.TagKey; @@ -9,7 +9,6 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkSource; import net.minecraft.world.level.chunk.LevelChunkSection; import net.minecraft.world.level.chunk.PalettedContainer; @@ -61,7 +60,7 @@ public boolean updateFluidHeightAndDoFluidPushing(final TagKey fluid, fin final AABB boundingBox = this.getBoundingBox().deflate(1.0E-3); final Level world = this.level; - final int minSection = ((GetBlockLevel)world).moonrise$getMinSection(); + final int minSection = WorldUtil.getMinSection(world); final int minBlockX = Mth.floor(boundingBox.minX); final int minBlockY = Math.max((minSection << 4), Mth.floor(boundingBox.minY)); @@ -69,7 +68,7 @@ public boolean updateFluidHeightAndDoFluidPushing(final TagKey fluid, fin // note: bounds are exclusive in Vanilla, so we subtract 1 - our loop expects bounds to be inclusive final int maxBlockX = Mth.ceil(boundingBox.maxX) - 1; - final int maxBlockY = Math.min((((GetBlockLevel)world).moonrise$getMaxSection() << 4) | 15, Mth.ceil(boundingBox.maxY) - 1); + final int maxBlockY = Math.min((WorldUtil.getMaxSection(world) << 4) | 15, Mth.ceil(boundingBox.maxY) - 1); final int maxBlockZ = Mth.ceil(boundingBox.maxZ) - 1; final boolean isPushable = this.isPushedByFluid(); 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..3ef2f9f3 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,7 +1,7 @@ package ca.spottedleaf.moonrise.neoforge.mixin.collisions; +import ca.spottedleaf.moonrise.common.util.WorldUtil; import ca.spottedleaf.moonrise.neoforge.patches.collisions.FluidPushCalculation; -import ca.spottedleaf.moonrise.patches.getblock.GetBlockLevel; import it.unimi.dsi.fastutil.objects.Reference2ReferenceArrayMap; import it.unimi.dsi.fastutil.objects.Reference2ReferenceMap; import net.minecraft.core.BlockPos; @@ -10,7 +10,6 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkSource; import net.minecraft.world.level.chunk.LevelChunkSection; import net.minecraft.world.level.chunk.PalettedContainer; @@ -59,7 +58,7 @@ public void updateFluidHeightAndDoFluidPushing() { final AABB boundingBox = this.getBoundingBox().deflate(1.0E-3); final Level world = this.level; - final int minSection = ((GetBlockLevel)world).moonrise$getMinSection(); + final int minSection = WorldUtil.getMinSection(world); final int minBlockX = Mth.floor(boundingBox.minX); final int minBlockY = Math.max((minSection << 4), Mth.floor(boundingBox.minY)); @@ -67,7 +66,7 @@ public void updateFluidHeightAndDoFluidPushing() { // note: bounds are exclusive in Vanilla, so we subtract 1 final int maxBlockX = Mth.ceil(boundingBox.maxX) - 1; - final int maxBlockY = Math.min((((GetBlockLevel)world).moonrise$getMaxSection() << 4) | 15, Mth.ceil(boundingBox.maxY) - 1); + final int maxBlockY = Math.min((WorldUtil.getMaxSection(world) << 4) | 15, Mth.ceil(boundingBox.maxY) - 1); final int maxBlockZ = Mth.ceil(boundingBox.maxZ) - 1; final BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos(); diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/WorldUtil.java b/src/main/java/ca/spottedleaf/moonrise/common/util/WorldUtil.java index 8e307016..0b24eba5 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/util/WorldUtil.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/util/WorldUtil.java @@ -11,10 +11,18 @@ public static int getMaxSection(final LevelHeightAccessor world) { return world.getMaxSection() - 1; // getMaxSection() is exclusive } + public static int getMaxSection(final Level world) { + return world.getMaxSection() - 1; // getMaxSection() is exclusive + } + public static int getMinSection(final LevelHeightAccessor world) { return world.getMinSection(); } + public static int getMinSection(final Level world) { + return world.getMinSection(); + } + public static int getMaxLightSection(final LevelHeightAccessor world) { return getMaxSection(world) + 1; } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/EntityMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/EntityMixin.java index f051ab0b..0865fa8c 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/EntityMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/EntityMixin.java @@ -1,11 +1,11 @@ package ca.spottedleaf.moonrise.mixin.collisions; +import ca.spottedleaf.moonrise.common.util.WorldUtil; import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel; import ca.spottedleaf.moonrise.patches.collisions.CollisionUtil; import ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState; import ca.spottedleaf.moonrise.patches.collisions.shape.CollisionVoxelShape; import ca.spottedleaf.moonrise.patches.collisions.util.NoneMatchStream; -import ca.spottedleaf.moonrise.patches.getblock.GetBlockLevel; import it.unimi.dsi.fastutil.floats.FloatArraySet; import it.unimi.dsi.fastutil.floats.FloatArrays; import net.minecraft.core.BlockPos; @@ -16,7 +16,6 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkSource; import net.minecraft.world.level.chunk.LevelChunkSection; import net.minecraft.world.level.chunk.PalettedContainer; @@ -222,7 +221,7 @@ public boolean isInWall() { final int maxChunkY = maxBlockY >> 4; final int maxChunkZ = maxBlockZ >> 4; - final int minSection = ((GetBlockLevel)world).moonrise$getMinSection(); + final int minSection = WorldUtil.getMinSection(world); final ChunkSource chunkSource = world.getChunkSource(); final BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos(); @@ -331,7 +330,7 @@ private Stream avoidStreams(final Level world, final AABB boundingBox) { return new NoneMatchStream<>(true); } - final int minSection = ((GetBlockLevel)world).moonrise$getMinSection(); + final int minSection = WorldUtil.getMinSection(world); final ChunkSource chunkSource = world.getChunkSource(); for (int currChunkZ = minChunkZ; currChunkZ <= maxChunkZ; ++currChunkZ) { @@ -406,7 +405,7 @@ public void checkInsideBlocks() { return; } - final int minSection = ((GetBlockLevel)world).moonrise$getMinSection(); + final int minSection = WorldUtil.getMinSection(world); final ChunkSource chunkSource = world.getChunkSource(); final BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos(); diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/LevelMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/LevelMixin.java index 43865436..845dca89 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/LevelMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/LevelMixin.java @@ -1,10 +1,10 @@ package ca.spottedleaf.moonrise.mixin.collisions; +import ca.spottedleaf.moonrise.common.util.WorldUtil; import ca.spottedleaf.moonrise.patches.block_counting.BlockCountingChunkSection; import ca.spottedleaf.moonrise.patches.collisions.CollisionUtil; import ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState; import ca.spottedleaf.moonrise.patches.collisions.shape.CollisionVoxelShape; -import ca.spottedleaf.moonrise.patches.getblock.GetBlockLevel; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.util.Mth; @@ -139,7 +139,7 @@ private static BlockHitResult fastClip(final Vec3 from, final Vec3 to, final Lev int lastChunkY = Integer.MIN_VALUE; int lastChunkZ = Integer.MIN_VALUE; - final int minSection = ((GetBlockLevel)level).moonrise$getMinSection(); + final int minSection = WorldUtil.getMinSection(level); for (;;) { currPos.set(currX, currY, currZ); @@ -334,13 +334,13 @@ public Optional findFreePosition(final Entity entity, final VoxelShape bou */ @Override public Optional findSupportingBlock(final Entity entity, final AABB aabb) { - final int minSection = ((GetBlockLevel)(Level)(Object)this).moonrise$getMinSection(); + final int minSection = WorldUtil.getMinSection((Level)(Object)this); final int minBlockX = Mth.floor(aabb.minX - CollisionUtil.COLLISION_EPSILON) - 1; final int maxBlockX = Mth.floor(aabb.maxX + CollisionUtil.COLLISION_EPSILON) + 1; final int minBlockY = Math.max((minSection << 4) - 1, Mth.floor(aabb.minY - CollisionUtil.COLLISION_EPSILON) - 1); - final int maxBlockY = Math.min((((GetBlockLevel)(Level)(Object)this).moonrise$getMaxSection() << 4) + 16, Mth.floor(aabb.maxY + CollisionUtil.COLLISION_EPSILON) + 1); + final int maxBlockY = Math.min((WorldUtil.getMaxSection((Level)(Object)this) << 4) + 16, Mth.floor(aabb.maxY + CollisionUtil.COLLISION_EPSILON) + 1); final int minBlockZ = Mth.floor(aabb.minZ - CollisionUtil.COLLISION_EPSILON) - 1; final int maxBlockZ = Mth.floor(aabb.maxZ + CollisionUtil.COLLISION_EPSILON) + 1; diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/getblock/LevelMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/getblock/LevelMixin.java index bb75901f..573f5ea2 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/getblock/LevelMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/getblock/LevelMixin.java @@ -1,10 +1,11 @@ package ca.spottedleaf.moonrise.mixin.getblock; -import ca.spottedleaf.moonrise.common.util.WorldUtil; -import ca.spottedleaf.moonrise.patches.getblock.GetBlockLevel; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.dimension.DimensionType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -13,13 +14,10 @@ // Higher priority to apply after Lithium mixin.world.inline_height.WorldMixin @Mixin(value = Level.class, priority = 1100) -abstract class LevelMixin implements GetBlockLevel, LevelAccessor, AutoCloseable { +abstract class LevelMixin implements LevelAccessor, AutoCloseable { @Unique - private int minSection; - - @Unique - private int maxSection; + private int height; @Unique private int minBuildHeight; @@ -27,41 +25,59 @@ abstract class LevelMixin implements GetBlockLevel, LevelAccessor, AutoCloseable @Unique private int maxBuildHeight; - @Override - public final int moonrise$getMinSection() { - return this.minSection; + @Unique + private int minSection; + + @Unique + private int maxSection; + + @Unique + private int sectionsCount; + + /** + * @reason Init min/max section + * @author Spottedleaf + */ + @Inject( + method = "", + at = @At( + value = "CTOR_HEAD" + ) + ) + private void init(final CallbackInfo ci, + @Local(ordinal = 0, argsOnly = true) final Holder dimensionTypeHolder) { + final DimensionType dimType = dimensionTypeHolder.value(); + this.height = dimType.height(); + this.minBuildHeight = dimType.minY(); + this.maxBuildHeight = this.minBuildHeight + this.height; + this.minSection = this.minBuildHeight >> 4; + this.maxSection = ((this.maxBuildHeight - 1) >> 4) + 1; + this.sectionsCount = this.maxSection - this.minSection; } @Override - public final int moonrise$getMaxSection() { - return this.maxSection; + public int getHeight() { + return this.height; } @Override - public final int moonrise$getMinBuildHeight() { + public int getMinBuildHeight() { return this.minBuildHeight; } @Override - public final int moonrise$getMaxBuildHeight() { + public int getMaxBuildHeight() { return this.maxBuildHeight; } - /** - * @reason Init min/max section - * @author Spottedleaf - */ - @Inject( - method = "", - at = @At( - value = "RETURN" - ) - ) - private void init(final CallbackInfo ci) { - this.minSection = WorldUtil.getMinSection(this); - this.maxSection = WorldUtil.getMaxSection(this); - this.minBuildHeight = this.getMinBuildHeight(); - this.maxBuildHeight = this.getMaxBuildHeight(); + @Override + public int getMinSection() { + return this.minSection; + } + + @Override + public int getMaxSection() { + return this.maxSection; } @Override @@ -73,4 +89,24 @@ public boolean isOutsideBuildHeight(final int y) { public boolean isOutsideBuildHeight(final BlockPos blockPos) { return this.isOutsideBuildHeight(blockPos.getY()); } + + @Override + public int getSectionIndex(final int blockY) { + return (blockY >> 4) - this.minSection; + } + + @Override + public int getSectionIndexFromSectionY(final int sectionY) { + return sectionY - this.minSection; + } + + @Override + public int getSectionYFromSectionIndex(final int sectionIdx) { + return sectionIdx + this.minSection; + } + + @Override + public int getSectionsCount() { + return this.sectionsCount; + } } diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java index 87d83ea9..a147667b 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java @@ -46,8 +46,6 @@ public abstract class EntityLookup implements LevelEntityGetter { protected final SWMRLong2ObjectHashTable regions = new SWMRLong2ObjectHashTable<>(128, 0.5f); - protected final int minSection; // inclusive - protected final int maxSection; // inclusive protected final LevelCallback worldCallback; protected final ConcurrentLong2ReferenceChainedHashTable entityById = new ConcurrentLong2ReferenceChainedHashTable<>(); @@ -56,8 +54,6 @@ public abstract class EntityLookup implements LevelEntityGetter { public EntityLookup(final Level world, final LevelCallback worldCallback) { this.world = world; - this.minSection = WorldUtil.getMinSection(world); - this.maxSection = WorldUtil.getMaxSection(world); this.worldCallback = worldCallback; } @@ -404,7 +400,7 @@ public static Visibility getEntityStatus(final Entity entity) { protected boolean addEntity(final Entity entity, final boolean fromDisk, final boolean event) { final BlockPos pos = entity.blockPosition(); final int sectionX = pos.getX() >> 4; - final int sectionY = Mth.clamp(pos.getY() >> 4, this.minSection, this.maxSection); + final int sectionY = Mth.clamp(pos.getY() >> 4, WorldUtil.getMinSection(this.world), WorldUtil.getMaxSection(this.world)); final int sectionZ = pos.getZ() >> 4; this.checkThread(sectionX, sectionZ, "Cannot add entity off-main thread"); @@ -523,7 +519,7 @@ protected ChunkEntitySlices moveEntity(final Entity entity) { final int sectionZ = ((ChunkSystemEntity)entity).moonrise$getSectionZ(); final BlockPos newPos = entity.blockPosition(); final int newSectionX = newPos.getX() >> 4; - final int newSectionY = Mth.clamp(newPos.getY() >> 4, this.minSection, this.maxSection); + final int newSectionY = Mth.clamp(newPos.getY() >> 4, WorldUtil.getMinSection(this.world), WorldUtil.getMaxSection(this.world)); final int newSectionZ = newPos.getZ() >> 4; if (newSectionX == sectionX && newSectionY == sectionY && newSectionZ == sectionZ) { diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java b/src/main/java/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java index 6a5907ec..18608d35 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java @@ -1,12 +1,12 @@ package ca.spottedleaf.moonrise.patches.collisions; +import ca.spottedleaf.moonrise.common.util.WorldUtil; import ca.spottedleaf.moonrise.patches.chunk_system.world.ChunkSystemEntityGetter; import ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState; import ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity; import ca.spottedleaf.moonrise.patches.collisions.shape.CachedShapeData; import ca.spottedleaf.moonrise.patches.collisions.shape.CollisionDiscreteVoxelShape; import ca.spottedleaf.moonrise.patches.collisions.shape.CollisionVoxelShape; -import ca.spottedleaf.moonrise.patches.getblock.GetBlockLevel; import ca.spottedleaf.moonrise.patches.block_counting.BlockCountingChunkSection; import it.unimi.dsi.fastutil.doubles.DoubleArrayList; import it.unimi.dsi.fastutil.doubles.DoubleList; @@ -1934,13 +1934,13 @@ public static boolean getCollisionsForBlocksOrWorldBorder(final Level world, fin } } - final int minSection = ((GetBlockLevel)world).moonrise$getMinSection(); + final int minSection = WorldUtil.getMinSection(world); final int minBlockX = Mth.floor(aabb.minX - COLLISION_EPSILON) - 1; final int maxBlockX = Mth.floor(aabb.maxX + COLLISION_EPSILON) + 1; final int minBlockY = Math.max((minSection << 4) - 1, Mth.floor(aabb.minY - COLLISION_EPSILON) - 1); - final int maxBlockY = Math.min((((GetBlockLevel)world).moonrise$getMaxSection() << 4) + 16, Mth.floor(aabb.maxY + COLLISION_EPSILON) + 1); + final int maxBlockY = Math.min((WorldUtil.getMaxSection(world) << 4) + 16, Mth.floor(aabb.maxY + COLLISION_EPSILON) + 1); final int minBlockZ = Mth.floor(aabb.minZ - COLLISION_EPSILON) - 1; final int maxBlockZ = Mth.floor(aabb.maxZ + COLLISION_EPSILON) + 1; diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/getblock/GetBlockLevel.java b/src/main/java/ca/spottedleaf/moonrise/patches/getblock/GetBlockLevel.java deleted file mode 100644 index 14cfcf4c..00000000 --- a/src/main/java/ca/spottedleaf/moonrise/patches/getblock/GetBlockLevel.java +++ /dev/null @@ -1,13 +0,0 @@ -package ca.spottedleaf.moonrise.patches.getblock; - -public interface GetBlockLevel { - - public int moonrise$getMinSection(); - - public int moonrise$getMaxSection(); - - public int moonrise$getMinBuildHeight(); - - public int moonrise$getMaxBuildHeight(); - -}