Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ryanhcode/sable/llms.txt

Use this file to discover all available pages before exploring further.

EntitySubLevelUtil provides utilities for working with entities in relation to sub-levels: kicking entities out of sub-levels, checking whether an entity should be kicked, and reading tracking state. All methods are static; the class is not intended to be instantiated.

kickEntity

public static void kickEntity(SubLevel subLevel, Entity entity)
Teleports the entity to its equivalent position in global space, applying the sub-level’s velocity and rotational contribution to the entity’s delta movement and look angle. This ensures entities ejected from a sub-level continue moving naturally rather than snapping to rest. For AbstractHurtingProjectile instances with zero accelerationPower, the global velocity at the entity’s position is also added to the delta movement (converted from m/s to m/t). FallingBlockEntity receives special treatment: the transform is applied relative to the block’s vertical centre rather than its feet, preventing a visual offset on ejection.
subLevel
SubLevel
required
The sub-level the entity is currently tracked inside and being ejected from.
entity
Entity
required
The entity to relocate to global space.

shouldKick

public static boolean shouldKick(Entity entity)
Returns true if the entity’s type does not have the #sable:retain_in_sub_level entity type tag. Entities without this tag are candidates for ejection when a sub-level is removed or when the engine determines they should not remain inside.
entity
Entity
required
The entity to check.
To make a custom entity remain inside a sub-level after removal, add its entity type to the sable:retain_in_sub_level tag in your mod’s data pack.

setOldPosNoMovement

public static void setOldPosNoMovement(Entity entity)
Sets the entity’s previous-tick position fields (xOld, xo, yOld, yo, zOld, zo) so that the renderer interpolates zero movement for the current tick. This accounts for any tracking sub-level interpolation that may have shifted the entity’s apparent position, making teleportation appear instantaneous rather than as a visual jump. Call this immediately after repositioning an entity (for example, after kickEntity) when you do not want the engine’s default position interpolation to apply.
entity
Entity
required
The entity whose previous-position fields should be updated.

getCustomEntityOrientation

@Nullable
public static Quaterniondc getCustomEntityOrientation(Entity entity, float partialTicks)
Returns a custom rendering orientation for the entity, or null to fall back to the default orientation. The default implementation always returns null and is intended as an extension point for override by platform-specific code or future additions.
entity
Entity
required
The entity to query.
partialTicks
float
required
The render partial tick value for interpolation.

hasCustomEntityOrientation

public static boolean hasCustomEntityOrientation(Entity entity)
Returns true if getCustomEntityOrientation() will return a non-null value for this entity. The default implementation always returns false. Check this before calling the heavier getCustomEntityOrientation() in a render loop.
entity
Entity
required
The entity to check.

SubLevelHelper — wind and air-velocity utilities

SubLevelHelper is a companion class that exposes two static methods relevant to aerodynamic and propulsion force calculations in sub-level physics.

registerWindProvider

public static void registerWindProvider(
    BiFunction<Vector3dc, Level, Vector3dc> function
)
Registers a function that returns the air velocity vector at a given world position. Multiple providers can be registered; their contributions are summed. Registered providers are used by getVelocityRelativeToAir() to compute the net wind at any point. Use this to integrate custom weather, fan blocks, or atmospheric systems with Sable’s aerodynamic simulation. Wind velocity is expressed in metres per second.
function
BiFunction<Vector3dc, Level, Vector3dc>
required
A function that accepts a world position and the level, and returns the air velocity vector at that point in m/s. May return null to indicate no contribution at that position.
Call registerWindProvider once during your mod’s initialization phase, not per-tick.

getVelocityRelativeToAir

public static Vector3d getVelocityRelativeToAir(
    Level level,
    Vector3dc pos,
    Vector3d dest
)
Computes the velocity of a point — taking into account any sub-level it belongs to — relative to the surrounding air. Each registered wind provider’s contribution at pos is subtracted from the raw velocity. The result is written into dest and also returned. This value is used internally for propeller and aerodynamic drag force calculations.
level
Level
required
The level containing the point.
pos
Vector3dc
required
The world position to evaluate, in metres.
dest
Vector3d
required
Destination vector that receives the result. Also returned by the method.
Returns dest populated with the velocity relative to air in m/s.

Usage example

// Check whether an entity should be ejected, then eject it
if (EntitySubLevelUtil.shouldKick(entity)) {
    EntitySubLevelUtil.kickEntity(subLevel, entity);

    // Suppress interpolation artefacts from the teleport
    EntitySubLevelUtil.setOldPosNoMovement(entity);
}
Registering a wind provider during mod initialization:
SubLevelHelper.registerWindProvider((pos, level) -> {
    // return a constant eastward breeze of 3 m/s
    return new Vector3d(3.0, 0.0, 0.0);
});

Build docs developers (and LLMs) love