---
title: "Updating Guide: 2.x to 3.x"
hide_meta: true
---

# Updating Entities

A guide for converting AzureLib/Geckolib Entities to the new 3.x code.

## Entity Class

<CodeTabs>

```java !!tabs AzureLib 2.x/Geckolib
public class ExampleEntity extends Entity implements GeoEntity  {
    private static final RawAnimation IDLE = RawAnimation.begin().thenLoop("idle");
    // Geckolib used GeckoLibUtil
    private final AnimatableInstanceCache cache = AzureLibUtil.createInstanceCache(this);

    public ExampleEntity(EntityType<? extends Entity> entityType, Level level) {
        super(entityType, level);
    }

    @Override
    public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
        controllers.add(
            new AnimationController<>(this, "base_controller", 0,
                state -> state.setAndContinue(IDLE))
        );
    }

    @Override
    public AnimatableInstanceCache getAnimatableInstanceCache() {
        return cache;
    }
}
```

```java !!tabs AzureLib 3.x
public class ExampleEntity extends Entity {
    // This is your class where you will setup the AzCommands/Animations you wish to play
    public final ExampleEntityDispatcher dispatcher;

    public ExampleEntity(EntityType<? extends Entity> entityType, Level level) {
        super(entityType, level);
        // Create the instance of the class here to use later.
        this.dispatcher = new ExampleEntityDispatcher(this);
    }

    @Override
    public void tick() {
        super.tick();

        if (this.level().isClientSide) {
            animationDispatcher.idle();
        }
    }
}
```

</CodeTabs>

As you can see here, you no longer need to implement a Geo interface to your class anymore and no longer register your controllers here. All that is needed now is to simply implement a Dispatcher, which we will cover below.

## Animations

<Callout variant="info">
    See here for a more [indepth example](../misc/animating/azcommands_101#converting-from-animationcontroller-to-azcommand)
</Callout>

<CodeTabs>

```java !!tabs AzureLib 2.x/Geckolib
    private static final RawAnimation IDLE = RawAnimation.begin().thenLoop("idle");

    @Override
    public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
        controllers.add(
            new AnimationController<>(this, "base_controller", 0,
                state -> state.setAndContinue(IDLE))
        );
    }
```

```java !!tabs AzureLib 3.x
public class ExampleEntityAnimator extends AzEntityAnimator<ExampleEntity> {
    private static final ResourceLocation ANIMATIONS = ResourceLocation.fromNamespaceAndPath(
        YOUR_MOD_ID,
        "animations/entity/example_entity.animation.json"
    );

    public ExampleEntityAnimator() {
        super(AzAnimatorConfig.defaultConfig());
    }

    @Override
    public void registerControllers(AzAnimationControllerContainer<ExampleEntity> animationControllerContainer) {
        animationControllerContainer.add(
            AzAnimationController.builder(this, "base_controller")
                .build()
        );
    }

    @Override
    public @NotNull ResourceLocation getAnimationLocation(ExampleEntity animatable) {
        return ANIMATIONS;
    }
}
```

</CodeTabs>

<Callout variant="info">
    It is recommend to created a dedicated class for your Animation triggers as AzureLib now functions only using animation trigger calls, which is registered in your item like in the example above of the new Item class:
</Callout>
```java
public class ExampleEntityDispatcher {
    private static final AzCommand IDLE_COMMAND = AzCommand.create(
        "base_controller",
        "idle",
        AzPlayBehaviors.LOOP
    );

    private final ExampleEntity example_entity;

    public DoomHunterAnimationDispatcher(ExampleEntity animatable) {
        this.example_entity = animatable;
    }

    public void idle() {
        IDLE_COMMAND.sendForEntity(example_entity);
    }
}
```

## Rendering

<Callout variant="info">
    See [here](../misc/rendering/azrenderer_config#azentityrendererconfig) for a more indepth example
</Callout>

<CodeTabs>

```java !!tabs AzureLib 2.x/Geckolib
public class ExampleEntityRenderer extends GeoEntityRenderer<ExampleEntity> {
    public ExampleEntityRenderer() {
        super(new DefaultedEntityGeoModel<>(ResourceLocation.fromNamespaceAndPath(
            YOUR_MOD_ID, "example_entity"
        )));
    }
}
```

```java !!tabs AzureLib 3.x
public class ExampleEntityRenderer extends AzEntityRenderer<ExampleEntity> {
    private static final ResourceLocation GEO = ResourceLocation.fromNamespaceAndPath(
        YOUR_MOD_ID,
        "geo/entity/example_entity.geo.json"
    );

    private static final ResourceLocation TEX = ResourceLocation.fromNamespaceAndPath(
        YOUR_MOD_ID,
        "textures/entity/example_entity.png"
    );

    public ExampleEntityRenderer(EntityRendererProvider.Context context) {
        super(
            AzEntityRendererConfig.<ExampleEntity>builder(GEO, TEX)
                .setAnimatorProvider(ExampleEntityAnimator::new).build(),
            context
        );
    }
}
```

</CodeTabs>

This is where you will now register the ResourceLocation model and texture of your armor and you register your ExampleEntityAnimator.

## Registering

Basic Example of Fabric and NeoForge

<CodeTabs>

```java !!tabs Fabric
@Override
public void onInitializeClient() {
    EntityRendererRegistry.register(EntityType.CREEPER, ExampleEntityRenderer::new);
}
```

```java !!tabs NeoForge
@SubscribeEvent
public static void registerRenderers(final EntityRenderersEvent.RegisterRenderers event) {
    event.registerEntityRenderer(ExampleRegistry.EXAMPLE_ENTITY.get(), ExampleEntityRenderer::new);
}
```

</CodeTabs>