Skip to content

Commit

Permalink
Adjust min/max section optimizations (#55)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
jpenilla and Spottedleaf authored Oct 18, 2024
1 parent 56e48ed commit f32a087
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 68 deletions.
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -61,15 +60,15 @@ public boolean updateFluidHeightAndDoFluidPushing(final TagKey<Fluid> 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));
final int minBlockZ = Mth.floor(boundingBox.minZ);

// 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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -59,15 +58,15 @@ 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));
final int minBlockZ = Mth.floor(boundingBox.minZ);

// 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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -331,7 +330,7 @@ private <T> Stream<T> 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) {
Expand Down Expand Up @@ -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();

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -334,13 +334,13 @@ public Optional<Vec3> findFreePosition(final Entity entity, final VoxelShape bou
*/
@Override
public Optional<BlockPos> 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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -13,55 +14,70 @@

// 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;

@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 = "<init>",
at = @At(
value = "CTOR_HEAD"
)
)
private void init(final CallbackInfo ci,
@Local(ordinal = 0, argsOnly = true) final Holder<DimensionType> 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 = "<init>",
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
Expand All @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ public abstract class EntityLookup implements LevelEntityGetter<Entity> {

protected final SWMRLong2ObjectHashTable<ChunkSlicesRegion> regions = new SWMRLong2ObjectHashTable<>(128, 0.5f);

protected final int minSection; // inclusive
protected final int maxSection; // inclusive
protected final LevelCallback<Entity> worldCallback;

protected final ConcurrentLong2ReferenceChainedHashTable<Entity> entityById = new ConcurrentLong2ReferenceChainedHashTable<>();
Expand All @@ -56,8 +54,6 @@ public abstract class EntityLookup implements LevelEntityGetter<Entity> {

public EntityLookup(final Level world, final LevelCallback<Entity> worldCallback) {
this.world = world;
this.minSection = WorldUtil.getMinSection(world);
this.maxSection = WorldUtil.getMaxSection(world);
this.worldCallback = worldCallback;
}

Expand Down Expand Up @@ -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");

Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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;
Expand Down

This file was deleted.

0 comments on commit f32a087

Please sign in to comment.