-
Notifications
You must be signed in to change notification settings - Fork 0
Movement
Package: dev.goshi.omnimixin.api.event.movement
Hooks around how entities move: ground speed, jumping, sprinting, flight speed, and being pushed by other entities. Everything here runs on the logical server (or singleplayer integrated server) — movement is server-authoritative in vanilla, so that's where these fire.
Fires whenever an entity's base ground movement speed is calculated.
Carries a [SpeedContext](https://claude.ai/chat/a3c01413-be46-46f0-a149-92ab00193506#speedcontext) with the entity, the speed vanilla
was about to use, and a MutableFloat to change it.
PlaySpeed.MODIFY_GROUND.register(ctx -> {
if (ctx.entity().hasStatusEffect(StatusEffects.SLOWNESS)) {
return; // let vanilla's own slowness handling apply on top
}
if (isStandingOnMyCustomIceBlock(ctx.entity())) {
ctx.modifier().multiply(1.5f);
}
});
SpeedContext(LivingEntity entity, float currentBase, MutableFloat modifier)
Three phases around a jump — PRE_JUMP, MODIFY_IMPULSE, POST_JUMP — all
sharing the same [JumpContext](https://claude.ai/chat/a3c01413-be46-46f0-a149-92ab00193506#jumpcontext).
// Give shift-clicking (sneaking) entities a lower jump.
PlayJump.MODIFY_IMPULSE.register(ctx -> {
if (ctx.entity().isSneaking()) {
ctx.verticalImpulse().multiply(0.6f);
}
});
// Block jumping entirely for a rooted/stunned status effect.
PlayJump.PRE_JUMP.register(ctx -> {
if (ctx.entity().hasStatusEffect(MyEffects.ROOTED)) {
ctx.cancel().cancel();
}
});
JumpContext(LivingEntity entity, Cancellable cancel, MutableFloat verticalImpulse)
PRE_JUMP fires before the jump happens at all — cancel here to stop it
outright. MODIFY_IMPULSE fires as the actual vertical velocity is being
computed — this is where you scale jump height. POST_JUMP fires after,
for reacting to a jump that already happened (playing a custom sound,
starting a cooldown, etc.) — cancelling at this point has no effect, since
the jump is already done.
Two events, not phases of the same action — CAN_SPRINT gates whether an
entity is allowed to start sprinting, and ON_TOGGLE tells you whenever
sprinting turns on or off.
// Prevent sprinting while encumbered by a heavy backpack item.
PlaySprint.CAN_SPRINT.register(ctx -> !isCarryingHeavyLoad(ctx.entity()));
// Play a custom sound whenever any entity starts or stops sprinting.
PlaySprint.ON_TOGGLE.register((ctx, sprinting) -> {
if (sprinting) {
playWhooshSound(ctx.entity());
}
});CAN_SPRINT's listener returns a boolean — return false to veto. If
any registered listener returns false, sprinting is blocked and no
further CAN_SPRINT listeners even run.
SprintContext(LivingEntity entity)
Adjusts a player's creative/spectator flight speed.
PlayFly.MODIFY_FLIGHT_SPEED.register(ctx -> {
if (hasSpeedBoots(ctx.abilities())) {
ctx.modifier().add(0.02f);
}
});
FlySpeedContext(PlayerAbilities abilities, float baseFlySpeed, MutableFloat modifier)
Note: only flight speed is covered right now. Toggling flight on/off and elytra-allowed checks are not — see Known Limitations for why.
Fires whenever one entity pushes another apart (the constant gentle nudging that keeps mobs from overlapping).
// My custom "heavy" entities can't be pushed around by regular mobs.
PlayCollision.ENTITY_PUSH.register(ctx -> {
if (isHeavyEntity(ctx.entity()) && !isHeavyEntity(ctx.other())) {
ctx.cancel().cancel();
}
});
PushContext(Entity entity, Entity other, MutableFloat forceMultiplier, Cancellable cancel)
entity is the one being pushed; other is whatever is pushing it.
Cancelling stops this specific push interaction between this specific pair
for this tick — it doesn't make entity generally unpushable.
Note: only entity-vs-entity pushing is covered. Block collision math and step-height are not — see Known Limitations.