diff --git a/sable_rapier/src/main/java/dev/ryanhcode/sable/physics/impl/rapier/collider/RapierVoxelColliderBakery.java b/sable_rapier/src/main/java/dev/ryanhcode/sable/physics/impl/rapier/collider/RapierVoxelColliderBakery.java index f4baf892..6f84f864 100644 --- a/sable_rapier/src/main/java/dev/ryanhcode/sable/physics/impl/rapier/collider/RapierVoxelColliderBakery.java +++ b/sable_rapier/src/main/java/dev/ryanhcode/sable/physics/impl/rapier/collider/RapierVoxelColliderBakery.java @@ -1,5 +1,6 @@ package dev.ryanhcode.sable.physics.impl.rapier.collider; +import dev.ryanhcode.sable.Sable; import dev.ryanhcode.sable.api.block.BlockSubLevelCollisionShape; import dev.ryanhcode.sable.api.block.BlockWithSubLevelCollisionCallback; import dev.ryanhcode.sable.api.physics.callback.BlockSubLevelCollisionCallback; @@ -13,6 +14,7 @@ import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -66,15 +68,7 @@ public RapierVoxelColliderBakery(@NotNull final BlockGetter blockGetter) { return entry; } - final VoxelShape shape; - - this.level.setup(childState); - if (childState.getBlock() instanceof final BlockSubLevelCollisionShape extension) { - shape = extension.getSubLevelCollisionShape(this.level, childState); - } else { - shape = childState.getCollisionShape(this.level, BlockPos.ZERO, SableCollisionContext.get()); - } - this.level.setup(Blocks.AIR.defaultBlockState()); + final VoxelShape shape = this.getCollisionShapeOrFallback(childState); if (shape.isEmpty()) { return RapierVoxelColliderData.EMPTY; @@ -92,6 +86,38 @@ public RapierVoxelColliderBakery(@NotNull final BlockGetter blockGetter) { return entry; } + private @NotNull VoxelShape getCollisionShapeOrFallback(final BlockState childState) { + try { + this.level.setup(childState); + + final VoxelShape shape; + if (childState.getBlock() instanceof final BlockSubLevelCollisionShape extension) { + shape = extension.getSubLevelCollisionShape(this.level, childState); + } else { + shape = childState.getCollisionShape(this.level, BlockPos.ZERO, SableCollisionContext.get()); + } + + if (shape == null) { + Sable.LOGGER.warn( + "Block state {} returned a null collision shape. Falling back to a full block collision shape.", + childState + ); + return Shapes.block(); + } + + return shape; + } catch (final Exception exception) { + Sable.LOGGER.warn( + "Failed to get collision shape for block state {}. Falling back to a full block collision shape.", + childState, + exception + ); + return Shapes.block(); + } finally { + this.level.setup(Blocks.AIR.defaultBlockState()); + } + } + /** * Builds / gets a saved box or compound collision shape for a block *