Repository navigation
API ‐ Extensible Playback Speed
The Playback Speed system is fully extensible.
Third-party mods may register custom playback speed modifiers, allowing animations to compute their playback speed using arbitrary logic.
Every playback modifier consists of three parts:
- A parameter record.
- A playback modifier type.
- A registry entry.
ExtendedDatapacksRegistry
│
▼
IPlaySpeedModifierType
│
▼
paramsCodec()
│
▼
IPlaySpeedModifierParams
│
▼
modify(...)
│
▼
Animation Playback Speed
The registry serializes modifier types using DFU (
Codec), while modifier parameters are decoded through theMapCodecsupplied by each registered type.
Parameter objects contain both:
- The serialized configuration.
- The playback speed logic.
Every parameter record must implement:
IPlaySpeedExternalModifierParamswhich extends the non-sealed extension point of:
IPlaySpeedModifierParamspublic record ConstantAnimationSpeed(Float constant)
implements IPlaySpeedExternalModifierParams {
public static final MapCodec<ConstantAnimationSpeed> CODEC =
RecordCodecBuilder.mapCodec(instance ->
instance.group(
Codec.FLOAT.fieldOf("constant")
.forGetter(ConstantAnimationSpeed::constant)
).apply(instance, ConstantAnimationSpeed::new)
);
@Override
public <T extends DynamicAnimation> float modify(
T self,
LivingEntityPatch<?> patch,
float speed,
float prevElapsedTime,
float elapsedTime) {
return constant;
}
}The modify() method is invoked every tick while the animation is playing.
Playback modifier types expose the codec responsible for decoding their parameter object.
They implement:
IPlaySpeedModifierTypepublic enum ExamplePlaybackTypes implements IPlaySpeedModifierType {
CONSTANT(ConstantAnimationSpeed.CODEC);
private final MapCodec<? extends IPlaySpeedModifierParams> codec;
ExamplePlaybackTypes(
MapCodec<? extends IPlaySpeedModifierParams> codec) {
this.codec = codec;
}
@Override
public MapCodec<? extends IPlaySpeedModifierParams> paramsCodec() {
return codec;
}
}Each enum constant represents an individual playback modifier type.
Playback modifier types are registered through the centralized:
ExtendedDatapacksRegistryUse the ANIMATION_PLAYBACK registry entry:
ExtendedDatapacksRegistry.ANIMATION_PLAYBACK.register(
MOD_ID,
ExamplePlaybackTypes.class
);The registry accepts either a single enum class or multiple enum classes.
ExtendedDatapacksRegistry.ANIMATION_PLAYBACK.register(
MOD_ID,
FirstPlaybackTypes.class,
SecondPlaybackTypes.class,
ThirdPlaybackTypes.class
);The registry automatically verifies that every supplied enum implements:
IPlaySpeedModifierTypeInvalid classes are rejected and a warning is emitted to the log.
Every enum constant becomes a playback modifier.
The generated identifier follows the format:
<modid>:<enum_name>
For example:
example_mod:constant
The centralized registry exposes the following general form:
ExtendedDatapacksRegistry.ANIMATION_PLAYBACK.register(
String modId,
Class<? extends Enum<?>>... enumClasses
);This same registration system is also used by Extended Datapacks for other animation extension points, such as animation events, accessors, groups, and armatures.
Once registered, the modifier can immediately be used inside animation JSON.
{
"play_speed_modifier": {
"type": "example_mod:constant",
"params": {
"constant": 1.5
}
}
}The params object is automatically decoded using the MapCodec returned by the registered playback type.
Playback modifiers must be registered before Extended Datapacks loads and consumes its animation registries.
For example, registration should occur during your mod's initialization:
private static void registerPlaybackModifiers() {
ExtendedDatapacksRegistry.ANIMATION_PLAYBACK.register(
ExtendedDatapacks.MODID,
ExamplePlaybackTypes.class
);
}Attempting to register new playback modifiers after the registry has been consumed will throw:
RegistryObjectException
This restriction exists because the animation codecs resolve the available playback modifier types during registry initialization.
The playback modifier registry internally uses DFU.
Conceptually, the registry exposes:
Codec<IPlaySpeedModifierType>Each playback type supplies its own:
MapCodec<? extends IPlaySpeedModifierParams>This allows every modifier to define its own parameter structure independently.
For example, one modifier may use:
{
"constant": 1.5
}while another could define an entirely different structure:
{
"minimum": 0.5,
"maximum": 2.0
}The registry only needs to identify the modifier type; the registered type is responsible for decoding its parameters.
A minimal external playback modifier therefore consists of:
public record ConstantAnimationSpeed(Float constant)
implements IPlaySpeedExternalModifierParams {
public static final MapCodec<ConstantAnimationSpeed> CODEC =
RecordCodecBuilder.mapCodec(instance ->
instance.group(
Codec.FLOAT.fieldOf("constant")
.forGetter(ConstantAnimationSpeed::constant)
).apply(instance, ConstantAnimationSpeed::new)
);
@Override
public <T extends DynamicAnimation> float modify(
T self,
LivingEntityPatch<?> patch,
float speed,
float prevElapsedTime,
float elapsedTime) {
return constant;
}
}public enum ExamplePlaybackTypes
implements IPlaySpeedModifierType {
CONSTANT(ConstantAnimationSpeed.CODEC);
private final MapCodec<? extends IPlaySpeedModifierParams> codec;
ExamplePlaybackTypes(
MapCodec<? extends IPlaySpeedModifierParams> codec) {
this.codec = codec;
}
@Override
public MapCodec<? extends IPlaySpeedModifierParams> paramsCodec() {
return codec;
}
}ExtendedDatapacksRegistry.ANIMATION_PLAYBACK.register(
MOD_ID,
ExamplePlaybackTypes.class
);{
"play_speed_modifier": {
"type": "example_mod:constant",
"params": {
"constant": 1.5
}
}
}- Custom playback modifiers should implement
IPlaySpeedExternalModifierParamsrather than directly implementingIPlaySpeedModifierParams. - Playback modifier types must implement
IPlaySpeedModifierType. - Register modifier enums through
ExtendedDatapacksRegistry.ANIMATION_PLAYBACK. - Multiple enum classes can be registered in a single call.
- The registry automatically validates that supplied classes implement the appropriate registry interface.
- Registration must occur before Extended Datapacks initializes and consumes its animation registries.
- The generated modifier identifier is based on the mod ID and enum constant name.
- The
paramsobject is decoded using theMapCodecsupplied by the registered modifier type. - The centralized
ExtendedDatapacksRegistryis now the recommended registration API; the underlyingPlaySpeedModifierTypeRegistryremains an implementation detail.
EF: Extended Datapacks
📦 Data
🧰 Core
👁️ Visuals
- Zoom Types
- Weapon Models per Style
- Advanced Swing Trails
- Weapons Passive Particles
- Shader Effects I
- Shader Effects II
- Shader Effects III
⚔️ Combat
🗝️ Skill Builder
🛠️ Innate Builder
- Simple Innate Skills
- Holdable Innate Skills
- Conditional Innate Skills
- Conditional Data Innate Skills
- Conditional Holdable Innate Skills
- Sequential Innate Skills
- Per Combo Innate Skills
- Combo Innate Skills
🗡️ Animation Operations
- Animation Operations
- Animation Properties
⚙️ Third-Party