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 block) { return ShapeImpl.parseBlockFromRegistry(str, block); } }