Skip to content

API Animation Groups

Sleys edited this page Sep 22, 2026 · 2 revisions

The Animation Group system allows existing animations to be parameterized according to their animation inheritance without creating a "new animation object".

Animation groups describe how a JSON definition should be interpreted based on the type of animation it targets.

Unlike [Animation Accessors], groups do not construct animations. Instead, they operate on existing animations and treat them according to their inheritance hierarchy.

For example, an animation belonging to an attack group can accept properties applicable to attack animations, as well as properties inherited from its parent animation types.


🧩 Architecture

ExtendedDatapacksRegistry
          │
          ▼
 IAnimationGroupType
          │
          ├──────────────────────┐
          ▼                      ▼
Virtualization Definition   Config Definition
          │                      │
          ▼                      ▼
IAnimationVirtualization    IAnimationConfig
          │                      │
          ▼                      ▼
 Existing Animation       Existing Animation

An animation group provides two independent definitions:

  • A configuration definition, used to modify an existing animation.
  • A virtualization definition, used to create a virtual representation of an existing animation.

Both definitions are associated with the same animation group type.


🧬 Animation Inheritance

Animation groups are based on the inheritance hierarchy of Epic Fight animations.

Conceptually:

StaticAnimation
      │
      └── ActionAnimation
              │
              └── AttackAnimation

A group represents one point in this hierarchy.

For example:

STATIC_GROUP
    │
    ▼
StaticAnimation

ATTACK_GROUP
    │
    ▼
ActionAnimation
    │
    ▼
AttackAnimation

Therefore, an animation belonging to an attack group can accept properties applicable to:

  • Static animations.
  • Action animations.
  • Attack animations.

A static animation, on the other hand, only accepts properties applicable to the static level of the hierarchy.

This allows animation JSON to remain generic while still respecting the capabilities of the underlying animation type.


📦 Step 1 — Create the Group Type

Animation groups implement:

IAnimationGroupType

A group type defines:

  • Its unique identifier.
  • Its virtualization definition codec.
  • Its configuration definition codec.

Example

public enum EpicFightAnimationGroups
        implements IAnimationGroupType {

    STATIC_GROUP(
        "epicfight_edp:static_group",

        new AnimationVirtualizationDefinitionCodec<>(
            VirtualStaticAnimationGroup.CODEC,
            StaticAnimationProperties.CODEC
        ),

        new AnimationConfigDefinitionCodec<>(
            ConfigStaticAnimationGroup.CODEC,
            StaticAnimationProperties.CODEC
        )
    ),

    ATTACK_GROUP(
        "epicfight_edp:attack_group",

        new AnimationVirtualizationDefinitionCodec<>(
            VirtualActionAnimationGroup.CODEC,
            ActionAnimationProperties.CODEC
        ),

        new AnimationConfigDefinitionCodec<>(
            ConfigActionAnimationGroup.CODEC,
            ActionAnimationProperties.CODEC
        )
    ),

    ACTION_GROUP(
        "epicfight_edp:action_group",

        new AnimationVirtualizationDefinitionCodec<>(
            VirtualAttackAnimationGroup.CODEC,
            AttackAnimationProperties.CODEC
        ),

        new AnimationConfigDefinitionCodec<>(
            ConfigAttackAnimationGroup.CODEC,
            AttackAnimationProperties.CODEC
        )
    );

    private final String id;

    private final AnimationVirtualizationDefinitionCodec<?> virtualDefinitionCodec;
    private final AnimationConfigDefinitionCodec<?> configDefinitionCodec;

    EpicFightAnimationGroups(
            String id,
            AnimationVirtualizationDefinitionCodec<?> virtualDefinitionCodec,
            AnimationConfigDefinitionCodec<?> configDefinitionCodec) {

        this.id = id;
        this.virtualDefinitionCodec = virtualDefinitionCodec;
        this.configDefinitionCodec = configDefinitionCodec;
    }

    @Override
    public String id() {
        return id;
    }

    @Override
    public AnimationVirtualizationDefinitionCodec<?> virtualDefinitionCodec() {
        return virtualDefinitionCodec;
    }

    @Override
    public AnimationConfigDefinitionCodec<?> configDefinitionCodec() {
        return configDefinitionCodec;
    }
}

The group identifier is explicitly defined through:

String id()

For example:

epicfight_edp:static_group
epicfight_edp:attack_group
epicfight_edp:action_group

📦 Step 2 — Create a Configuration Definition

Configuration definitions implement:

IAnimationConfig<T>

They operate on an existing animation.

They do not create a new animation instance.

Example

public record ConfigStaticAnimationGroup(
        ResourceLocation animation
) implements IAnimationConfig<StaticAnimation> {

    public static final MapCodec<ConfigStaticAnimationGroup> CODEC =
        RecordCodecBuilder.mapCodec(instance ->
            instance.group(
                ResourceLocation.CODEC
                    .fieldOf("animation")
                    .forGetter(ConfigStaticAnimationGroup::animation)
            ).apply(instance, ConfigStaticAnimationGroup::new)
        );

    @Override
    public IAnimationGroupType groupType() {
        return EpicFightAnimationGroups.STATIC_GROUP;
    }

    @Override
    public void applyConfig(
            IAnimationProperties<StaticAnimation> property) {

        if (this.isInvalidAccessor()) return;

        var animation = getAccessor().get();

        property.applyTo(animation);

        this.isSuccessful();
    }
}

The configuration definition identifies an existing animation:

{
  "animation": "..."
}

and then applies the decoded properties to that animation.

The important distinction is that the animation already exists.


📦 Step 3 — Create a Virtualization Definition

Virtualization definitions implement:

IAnimationVirtualization<T>

They also operate on existing animations, but instead of modifying the original animation directly, they describe a virtual animation based on an existing one.

Example

public record VirtualStaticAnimationGroup(
        ResourceLocation realAnimation,
        ResourceLocation virtualAnimation
) implements IAnimationVirtualization<StaticAnimation> {

    public static final MapCodec<VirtualStaticAnimationGroup> CODEC =
        RecordCodecBuilder.mapCodec(instance ->
            instance.group(
                ResourceLocation.CODEC
                    .fieldOf("real_animation")
                    .forGetter(VirtualStaticAnimationGroup::realAnimation),

                ResourceLocation.CODEC
                    .fieldOf("virtual_animation")
                    .forGetter(VirtualStaticAnimationGroup::virtualAnimation)

            ).apply(instance, VirtualStaticAnimationGroup::new)
        );

    @Override
    public IAnimationGroupType groupType() {
        return EpicFightAnimationGroups.STATIC_GROUP;
    }
}

A virtualization definition therefore establishes a relationship between:

real animation
      │
      ▼
virtual animation

The virtual animation can then receive additional configuration while retaining the behavior and inheritance characteristics of the underlying animation.


📦 Step 4 — Register the Group Type

Animation groups are registered through the centralized:

ExtendedDatapacksRegistry

using:

ANIMATION_GROUP

Single group registry

ExtendedDatapacksRegistry.ANIMATION_GROUP.register(
        MOD_ID,
        EpicFightAnimationGroups.class
);

Multiple group registries

Multiple enum classes can be registered in a single call:

ExtendedDatapacksRegistry.ANIMATION_GROUP.register(
        MOD_ID,
        EpicFightAnimationGroups.class,
        CustomAnimationGroups.class
);

The registry automatically verifies that every supplied enum implements:

IAnimationGroupType

Invalid classes are rejected and a warning is emitted to the log.


📄 Configuration Animation

A configuration definition uses an existing animation as its target.

For example:

{
  "type": "attack_group",
  "animation": "epicfight:biped/skill/battojutsu_dash",

  "in_time_events": [
    {
      "type": "epicfight_edp:thunder",
      "side": "server",
      "start": 1.0
    }
  ]
}

Here:

"type": "attack_group"

selects the animation group.

The:

"animation": "epicfight:biped/skill/battojutsu_dash"

field identifies the existing animation that will receive the configuration.

The remaining fields are interpreted according to the properties supported by that animation group.


📄 Virtualization Animation

Virtualization definitions use two animation identifiers:

{
  "type": "attack_group",
  "real_animation": "epicfight:biped/skill/battojutsu",
  "virtual_animation": "new_epicfight:biped/skill/battojutsu",

  "in_time_events": [
    {
      "type": "teleport",
      "side": "server",
      "start": 0.15,
      "params": {
        "offset": [0, 0, 0],
        "mode": "target_front"
      }
    }
  ]
}

The:

"real_animation"

identifies the existing animation.

The:

"virtual_animation"

defines the new identifier under which the virtualized animation can be referenced.

The virtualized animation can then receive additional properties and events without requiring the creation of a new concrete DynamicAnimation implementation.


🧬 Configuration vs. Virtualization

The two group operations serve different purposes.

Configuration

Existing Animation
       │
       ▼
 Apply Properties
       │
       ▼
Modified Existing Animation

A configuration definition references an animation and applies properties to it.

Virtualization

Existing Animation
       │
       ▼
 Virtual Definition
       │
       ├── real_animation
       │
       └── virtual_animation
               │
               ▼
       Virtual Animation Reference

A virtualization definition creates an additional virtual representation of an existing animation.


🔗 Groups and Inheritance

The most important distinction between Animation Accessors and Animation Groups is how they interact with animations.

Accessors

Accessors create an animation:

JSON
 │
 ▼
Accessor
 │
 ▼
new DynamicAnimation(...)
 │
 ▼
Registered Animation

An accessor therefore defines how an animation object is constructed.

Groups

Groups do not create the underlying animation:

JSON
 │
 ▼
Group
 │
 ▼
Existing Animation
 │
 ▼
Treat according to its inheritance

They operate on an existing animation and determine which property definitions are valid according to its inheritance level.

This distinction allows a single group definition to work with the capabilities inherited by the target animation.


🧱 Example of Inheritance

Suppose the animation hierarchy is:

StaticAnimation
      │
      └── ActionAnimation
              │
              └── AttackAnimation

A group associated with AttackAnimation can expose properties from the complete applicable hierarchy:

Attack Group
    │
    ├── Static properties
    ├── Action properties
    └── Attack properties

While a static group only exposes:

Static Group
    │
    └── Static properties

This is why the group definition associates a group with a specific property codec:

new AnimationConfigDefinitionCodec<>(
    ConfigActionAnimationGroup.CODEC,
    ActionAnimationProperties.CODEC
)

or:

new AnimationConfigDefinitionCodec<>(
    ConfigAttackAnimationGroup.CODEC,
    AttackAnimationProperties.CODEC
)

The same principle applies to virtualization definitions.


⚙️ Registration Lifecycle

Animation groups must be registered before Extended Datapacks initializes and consumes its animation registries.

Attempting to register an animation group after the registry has been consumed will throw:

RegistryObjectException

Registration should therefore occur during mod initialization:

private static void registerAnimationGroups() {
    ExtendedDatapacksRegistry.ANIMATION_GROUP.register(
            MOD_ID,
            EpicFightAnimationGroups.class
    );
}

🧩 Creating a Custom Animation Group

A third-party mod can define its own animation group by providing:

  1. A group enum implementing IAnimationGroupType.
  2. A configuration definition implementing IAnimationConfig<T>.
  3. A virtualization definition implementing IAnimationVirtualization<T>.
  4. The corresponding codecs.
  5. Registration through ExtendedDatapacksRegistry.ANIMATION_GROUP.

Conceptually:

                 IAnimationGroupType
                         │
          ┌──────────────┴──────────────┐
          ▼                             ▼
 Config Definition             Virtualization Definition
          │                             │
          ▼                             ▼
 IAnimationConfig<T>          IAnimationVirtualization<T>
          │                             │
          └──────────────┬──────────────┘
                         ▼
                Existing Animation

⚠️ Notes

  • Animation groups implement IAnimationGroupType.
  • Groups operate on existing animations rather than constructing new animation objects.
  • Configuration definitions implement IAnimationConfig<T>.
  • Virtualization definitions implement IAnimationVirtualization<T>.
  • Every group provides both a configuration definition codec and a virtualization definition codec.
  • Group identifiers are explicitly defined through IAnimationGroupType.id().
  • Register group enum classes through ExtendedDatapacksRegistry.ANIMATION_GROUP.
  • Multiple group enum classes can be registered in a single call.
  • The applicable property set is determined by the animation group's position in the animation inheritance hierarchy.
  • A more specialized animation group can expose properties belonging to its inherited animation types.
  • Configuration definitions modify an existing animation.
  • Virtualization definitions establish a virtual representation of an existing animation.

EF: Extended Datapacks

📦 Data

🧰 Core

👁️ Visuals

⚔️ Combat

🗝️ Skill Builder

🛠️ Innate Builder

🗡️ Animation Operations

⚙️ Third-Party

Clone this wiki locally