package net.minestom.server.collision; import net.minestom.server.coordinate.Pos; import net.minestom.server.coordinate.Vec; import net.minestom.server.entity.Entity; import net.minestom.server.instance.Instance; import net.minestom.server.instance.WorldBorder; import net.minestom.server.instance.block.Block; import net.minestom.server.item.Material; import net.minestom.server.utils.chunk.ChunkCache; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.function.Supplier; @ApiStatus.Internal @ApiStatus.Experimental public final class CollisionUtils { /** * Moves an entity with physics applied (ie checking against blocks) *
* Works by getting all the full blocks that an entity could interact with.
* All bounding boxes inside the full blocks are checked for collisions with the entity.
*
* @param entity the entity to move
* @return the result of physics simulation
*/
public static PhysicsResult handlePhysics(@NotNull Entity entity, @NotNull Vec entityVelocity,
@Nullable PhysicsResult lastPhysicsResult) {
final BoundingBox boundingBox = entity.getBoundingBox();
final Pos currentPosition = entity.getPosition();
final Block.Getter getter = new ChunkCache(entity.getInstance(), entity.getChunk(), Block.STONE);
return BlockCollision.handlePhysics(boundingBox,
entityVelocity, currentPosition,
getter, lastPhysicsResult);
}
public static PhysicsResult handlePhysics(@NotNull Entity entity, @NotNull Vec entityVelocity) {
return handlePhysics(entity, entityVelocity, null);
}
/**
* Applies world border collision.
*
* @param instance the instance where the world border is
* @param currentPosition the current position
* @param newPosition the future target position
* @return the position with the world border collision applied (can be {@code newPosition} if not changed)
*/
public static @NotNull Pos applyWorldBorder(@NotNull Instance instance,
@NotNull Pos currentPosition, @NotNull Pos newPosition) {
final WorldBorder worldBorder = instance.getWorldBorder();
final WorldBorder.CollisionAxis collisionAxis = worldBorder.getCollisionAxis(newPosition);
return switch (collisionAxis) {
case NONE ->
// Apply velocity + gravity
newPosition;
case BOTH ->
// Apply Y velocity/gravity
new Pos(currentPosition.x(), newPosition.y(), currentPosition.z());
case X ->
// Apply Y/Z velocity/gravity
new Pos(currentPosition.x(), newPosition.y(), newPosition.z());
case Z ->
// Apply X/Y velocity/gravity
new Pos(newPosition.x(), newPosition.y(), currentPosition.z());
};
}
public static Shape parseBlockShape(String str, Supplier