Collision System
Collision System
Section titled “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.
Package Location
Section titled “Package Location”com.hypixel.hytale.server.core.modules.collision
Core Classes
Section titled “Core Classes”| Class | Description |
|---|---|
CollisionModule | Main collision detection plugin, singleton |
CollisionResult | Stores collision query results with pooled arrays |
CollisionConfig | Per-block collision configuration and world lookup |
CollisionMaterial | Material mask constants |
BasicCollisionData | Base collision data with point and start parameter |
BoxCollisionData | Extends BasicCollisionData, adds end parameter and normal |
BlockCollisionData | Extends BoxCollisionData, adds block info |
CharacterCollisionData | Extends BasicCollisionData, entity collision data |
BlockContactData | Contact data base for evaluators (normal, point, ground state) |
MovingBoxBoxCollisionEvaluator | Swept (continuous) box collision detection |
BoxBlockIntersectionEvaluator | Static box-to-block intersection tests |
CollisionMath | AABB intersection math utilities |
CollisionDataArray | Pooled, sortable collision data list |
BlockCollisionProvider | Block collision provider |
EntityCollisionProvider | Entity collision provider |
IBlockCollisionConsumer | Callback interface for collision events |
IBlockCollisionEvaluator | Interface for collision evaluators |
CollisionFilter | Functional interface for collision filtering |
Class Hierarchy
Section titled “Class Hierarchy”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
}
CollisionModule
Section titled “CollisionModule”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);}CollisionResult
Section titled “CollisionResult”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);}Collision Data Types
Section titled “Collision Data Types”BasicCollisionData
Section titled “BasicCollisionData”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);}BoxCollisionData
Section titled “BoxCollisionData”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);}BlockCollisionData
Section titled “BlockCollisionData”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();}CharacterCollisionData
Section titled “CharacterCollisionData”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 );}Collision Evaluators
Section titled “Collision Evaluators”BlockContactData
Section titled “BlockContactData”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();}IBlockCollisionEvaluator
Section titled “IBlockCollisionEvaluator”Interface that both evaluators implement:
public interface IBlockCollisionEvaluator { double getCollisionStart(); void setCollisionData(BlockCollisionData data, CollisionConfig collisionConfig, int hitboxIndex);}MovingBoxBoxCollisionEvaluator
Section titled “MovingBoxBoxCollisionEvaluator”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);}BoxBlockIntersectionEvaluator
Section titled “BoxBlockIntersectionEvaluator”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();}CollisionMath
Section titled “CollisionMath”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 );}Material Masks
Section titled “Material Masks”Block materials affect collision behavior. Defined in CollisionMaterial (and mirrored in CollisionConfig):
| Constant | Value | Description |
|---|---|---|
MATERIAL_EMPTY | 1 | No collision (air) |
MATERIAL_FLUID | 2 | Fluid block (water, lava) |
MATERIAL_SOLID | 4 | Solid collision |
MATERIAL_SUBMERGED | 8 | Fully in fluid |
MATERIAL_SET_ANY | 15 | All non-damage materials |
MATERIAL_DAMAGE | 16 | Damage on contact |
MATERIAL_SET_NONE | 0 | No materials |
IBlockCollisionConsumer
Section titled “IBlockCollisionConsumer”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();}CollisionFilter
Section titled “CollisionFilter”A functional interface used for position validation filtering:
@FunctionalInterfacepublic interface CollisionFilter<D, T> { boolean test(T t, int code, D data, CollisionConfig config);}Collision Detection Flow
Section titled “Collision Detection Flow”How findCollisions Works
Section titled “How findCollisions Works”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]
Block Collision (Short Distance)
Section titled “Block Collision (Short Distance)”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]
Entity Collision
Section titled “Entity Collision”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
Collision Types
Section titled “Collision Types”Solid Collision
Section titled “Solid Collision”Standard blocking collision:
- Stops movement at collision point
- Returns collision normal for response
- Used for walls, floors, ceilings
Slide Collision
Section titled “Slide Collision”Walkable surface collision:
- Detected when
onGroundis true and block material is walkable - Allows movement along surface
- Used for slopes and stairs
- Entity can slide along the surface
Trigger Collision
Section titled “Trigger Collision”Non-blocking sensor collision:
- Does not stop movement
- Fires interaction events (
CollisionEnter,Collision,CollisionLeave) - Used for pressure plates, zones, fluids
Damage Collision
Section titled “Damage Collision”Harmful surface collision:
- Blocks with
damageToEntities > 0or fluids with damage - Added as trigger blocks, damage amount tracked
- Used for spikes, lava, etc.
Usage Examples
Section titled “Usage Examples”Basic Collision Check
Section titled “Basic Collision Check”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;}Collision Response
Section titled “Collision Response”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;}Position Validation
Section titled “Position Validation”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;}Best Practices
Section titled “Best Practices”- Reuse CollisionResult: Call
reset()instead of creating new instances — the pooled arrays avoid allocation overhead - Choose appropriate method: Short-distance is used automatically when velocity is below threshold
- Check material masks: Use
setCollisionByMaterial()andsetWalkableByMaterial()to control what blocks collide - Handle slides separately: Slides allow movement along walkable surfaces, collisions block
- Process triggers: Trigger blocks fire interaction events (
CollisionEnter,Collision,CollisionLeave) - Understand return types:
findCollisionsreturnsboolean(far distance flag),validatePositionreturnsint(status code) - Instance vs static:
findCollisions,findBlockCollisions*, andfindCharacterCollisionsare static;validatePositionandfindIntersectionsare instance methods
Related
Section titled “Related”- Physics Overview - Physics system architecture
- Hitbox System - Entity hitboxes
- Block System - Block types and materials