Skip to content

Collision System

The Collision System detects and responds to collisions between entities and blocks. It uses swept collision detection for continuous movement and supports multiple collision types including solid, slide, trigger, and damage collisions.

com.hypixel.hytale.server.core.modules.collision

ClassDescription
CollisionModuleMain collision detection plugin, singleton
CollisionResultStores collision query results with pooled arrays
CollisionConfigPer-block collision configuration and world lookup
CollisionMaterialMaterial mask constants
BasicCollisionDataBase collision data with point and start parameter
BoxCollisionDataExtends BasicCollisionData, adds end parameter and normal
BlockCollisionDataExtends BoxCollisionData, adds block info
CharacterCollisionDataExtends BasicCollisionData, entity collision data
BlockContactDataContact data base for evaluators (normal, point, ground state)
MovingBoxBoxCollisionEvaluatorSwept (continuous) box collision detection
BoxBlockIntersectionEvaluatorStatic box-to-block intersection tests
CollisionMathAABB intersection math utilities
CollisionDataArrayPooled, sortable collision data list
BlockCollisionProviderBlock collision provider
EntityCollisionProviderEntity collision provider
IBlockCollisionConsumerCallback interface for collision events
IBlockCollisionEvaluatorInterface for collision evaluators
CollisionFilterFunctional interface for collision filtering
classDiagram
    BasicCollisionData <|-- BoxCollisionData
    BasicCollisionData <|-- CharacterCollisionData
    BoxCollisionData <|-- BlockCollisionData
    BlockContactData <|-- MovingBoxBoxCollisionEvaluator
    BlockContactData <|-- BoxBlockIntersectionEvaluator
    IBlockCollisionEvaluator <|.. MovingBoxBoxCollisionEvaluator
    IBlockCollisionEvaluator <|.. BoxBlockIntersectionEvaluator
    JavaPlugin <|-- CollisionModule

    class BasicCollisionData {
        +Vector3d collisionPoint
        +double collisionStart
    }
    class BoxCollisionData {
        +double collisionEnd
        +Vector3d collisionNormal
    }
    class BlockCollisionData {
        +int x, y, z
        +int blockId
        +BlockType blockType
        +BlockMaterial blockMaterial
        +boolean willDamage
    }
    class CharacterCollisionData {
        +Ref~EntityStore~ entityReference
        +boolean isPlayer
    }
    class BlockContactData {
        +Vector3d collisionNormal
        +Vector3d collisionPoint
        +double collisionStart
        +double collisionEnd
        +boolean onGround
        +boolean overlapping
    }

The central collision detection system. It extends JavaPlugin and is accessed as a singleton.

package com.hypixel.hytale.server.core.modules.collision;
public class CollisionModule extends JavaPlugin {
public static final int VALIDATE_INVALID = -1;
public static final int VALIDATE_OK = 0;
public static final int VALIDATE_ON_GROUND = 1;
public static final int VALIDATE_TOUCH_CEIL = 2;
public static CollisionModule get();
// returns true if far-distance (iterative) mode was used
public static boolean findCollisions(
Box collider,
Vector3d pos,
Vector3d v,
CollisionResult result,
ComponentAccessor<EntityStore> componentAccessor
);
// overload with stopOnCollisionFound flag
public static boolean findCollisions(
Box collider,
Vector3d pos,
Vector3d v,
boolean stopOnCollisionFound,
CollisionResult result,
ComponentAccessor<EntityStore> componentAccessor
);
// block collision (iterative, far distance)
public static void findBlockCollisionsIterative(
World world,
Box collider,
Vector3d pos,
Vector3d v,
boolean stopOnCollisionFound,
CollisionResult result
);
// block collision (direct, short distance)
public static void findBlockCollisionsShortDistance(
World world,
Box collider,
Vector3d pos,
Vector3d v,
CollisionResult result
);
// entity collision
public static void findCharacterCollisions(
Vector3d pos,
Vector3d v,
CollisionResult result,
ComponentAccessor<EntityStore> componentAccessor
);
// position validation (instance method, returns int status code)
public int validatePosition(
World world,
Box collider,
Vector3d pos,
CollisionResult result
);
// intersection detection (instance method)
public void findIntersections(
World world,
Box collider,
Vector3d pos,
CollisionResult result,
boolean triggerBlocks,
boolean intersections
);
// check if velocity is below movement threshold
public static boolean isBelowMovementThreshold(Vector3d v);
}

Stores all collision data from a query. Uses pooled CollisionDataArray instances for efficiency.

package com.hypixel.hytale.server.core.modules.collision;
public class CollisionResult implements BoxBlockIterator.BoxIterationConsumer {
// block collisions (solid blocks)
private final CollisionDataArray<BlockCollisionData> blockCollisions;
// block slides (walkable surfaces)
private final CollisionDataArray<BlockCollisionData> blockSlides;
// block triggers (sensor/damage blocks)
private final CollisionDataArray<BlockCollisionData> blockTriggers;
// entity collisions
private final CollisionDataArray<CharacterCollisionData> characterCollisions;
// evaluators
private final MovingBoxBoxCollisionEvaluator movingBoxBoxCollision;
private final BoxBlockIntersectionEvaluator boxBlockIntersection;
// slide state (computed by process())
public double slideStart;
public double slideEnd;
public boolean isSliding;
public CollisionResult();
public CollisionResult(boolean enableSlides, boolean enableCharacters);
// reset all arrays for reuse
public void reset();
// sort results by collision start parameter
public void process();
// block collision queries
public int getBlockCollisionCount();
public BlockCollisionData getBlockCollision(int i);
@Nullable public BlockCollisionData getFirstBlockCollision();
@Nullable public BlockCollisionData forgetFirstBlockCollision();
// character collision queries
public int getCharacterCollisionCount();
@Nullable public CharacterCollisionData getFirstCharacterCollision();
@Nullable public CharacterCollisionData forgetFirstCharacterCollision();
// trigger block queries
public CollisionDataArray<BlockCollisionData> getTriggerBlocks();
public void pruneTriggerBlocks(double distance);
// allocators
public BlockCollisionData newCollision();
public BlockCollisionData newSlide();
public BlockCollisionData newTrigger();
public CharacterCollisionData allocCharacterCollision();
// configuration
public CollisionConfig getConfig();
public BoxBlockIntersectionEvaluator getBoxBlockIntersection();
public MovingBoxBoxCollisionEvaluator getMovingBoxBoxCollision();
// collision entity management
public List<Entity> getCollisionEntities();
public void setCollisionEntities(List<Entity> collisionEntities);
// slide control
public void enableSlides();
public void disableSlides();
// character collision control
public boolean isCheckingForCharacterCollisions();
public void enableCharacterCollsions(); // note: typo in source
public void disableCharacterCollisions();
// trigger block control
public void enableTriggerBlocks();
public void disableTriggerBlocks();
public boolean isCheckingTriggerBlocks();
// damage block control
public void enableDamageBlocks();
public void disableDamageBlocks();
public boolean isCheckingDamageBlocks();
public boolean setDamageBlocking(boolean blocking);
public boolean isDamageBlocking();
// material-based collision control
public void setCollisionByMaterial(int collidingMaterials);
public void setCollisionByMaterial(int collidingMaterials, int walkableMaterials);
public int getCollisionByMaterial();
// walkable configuration
public void setDefaultWalkableBehaviour();
public void setWalkableByMaterial(int walkableMaterial);
public void setNonWalkablePredicate(Predicate<CollisionConfig> classifier);
// presets
public void setDefaultCollisionBehaviour();
public void setDefaultPlayerSettings();
// overlap computation
public boolean isComputeOverlaps();
public void setComputeOverlaps(boolean computeOverlaps);
}

The base class for all collision data. Stores the collision point and start parameter (0-1 range along movement vector).

public class BasicCollisionData {
public final Vector3d collisionPoint;
public double collisionStart;
public void setStart(Vector3d point, double start);
}

Extends BasicCollisionData with an end parameter and collision normal. Used as the base for block collisions.

public class BoxCollisionData extends BasicCollisionData {
public double collisionEnd;
public final Vector3d collisionNormal;
public void setEnd(double collisionEnd, Vector3d collisionNormal);
}

Full block collision information:

public class BlockCollisionData extends BoxCollisionData {
public int x; // block world X
public int y; // block world Y
public int z; // block world Z
public int blockId; // block type ID
public int rotation; // block rotation index
@Nullable public BlockType blockType;
@Nullable public BlockMaterial blockMaterial;
public int detailBoxIndex; // which detail hitbox was hit
public boolean willDamage; // block causes damage
public int fluidId; // fluid at this position
@Nullable public Fluid fluid;
public boolean touching;
public boolean overlapping;
public void setBlockData(CollisionConfig collisionConfig);
public void setDetailBoxIndex(int detailBoxIndex);
public void setTouchingOverlapping(boolean touching, boolean overlapping);
public void clear();
}

Entity collision data. Note: this extends BasicCollisionData directly, not BoxCollisionData — so it has no collisionEnd or collisionNormal.

public class CharacterCollisionData extends BasicCollisionData {
public Ref<EntityStore> entityReference;
public boolean isPlayer;
public void assign(
Vector3d collisionPoint,
double collisionVectorScale,
Ref<EntityStore> entityReference,
boolean isPlayer
);
}

Base class for both evaluators. Holds contact state like ground detection and collision geometry:

public class BlockContactData {
protected final Vector3d collisionNormal;
protected final Vector3d collisionPoint;
protected double collisionStart;
protected double collisionEnd;
protected boolean onGround;
protected boolean overlapping;
protected int damage;
protected boolean isSubmergeFluid;
public Vector3d getCollisionNormal();
public Vector3d getCollisionPoint();
public double getCollisionStart();
public double getCollisionEnd();
public boolean isOnGround();
public boolean isOverlapping();
public int getDamage();
public boolean isSubmergeFluid();
}

Interface that both evaluators implement:

public interface IBlockCollisionEvaluator {
double getCollisionStart();
void setCollisionData(BlockCollisionData data, CollisionConfig collisionConfig, int hitboxIndex);
}

Swept (continuous) collision detection between a moving box and stationary blocks. Extends BlockContactData and implements IBlockCollisionEvaluator.

public class MovingBoxBoxCollisionEvaluator extends BlockContactData
implements IBlockCollisionEvaluator {
public MovingBoxBoxCollisionEvaluator setCollider(Box collider);
// set movement origin and direction
public MovingBoxBoxCollisionEvaluator setMove(Vector3d pos, Vector3d v);
// test collision against a block bounding box at world position
public boolean isBoundingBoxColliding(Box blockBoundingBox, double x, double y, double z);
public boolean isTouching();
public void setCollisionEnd(double collisionEnd);
public void setCheckForOnGround(boolean checkForOnGround);
public boolean isCheckForOnGround();
public boolean isComputeOverlaps();
public void setComputeOverlaps(boolean computeOverlaps);
}

Static box-to-block intersection tests (used for short-distance and position validation). Extends BlockContactData and implements IBlockCollisionEvaluator.

public class BoxBlockIntersectionEvaluator extends BlockContactData
implements IBlockCollisionEvaluator {
// set the box and position
public BoxBlockIntersectionEvaluator setBox(Box box);
public BoxBlockIntersectionEvaluator setBox(Box box, Vector3d pos);
public BoxBlockIntersectionEvaluator setPosition(Vector3d pos);
public BoxBlockIntersectionEvaluator offsetPosition(Vector3d offset);
public BoxBlockIntersectionEvaluator expandBox(double radius);
public BoxBlockIntersectionEvaluator setStartEnd(double start, double end);
// returns int code (use CollisionMath to interpret)
public int intersectBox(Box otherBox, double x, double y, double z);
public int intersectBoxComputeTouch(Box otherBox, double x, double y, double z);
public int intersectBoxComputeOnGround(Box otherBox, double x, double y, double z);
// convenience
public boolean isBoxIntersecting(Box otherBox, double x, double y, double z);
public boolean isTouching();
public boolean touchesCeil();
}

AABB intersection utilities. All methods are static. This class cannot be instantiated.

public class CollisionMath {
// intersection code constants
public static final int DISJOINT = 0;
public static final int TOUCH_X = 1;
public static final int TOUCH_Y = 2;
public static final int TOUCH_Z = 4;
public static final int TOUCH_ANY = 7;
public static final int OVERLAP_X = 8;
public static final int OVERLAP_Y = 16;
public static final int OVERLAP_Z = 32;
public static final int OVERLAP_ALL = 56;
// interpret intersection codes
public static boolean isDisjoint(int code);
public static boolean isOverlapping(int code);
public static boolean isTouching(int code);
// AABB-AABB intersection (returns int code)
public static int intersectAABBs(
Vector3d p, Box bbP, Vector3d q, Box bbQ
);
public static int intersectAABBs(
double px, double py, double pz, Box bbP,
double qx, double qy, double qz, Box bbQ
);
// vector-AABB intersection
public static boolean intersectVectorAABB(
Vector3d pos, Vector3d vec,
double x, double y, double z,
Box box, Vector2d minMax
);
// ray-AABB intersection
public static boolean intersectRayAABB(
Vector3d pos, Vector3d ray,
double x, double y, double z,
Box box, Vector2d minMax
);
public static double intersectRayAABB(
Vector3d pos, Vector3d ray,
double x, double y, double z,
Box box
);
// swept AABB intersection (minkowski sum approach)
public static boolean intersectSweptAABBs(
Vector3d posP, Vector3d vP, Box p,
Vector3d posQ, Box q,
Vector2d minMax, Box temp
);
}

Block materials affect collision behavior. Defined in CollisionMaterial (and mirrored in CollisionConfig):

ConstantValueDescription
MATERIAL_EMPTY1No collision (air)
MATERIAL_FLUID2Fluid block (water, lava)
MATERIAL_SOLID4Solid collision
MATERIAL_SUBMERGED8Fully in fluid
MATERIAL_SET_ANY15All non-damage materials
MATERIAL_DAMAGE16Damage on contact
MATERIAL_SET_NONE0No materials

Callback interface for collision events:

public interface IBlockCollisionConsumer {
enum Result {
CONTINUE,
STOP,
STOP_NOW
}
Result onCollision(int x, int y, int z,
Vector3d pos, BlockContactData contactData,
BlockData blockData, Box hitbox);
Result probeCollisionDamage(int x, int y, int z,
Vector3d pos, BlockContactData contactData,
BlockData blockData);
void onCollisionDamage(int x, int y, int z,
Vector3d pos, BlockContactData contactData,
BlockData blockData);
Result onCollisionSliceFinished();
void onCollisionFinished();
}

A functional interface used for position validation filtering:

@FunctionalInterface
public interface CollisionFilter<D, T> {
boolean test(T t, int code, D data, CollisionConfig config);
}
flowchart TD
    A[findCollisions called] --> B{velocity below threshold?}
    B -->|Yes| C[findBlockCollisionsShortDistance]
    B -->|No| D[findBlockCollisionsIterative]
    C --> E{checking character collisions?}
    D --> E
    E -->|Yes| F[findCharacterCollisions]
    E -->|No| G[process and sort results]
    F --> G
    G --> H[return boolean: was far distance?]

Block Collision (Iterative / Far Distance)

Section titled “Block Collision (Iterative / Far Distance)”
flowchart TD
    A[Set up MovingBoxBoxCollisionEvaluator] --> B[Iterate blocks along movement path]
    B --> C{For each block: canCollide?}
    C -->|No| B
    C -->|Yes| D[isBoundingBoxColliding against block hitbox]
    D --> E{Detail boxes?}
    E -->|1 or fewer| F[processCollisionResult]
    E -->|Multiple| G[Test each detail box individually]
    G --> F
    F --> H{onGround and walkable?}
    H -->|Yes| I[Add as slide]
    H -->|No, but colliding| J[Add as collision]
    F --> K{canTrigger?}
    K -->|Yes| L[Add as trigger]
flowchart TD
    A[Set up BoxBlockIntersectionEvaluator] --> B[Iterate blocks at destination]
    B --> C{canCollide?}
    C -->|No| B
    C -->|Yes| D[intersectBoxComputeTouch]
    D --> E{isDisjoint?}
    E -->|Yes| B
    E -->|No| F[processCollision]
    F --> G{onGround and walkable?}
    G -->|Yes| H[Add as slide + maybe trigger]
    G -->|No, but colliding| I[Add as collision]
    F --> J{canTrigger and touching/colliding?}
    J -->|Yes| K[Add as trigger]
flowchart TD
    A[Get collision entities list from result] --> B{velocity above threshold?}
    B -->|No| C[Skip - no entity checks]
    B -->|Yes| D[For each entity in list]
    D --> E{Is projectile or dead?}
    E -->|Yes| D
    E -->|No| F[Get entity position + bounding box]
    F --> G[CollisionMath.intersectVectorAABB]
    G --> H{Intersection found?}
    H -->|Yes| I[allocCharacterCollision with point and entity ref]
    H -->|No| D

Standard blocking collision:

  • Stops movement at collision point
  • Returns collision normal for response
  • Used for walls, floors, ceilings

Walkable surface collision:

  • Detected when onGround is true and block material is walkable
  • Allows movement along surface
  • Used for slopes and stairs
  • Entity can slide along the surface

Non-blocking sensor collision:

  • Does not stop movement
  • Fires interaction events (CollisionEnter, Collision, CollisionLeave)
  • Used for pressure plates, zones, fluids

Harmful surface collision:

  • Blocks with damageToEntities > 0 or fluids with damage
  • Added as trigger blocks, damage amount tracked
  • Used for spikes, lava, etc.
import com.hypixel.hytale.server.core.modules.collision.CollisionModule;
import com.hypixel.hytale.server.core.modules.collision.CollisionResult;
import com.hypixel.hytale.math.shape.Box;
import com.hypixel.hytale.math.vector.Vector3d;
public boolean wouldCollide(Box entityBox, Vector3d position, Vector3d movement,
ComponentAccessor<EntityStore> accessor) {
CollisionResult result = new CollisionResult();
CollisionModule.findCollisions(
entityBox,
position,
movement,
result,
accessor
);
return result.getBlockCollisionCount() > 0;
}
public Vector3d clampMovement(Box entityBox, Vector3d position,
Vector3d movement, ComponentAccessor<EntityStore> accessor) {
CollisionResult result = new CollisionResult();
CollisionModule.findCollisions(entityBox, position, movement, result, accessor);
if (result.getBlockCollisionCount() > 0) {
BlockCollisionData first = result.getFirstBlockCollision();
double clampedT = first.collisionStart;
return movement.multiply(clampedT);
}
return movement;
}
public boolean isPositionValid(World world, Box entityBox, Vector3d position) {
CollisionResult result = new CollisionResult();
int code = CollisionModule.get().validatePosition(world, entityBox, position, result);
if (code == CollisionModule.VALIDATE_INVALID) {
return false;
}
boolean onGround = (code & CollisionModule.VALIDATE_ON_GROUND) != 0;
boolean touchCeil = (code & CollisionModule.VALIDATE_TOUCH_CEIL) != 0;
return true;
}
  1. Reuse CollisionResult: Call reset() instead of creating new instances — the pooled arrays avoid allocation overhead
  2. Choose appropriate method: Short-distance is used automatically when velocity is below threshold
  3. Check material masks: Use setCollisionByMaterial() and setWalkableByMaterial() to control what blocks collide
  4. Handle slides separately: Slides allow movement along walkable surfaces, collisions block
  5. Process triggers: Trigger blocks fire interaction events (CollisionEnter, Collision, CollisionLeave)
  6. Understand return types: findCollisions returns boolean (far distance flag), validatePosition returns int (status code)
  7. Instance vs static: findCollisions, findBlockCollisions*, and findCharacterCollisions are static; validatePosition and findIntersections are instance methods