Skip to content

Commit

Permalink
Properly check empty context-sensitive collision shape
Browse files Browse the repository at this point in the history
The emptyCollisionShape() function only checks whether the
cached collision shape (not the context-sensitive collision shape)
is empty. In places where we use the context-sensitive
collision, we need to check the context-sensitive shape instead.
  • Loading branch information
Spottedleaf committed Aug 29, 2024
1 parent 92e5f2c commit 0075519
Show file tree
Hide file tree
Showing 6 changed files with 23 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ protected BlockStateBaseMixin(Block object, Reference2ObjectArrayMap<Property<?>
private boolean emptyCollisionShape;

@Unique
private VoxelShape constantCollisionShape;
private boolean emptyConstantCollisionShape;

@Unique
private AABB constantAABBCollision;
private VoxelShape constantCollisionShape;

@Unique
private static void initCaches(final VoxelShape shape, final boolean neighbours) {
Expand Down Expand Up @@ -95,14 +95,13 @@ private void initCollisionState(final CallbackInfo ci) {
final VoxelShape collisionShape = this.cache.collisionShape;
try {
this.constantCollisionShape = this.getCollisionShape(null, null, null);
this.constantAABBCollision = this.constantCollisionShape == null ? null : ((CollisionVoxelShape)this.constantCollisionShape).moonrise$getSingleAABBRepresentation();
} catch (final Throwable throwable) {
// :(
this.constantCollisionShape = null;
this.constantAABBCollision = null;
}
this.occludesFullBlock = ((CollisionVoxelShape)collisionShape).moonrise$occludesFullBlock();
this.emptyCollisionShape = collisionShape.isEmpty();
this.emptyConstantCollisionShape = this.constantCollisionShape != null && this.constantCollisionShape.isEmpty();
// init caches
initCaches(collisionShape, true);
if (this.constantCollisionShape != null) {
Expand All @@ -116,8 +115,8 @@ private void initCollisionState(final CallbackInfo ci) {
} else {
this.occludesFullBlock = false;
this.emptyCollisionShape = false;
this.emptyConstantCollisionShape = false;
this.constantCollisionShape = null;
this.constantAABBCollision = null;
}
}

Expand All @@ -136,6 +135,11 @@ private void initCollisionState(final CallbackInfo ci) {
return this.emptyCollisionShape;
}

@Override
public final boolean moonrise$emptyContextCollisionShape() {
return this.emptyConstantCollisionShape;
}

@Override
public final int moonrise$uniqueId1() {
return this.id1;
Expand All @@ -147,12 +151,7 @@ private void initCollisionState(final CallbackInfo ci) {
}

@Override
public final VoxelShape moonrise$getConstantCollisionShape() {
public final VoxelShape moonrise$getConstantContextCollisionShape() {
return this.constantCollisionShape;
}

@Override
public final AABB moonrise$getConstantCollisionAABB() {
return this.constantAABBCollision;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,10 @@ private boolean clipsAnything(final Vec3 from, final Vec3 to,
}

final BlockState blockState = cachedBlock.blockState;
if (blockState != null && !((CollisionBlockState)blockState).moonrise$emptyCollisionShape()) {
if (blockState != null && !((CollisionBlockState)blockState).moonrise$emptyContextCollisionShape()) {
VoxelShape collision = cachedBlock.cachedCollisionShape;
if (collision == null) {
collision = ((CollisionBlockState)blockState).moonrise$getConstantCollisionShape();
collision = ((CollisionBlockState)blockState).moonrise$getConstantContextCollisionShape();
if (collision == null) {
collision = blockState.getCollisionShape(this.level, currPos, context);
if (!context.isDelegated()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.Mth;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.Level;
Expand Down Expand Up @@ -425,11 +424,11 @@ public Optional<BlockPos> findSupportingBlock(final Entity entity, final AABB aa
}

final BlockState state = ((GetBlockChunk)lastChunk).moonrise$getBlock(currX, currY, currZ);
if (((CollisionBlockState)state).moonrise$emptyCollisionShape()) {
if (((CollisionBlockState)state).moonrise$emptyContextCollisionShape()) {
continue;
}

VoxelShape blockCollision = ((CollisionBlockState)state).moonrise$getConstantCollisionShape();
VoxelShape blockCollision = ((CollisionBlockState)state).moonrise$getConstantContextCollisionShape();

if ((edgeCount != 1 || state.hasLargeCollisionShape()) && (edgeCount != 2 || state.getBlock() == Blocks.MOVING_PISTON)) {
if (collisionContext == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ private void queueTaskForSection(final int chunkX, final int chunkY, final int c

final ChunkAccess center = this.starlight$getLightEngine().getAnyChunkNow(chunkX, chunkZ);
if (center == null || !center.getPersistedStatus().isOrAfter(ChunkStatus.LIGHT)) {
// do not accept updates in unlit chunks, unless we might be generating a chunk. thanks to the amazing
// chunk scheduling, we could be lighting and generating a chunk at the same time
// do not accept updates in unlit chunks, unless we might be generating a chunk
return;
}

Expand All @@ -97,8 +96,8 @@ private void queueTaskForSection(final int chunkX, final int chunkY, final int c

@Override
public final int starlight$serverRelightChunks(final Collection<ChunkPos> chunks0,
final Consumer<ChunkPos> chunkLightCallback,
final IntConsumer onComplete) {
final Consumer<ChunkPos> chunkLightCallback,
final IntConsumer onComplete) {
final Set<ChunkPos> chunks = new LinkedHashSet<>(chunks0);
final Map<ChunkPos, Long> ticketIds = new HashMap<>();
final ServerLevel world = (ServerLevel)this.starlight$getLightEngine().getWorld();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2023,11 +2023,11 @@ public static boolean getCollisionsForBlocksOrWorldBorder(final Level world, fin

final BlockState blockData = blocks.get(localBlockIndex);

if (((CollisionBlockState)blockData).moonrise$emptyCollisionShape()) {
if (((CollisionBlockState)blockData).moonrise$emptyContextCollisionShape()) {
continue;
}

VoxelShape blockCollision = ((CollisionBlockState)blockData).moonrise$getConstantCollisionShape();
VoxelShape blockCollision = ((CollisionBlockState)blockData).moonrise$getConstantContextCollisionShape();

if (edgeCount == 0 || ((edgeCount != 1 || blockData.hasLargeCollisionShape()) && (edgeCount != 2 || blockData.getBlock() == Blocks.MOVING_PISTON))) {
if (blockCollision == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package ca.spottedleaf.moonrise.patches.collisions.block;

import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.shapes.VoxelShape;

public interface CollisionBlockState {
Expand All @@ -12,6 +11,9 @@ public interface CollisionBlockState {
// whether the cached collision shape exists and is empty
public boolean moonrise$emptyCollisionShape();

// whether the context-sensitive shape is constant and is empty
public boolean moonrise$emptyContextCollisionShape();

// indicates that occludesFullBlock is cached for the collision shape
public boolean moonrise$hasCache();

Expand All @@ -23,7 +25,5 @@ public interface CollisionBlockState {
// value is still unique
public int moonrise$uniqueId2();

public VoxelShape moonrise$getConstantCollisionShape();

public AABB moonrise$getConstantCollisionAABB();
public VoxelShape moonrise$getConstantContextCollisionShape();
}

0 comments on commit 0075519

Please sign in to comment.