Skip to content

Velocity

Movement velocity vector for entities. Used for knockback, launches, dashes, and physics-based movement.

Velocity velocity = store.getComponent(ref, Velocity.getComponentType());
// get current velocity
Vector3d vel = velocity.getVelocity();
double speed = velocity.getSpeed(); // velocity.length()
// get individual axes
double x = velocity.getX();
double y = velocity.getY();
double z = velocity.getZ();
// set velocity (replaces current)
velocity.set(x, y, z);
velocity.set(new Vector3d(x, y, z));
// add force (accumulates)
velocity.addForce(x, y, z);
velocity.addForce(new Vector3d(x, y, z));
// clear velocity
velocity.setZero();

For player entities, use the instruction system. Instructions are queued and processed by the velocity system, which handles network synchronization.

// launch player upward
velocity.addInstruction(
new Vector3d(0, 15, 0),
null, // VelocityConfig (optional)
ChangeVelocityType.Set
);
// add knockback force
velocity.addInstruction(
knockbackDirection,
velocityConfig,
ChangeVelocityType.Add
);
TypeEffect
SetReplaces current velocity
AddAdds to current velocity

Controls how velocity decays over time:

FieldDefaultDescription
groundResistance0.82Velocity multiplier on ground
groundResistanceMax0.0Max resistance above threshold
airResistance0.96Velocity multiplier in air
airResistanceMax0.0Max resistance above threshold
threshold1.0Speed where resistance transitions to max
styleLinearTransition style (Linear or Exp)

Lower resistance = faster decay. A value of 0.82 means velocity is multiplied by 0.82 each tick when on ground.

When speed exceeds threshold, resistance transitions from base to max value based on style.

Velocity velocity = store.getComponent(ref, Velocity.getComponentType());
velocity.addInstruction(
new Vector3d(0, 20, 0), // launch upward
null,
ChangeVelocityType.Set
);
// calculate knockback direction from attacker to target
Vector3d knockback = targetPos.clone().sub(attackerPos).normalize();
knockback.setY(0.4); // add upward component
knockback.scale(10); // knockback strength
Velocity velocity = store.getComponent(targetRef, Velocity.getComponentType());
velocity.addInstruction(knockback, null, ChangeVelocityType.Add);
// get player's look direction
HeadRotation head = store.getComponent(ref, HeadRotation.getComponentType());
Vector3d direction = head.getDirection();
direction.setY(0); // horizontal only
direction.normalize().scale(15);
Velocity velocity = store.getComponent(ref, Velocity.getComponentType());
velocity.addInstruction(direction, null, ChangeVelocityType.Set);
Velocity velocity = store.getComponent(ref, Velocity.getComponentType());
double fallSpeed = Math.abs(velocity.getY());
if (fallSpeed > fallDamageThreshold) {
// apply fall damage
}

The component tracks separate velocities:

MethodPurpose
getVelocity()Server-side velocity
getClientVelocity()Client-predicted velocity
setClient(x, y, z)Set client velocity

For player entities, changes are synced via the ChangeVelocity packet (ID: 163).

Velocity changes are processed through ECS systems:

  1. Systems queue instructions via addInstruction()
  2. GenericVelocityInstructionSystem processes non-player entities
  3. PlayerVelocityInstructionSystem sends packets to player clients
  4. Instructions are cleared after processing