### Example Entity Class Setup with Geckolib Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Entities-(Geckolib4) Demonstrates the basic structure for a GeckoLib entity class, including implementing GeoEntity, initializing the AnimatableInstanceCache, and registering animation controllers. ```java public class ExampleEntity extends PathfinderMob implements GeoEntity { protected static final RawAnimation FLY_ANIM = RawAnimation.begin().thenLoop("move.fly"); private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this); public ExampleEntity(EntityType type, Level level) { super(type, level); } @Override public void registerControllers(final AnimatableManager.ControllerRegistrar controllers) { controllers.add(new AnimationController<>(this, "Flying", 5, this::flyAnimController)); } protected PlayState flyAnimController(final AnimationState event) { if (event.isMoving()) return event.setAndContinue(FLY_ANIM); return PlayState.STOP; } @Override public AnimatableInstanceCache getAnimatableInstanceCache() { return this.geoCache; } } ``` -------------------------------- ### Example Armor with Geckolib Animations Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-4-Changes Integrate Geckolib animations for custom armor items. This setup allows for custom rendering and animation handling for armor pieces. ```java public final class ExampleArmor extends ArmorItem implements GeoItem { private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); public ExampleArmor(ArmorMaterial armorMaterial, EquipmentSlot slot, Properties properties) { super(armorMaterial, slot, properties); } @Override public void initializeClient(Consumer consumer) { consumer.accept(new IClientItemExtensions() { private ExampleArmorRenderer renderer; @Override public @NotNull HumanoidModel getHumanoidArmorModel(LivingEntity livingEntity, ItemStack itemStack, EquipmentSlot equipmentSlot, HumanoidModel original) { if (this.renderer == null) this.renderer = new ExampleArmorRenderer(); this.renderer.prepForRender(livingEntity, itemStack, equipmentSlot, original); return this.renderer; } }); } @Override public void registerControllers(AnimatableManager.ControllerRegistrar controllers) { controllers.add(DefaultAnimations.genericIdleController(this)); } @Override public AnimatableInstanceCache getAnimatableInstanceCache() { return this.cache; } } ``` -------------------------------- ### Example Block Entity with Geckolib Animations Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-4-Changes Implement Geckolib animations for custom block entities. This example shows how to register controllers and manage animations based on game time. ```java public class ExampleBlockEntity extends BlockEntity implements GeoBlockEntity { private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); public ExampleBlockEntity(BlockPos pos, BlockState state) { super(TileRegistry.EXAMPLE_BLOCK_ENTITY.get(), pos, state); } @Override public void (AnimatableManager.ControllerRegistrar controllers) { controllers.add(new AnimationController<>(this, state -> { if (getLevel().getDayTime() > 23000 || getLevel().getDayTime() < 13000) { return state.setAndContinue(DefaultAnimations.REST); } else { return state.setAndContinue(DefaultAnimations.IDLE); } })); } @Override public AnimatableInstanceCache getAnimatableInstanceCache() { return this.cache; } } ``` -------------------------------- ### Example Renderer Class Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Items-(Geckolib4) Create a class that extends `GeoItemRenderer` and pass your `GeoModel` instance to the constructor to create a custom item renderer. ```java public class ExampleItemRenderer extends GeoItemRenderer { public ExampleItemRenderer() { super(new ExampleItemModel()); } } ``` -------------------------------- ### Example Animation Controller Registration Source: https://github.com/bernie-g/geckolib/wiki/The-Animation-Controller-(Geckolib4) An example of registering a single AnimationController. This controller plays the WALK animation if the entity is moving, otherwise it stops. ```java public void registerControllers(AnimatableManager.ControllerRegistrar controllers) { controllers.add(new AnimationController<>(this, "Walking", 0, state -> { return state.isMoving() ? state.setAndContinue(DefaultAnimations.WALK) : PlayState.STOP; })); } ``` -------------------------------- ### Example Item with Geckolib Animations Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-4-Changes Implement Geckolib animations for custom items. Requires registering the item as server-side handled for animation syncing and triggering. ```java public final class ExampleItem extends Item implements GeoItem { private final AnimatableInstanceCache cache = GeckoLibUtil.createInstancecache(this); public ExampleItem(Properties properties) { super(properties); // Register our item as server-side handled. // This enables both animation data syncing and server-side animation triggering SingletonGeoAnimatable.registerSyncedAnimatable(this); } @Override public void initializeClient(Consumer consumer) { consumer.accept(new IClientItemExtensions() { private ExampleItemRenderer renderer; @Override public BlockEntityWithoutLevelRenderer getCustomRenderer() { if (this.renderer == null) this.renderer = new ExampleItemRenderer(); return this.renderer; } }); } @Override public void registerControllers(AnimatableManager.ControllerRegistrar controllers) { controllers.add(new AnimationController<>(this, "shoot_controller", state -> PlayState.STOP) .triggerableAnim("shoot", DefaultAnimations.ATTACK_SHOOT)); } @Override public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { if (level instanceof ServerLevel serverLevel) triggerAnim(player, GeoItem.getOrAssignId(player.getItemInHand(hand), serverLevel), "shoot_controller", "shoot"); return super.use(level, player, hand); } @Override public AnimatableInstanceCache getAnimatableInstanceCache() { return this.cache; } } ``` -------------------------------- ### Example Entity Renderer Registration Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Entities-(Geckolib4) Extend GeoEntityRenderer and provide your entity and model classes. Ensure this renderer is registered with the game. ```java public class ExampleEntityRenderer extends GeoEntityRenderer { public ExampleEntityRenderer(EntityRendererProvider.Context context) { super(context, new ExampleEntityModel()); } } ``` -------------------------------- ### Example Item Class (Forge 1.19.3-1.20.6) Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Items-(Geckolib4) Implement a custom item that supports Geckolib animations for Forge. This includes registering the item for server-side handling and defining its custom renderer. ```java public class ExampleItem extends Item implements GeoItem { private static final RawAnimation ACTIVATE_ANIM = RawAnimation.begin().thenPlay("use.activate"); private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); public ExampleItem(Properties properties) { super(properties); // Register our item as server-side handled. // This enables both animation data syncing and server-side animation triggering SingletonGeoAnimatable.registerSyncedAnimatable(this); } // Utilise the existing forge hook to define our custom renderer @Override public void initializeClient(Consumer consumer) { consumer.accept(new IClientItemExtensions() { private ExampleItemRenderer renderer; @Override public BlockEntityWithoutLevelRenderer getCustomRenderer() { if (this.renderer == null) this.renderer = new ExampleItemRenderer(); return this.renderer; } }); } @Override public void registerControllers(AnimatableManager.ControllerRegistrar controllers) { controllers.add(new AnimationController<>(this, "Activation", 0, state -> PlayState.STOP) .triggerableAnim("activate", ACTIVATE_ANIM)); // We've marked the "activate" animation as being triggerable from the server } // Let's handle our use method so that we activate the animation when right-clicking while holding the box @Override public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { if (level instanceof ServerLevel serverLevel) triggerAnim(player, GeoItem.getOrAssignId(player.getItemInHand(hand), serverLevel), "Activation", "activate"); return super.use(level, player, hand); } @Override public AnimatableInstanceCache getAnimatableInstanceCache() { return this.cache; } } ``` -------------------------------- ### Example BlockEntity Class Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Blocks-(Geckolib4) Extends BlockEntity and implements GeoBlockEntity to enable Geckolib animations. Requires setting up animation controllers and an animatable instance cache. ```java public class ExampleBlockEntity extends BlockEntity implements GeoBlockEntity { protected static final RawAnimation DEPLOY_ANIM = RawAnimation.begin().thenPlayOnce("misc.deploy").thenLoop("misc.idle"); private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); public ExampleEntity(BlockPos pos, BlockState state) { super(MyBlockEntities.EXAMPLE_BLOCK_ENTITY.get(), pos, state); } @Override public void registerControllers(AnimatableManager.ControllerRegistrar controllers) { controllers.add(new AnimationController<>(this, this::deployAnimController)); } protected PlayState deployAnimController(final AnimationState state) { return state.setAndContinue(DEPLOY_ANIM); } @Override public AnimatableInstanceCache getAnimatableInstanceCache() { return this.cache; } } ``` -------------------------------- ### Example BlockEntity Renderer Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Blocks-(Geckolib4) Extends GeoBlockRenderer to render a custom block entity. Requires an instance of your GeoModel. ```java public class ExampleBlockEntityRenderer extends GeoBlockRenderer { public ExampleBlockEntityRenderer(EntityRendererProvider.Context context) { super(new ExampleBlockEntityModel()); } } ``` -------------------------------- ### Example Item Class (1.21.1+) Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Items-(Geckolib4) Implement a custom item that supports Geckolib animations for Minecraft 1.21.1 and later. This version uses a different hook for defining the custom renderer. ```java public final class ExampleItem extends Item implements GeoItem { private static final RawAnimation ACTIVATE_ANIM = RawAnimation.begin().thenPlay("use.activate"); private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); public ExampleItem(Properties properties) { super(properties); // Register our item as server-side handled. // This enables both animation data syncing and server-side animation triggering SingletonGeoAnimatable.registerSyncedAnimatable(this); } // Utilise our own render hook to define our custom renderer @Override public void createGeoRenderer(Consumer consumer) { consumer.accept(new GeoRenderProvider() { private ExampleItemRenderer renderer; @Override public BlockEntityWithoutLevelRenderer getGeoItemRenderer() { if (this.renderer == null) this.renderer = new ExampleItemRenderer(); return this.renderer; } }); } @Override ``` -------------------------------- ### Example Item Class (Fabric 1.19.3-1.20.6) Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Items-(Geckolib4) Implement a custom item that supports Geckolib animations for Fabric. This includes registering the item for server-side handling and defining its custom renderer using a supplier. ```java public final class ExampleItem extends Item implements GeoItem { private static final RawAnimation ACTIVATE_ANIM = RawAnimation.begin().thenPlay("use.activate"); private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); private final Supplier renderProvider = GeoItem.makeRenderer(this); public ExampleItem(Properties properties) { super(properties); // Register our item as server-side handled. // This enables both animation data syncing and server-side animation triggering SingletonGeoAnimatable.registerSyncedAnimatable(this); } // Utilise our own render hook to define our custom renderer @Override public void createRenderer(Consumer consumer) { consumer.accept(new RenderProvider() { private ExampleItemRenderer renderer; @Override public BlockEntityWithoutLevelRenderer getCustomRenderer() { if (this.renderer == null) this.renderer = new ExampleItemRenderer(); return this.renderer; } }); } @Override public Supplier getRenderProvider() { return this.renderProvider; } @Override public void registerControllers(AnimatableManager.ControllerRegistrar controllers) { controllers.add(new AnimationController<>(this, "Activation", 0, state -> PlayState.STOP) .triggerableAnim("activate", ACTIVATE_ANIM)); // We've marked the "activate" animation as being triggerable from the server } // Let's handle our use method so that we activate the animation when right-clicking while holding the box @Override public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { if (level instanceof ServerLevel serverLevel) triggerAnim(player, GeoItem.getOrAssignId(player.getItemInHand(hand), serverLevel), "Activation", "activate"); return super.use(level, player, hand); } @Override public AnimatableInstanceCache getAnimatableInstanceCache() { return this.cache; } } ``` -------------------------------- ### Setup Geckolib Armor Renderer (Fabric) Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Armor-(Geckolib4) For Fabric, you need to set up a custom render provider for your item class. This involves caching a renderer and returning it in the getter provided by GeoItem. ```java private final Supplier renderProvider = GeoItem.makeRenderer(this); @Override public Supplier getRenderProvider() { return this.renderProvider; } ``` -------------------------------- ### Example Armor Item Class with Geckolib Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Armor-(Geckolib4) This class demonstrates how to create a custom armor item that utilizes Geckolib for animations and rendering. It extends `ArmorItem` and implements `GeoItem`, setting up the animation cache, client-side extensions for rendering, and registering an animation controller. ```java public final class ExampleArmorItem extends ArmorItem implements GeoItem { private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); public ExampleArmorItem(ArmorMaterial armorMaterial, Type type, Properties properties) { super(armorMaterial, type, properties); } // Create our armor model/renderer for forge and return it @Override public void initializeClient(Consumer consumer) { consumer.accept(new IClientItemExtensions() { private GeoArmorRenderer renderer; @Override public @NotNull HumanoidModel getHumanoidArmorModel(LivingEntity livingEntity, ItemStack itemStack, EquipmentSlot equipmentSlot, HumanoidModel original) { if (this.renderer == null) this.renderer = new ExampleArmorRenderer(); // This prepares our GeoArmorRenderer for the current render frame. // These parameters may be null however, so we don't do anything further with them this.renderer.prepForRender(livingEntity, itemStack, equipmentSlot, original); return this.renderer; } }); } // Let's add our animation controller @Override public void registerControllers(AnimatableManager.ControllerRegistrar controllers) { controllers.add(new AnimationController<>(this, 20, state -> { // Apply our generic idle animation. // Whether it plays or not is decided down below. state.setAnimation(DefaultAnimations.IDLE); // Let's gather some data from the state to use below // This is the entity that is currently wearing/holding the item Entity entity = state.getData(DataTickets.ENTITY); // We'll just have ArmorStands always animate, so we can return here if (entity instanceof ArmorStand) return PlayState.CONTINUE; // For this example, we only want the animation to play if the entity is wearing all pieces of the armor // Let's collect the armor pieces the entity is currently wearing Set wornArmor = new ObjectOpenHashSet<>(); for (ItemStack stack : entity.getArmorSlots()) { // We can stop immediately if any of the slots are empty if (stack.isEmpty()) return PlayState.STOP; wornArmor.add(stack.getItem()); } // Check each of the pieces match our set boolean isFullSet = wornArmor.containsAll(ObjectArrayList.of( ItemRegistry.EXAMPLE_ARMOR_BOOTS.get(), ItemRegistry.EXAMPLE_ARMOR_LEGGINGS.get(), ItemRegistry.EXAMPLE_ARMOR_CHESTPLATE.get(), ItemRegistry.EXAMPLE_ARMOR_HELMET.get())); // Play the animation if the full set is being worn, otherwise stop return isFullSet ? PlayState.CONTINUE : PlayState.STOP; })); } @Override public AnimatableInstanceCache getAnimatableInstanceCache() { return this.cache; } } ``` -------------------------------- ### Preview Variables for Arc Animation Source: https://github.com/bernie-g/geckolib/wiki/Molang Defines variables used in the arc animation example. `temp.control_height` sets the peak of the arc. ```Molang temp.control_height = 50; ``` -------------------------------- ### Example Item Display JSON Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Items-(Geckolib4) This JSON file is required for all items, including GeckoLib items. It defines the item's rotation, scaling, and positioning. Including `"parent": "builtin/entity"` tells GeckoLib to render the item. ```json { "parent": "builtin/entity" } ``` -------------------------------- ### Example Armor Item Class with Geckolib 4 Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Armor-(Geckolib4) This class demonstrates how to create a custom armor item using Geckolib 4. It extends `ArmorItem` and implements `GeoItem`, setting up the animation cache, render provider, and an animation controller that checks for a full set of armor before playing an animation. The animation logic is contained within the `registerControllers` method. ```java public final class ExampleArmorItem extends ArmorItem implements GeoItem { private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); private final Supplier renderProvider = GeoItem.makeRenderer(this); public ExampleArmorItem(ArmorMaterial armorMaterial, ArmorItem.Type type, Properties properties) { super(armorMaterial, type, properties); } // Create our armor model/renderer for Fabric and return it @Override public void createRenderer(Consumer consumer) { consumer.accept(new RenderProvider() { private GeoArmorRenderer renderer; @Override public HumanoidModel getHumanoidArmorModel(LivingEntity livingEntity, ItemStack itemStack, EquipmentSlot equipmentSlot, HumanoidModel original) { if(this.renderer == null) this.renderer = new ExampleArmorRenderer(); // This prepares our GeoArmorRenderer for the current render frame. // These parameters may be null however, so we don't do anything further with them this.renderer.prepForRender(livingEntity, itemStack, equipmentSlot, original); return this.renderer; } }); } @Override public Supplier getRenderProvider() { return this.renderProvider; } // Let's add our animation controller @Override public void registerControllers(AnimatableManager.ControllerRegistrar controllers) { controllers.add(new AnimationController<>(this, 20, state -> { // Apply our generic idle animation. // Whether it plays or not is decided down below. state.getController().setAnimation(DefaultAnimations.IDLE); // Let's gather some data from the state to use below // This is the entity that is currently wearing/holding the item Entity entity = state.getData(DataTickets.ENTITY); // We'll just have ArmorStands always animate, so we can return here if (entity instanceof ArmorStand) return PlayState.CONTINUE; // For this example, we only want the animation to play if the entity is wearing all pieces of the armor // Let's collect the armor pieces the entity is currently wearing Set wornArmor = new ObjectOpenHashSet<>(); for (ItemStack stack : entity.getArmorSlots()) { // We can stop immediately if any of the slots are empty if (stack.isEmpty()) return PlayState.STOP; wornArmor.add(stack.getItem()); } // Check each of the pieces match our set boolean isFullSet = wornArmor.containsAll(ObjectArrayList.of( ItemRegistry.EXAMPLE_ARMOR_BOOTS, ItemRegistry.EXAMPLE_ARMOR_LEGGINGS, ItemRegistry.EXAMPLE_ARMOR_CHESTPLATE, ItemRegistry.EXAMPLE_ARMOR_HELMET)); // Play the animation if the full set is being worn, otherwise stop return isFullSet ? PlayState.CONTINUE : PlayState.STOP; })); } @Override public AnimatableInstanceCache getAnimatableInstanceCache() { return this.cache; } } ``` -------------------------------- ### Example GeoArmorRenderer Class Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Armor-(Geckolib4) This class extends `GeoArmorRenderer` and is used to define the custom armor model and its rendering logic. It specifies the Geo model to be used for the armor. ```java public final class ExampleArmorRenderer extends GeoArmorRenderer { public ExampleArmorRenderer() { super(new DefaultedItemGeoModel<>(new ResourceLocation(ExampleMod.MOD_ID, "armor/example_armor"))); // Using DefaultedItemGeoModel like this puts our 'location' as item/armor/example armor in the assets folders. } } ``` -------------------------------- ### Client Setup for GeoRenderProvider in Split Sources Source: https://github.com/bernie-g/geckolib/wiki/Split-Sources-Support-(Geckolib4) This Java code shows the client-side initialization for a GeoItem in a split-sources environment. It sets the GeoRenderProvider for the item's renderProviderHolder, providing a custom renderer instance. ```java @Override public void onInitializeClient() { ExampleModItems.EXAMPLE_ITEM.renderProviderHolder.setValue(new GeoRenderProvider() { private ExampleItemRenderer renderer; @Override public BlockEntityWithoutLevelRenderer getGeoItemRenderer() { if (this.renderer == null) this.renderer = new ExampleItemRenderer(); return this.renderer; } }); } ``` -------------------------------- ### Example Entity Class with GeckoLib Source: https://github.com/bernie-g/geckolib/wiki/Custom-GeckoLib-Entity Implement this class to create a custom entity that utilizes GeckoLib for animations. Ensure it extends GeoAnimatable and overrides necessary methods for animation controller registration and instance caching. ```java public class ExampleEntity extends PathfinderMob implements GeoEntity { private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); public ExampleEntity(EntityType type, Level level) { super(type, level); } @Override public void registerControllers(AnimatableManager.ControllerRegistrar controllers) { controllers.add(new AnimationController<>(this, "idle", 5, state -> state.setAndContinue(DefaultAnimations.IDLE))); } @Override public AnimatableInstanceCache getAnimatableInstanceCache() { return this.cache; } } ``` -------------------------------- ### Example GeckoLib Entity Renderer Source: https://github.com/bernie-g/geckolib/wiki/Custom-GeckoLib-Entity Create a custom entity renderer by extending GeoEntityRenderer and providing the appropriate entity model. This class handles the visual rendering of your animated entity. ```java public class ExampleGeoRenderer extends GeoEntityRenderer { public ExampleGeoRenderer(EntityRendererProvider.Context renderManager) { super(renderManager, new ExampleEntityModel()); } } ``` -------------------------------- ### Compound Expression Example Source: https://github.com/bernie-g/geckolib/wiki/Molang-(Geckolib4) Demonstrates a compound Molang expression that sets a local variable and then returns an animation value. Expressions are separated by a semicolon ';', and the last expression determines the return value. ```molang v.is_animating_walk = 1;math.sin(query.anim_time) ``` -------------------------------- ### Example Armor Item Class with Geckolib Integration Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Armor-(Geckolib4) This class extends `ArmorItem` and implements `GeoItem` to integrate Geckolib's animation and rendering capabilities for custom armor. It sets up the animation cache, defines the Geo renderer, and registers animation controllers. ```java public final class ExampleArmorItem extends ArmorItem implements GeoItem { private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); public ExampleArmorItem(Holder armorMaterial, ArmorItem.Type type, Properties properties) { super(armorMaterial, type, properties); } // Create our armor model/renderer for Fabric and return it @Override public void createGeoRenderer(Consumer consumer) { consumer.accept(new GeoRenderProvider() { private GeoArmorRenderer renderer; @Override public HumanoidModel getGeoArmorRenderer(@Nullable T livingEntity, ItemStack itemStack, @Nullable EquipmentSlot equipmentSlot, @Nullable HumanoidModel original) { if(this.renderer == null) this.renderer = new ExampleArmorRenderer(); return this.renderer; } }); } // Let's add our animation controller @Override public void registerControllers(AnimatableManager.ControllerRegistrar controllers) { controllers.add(new AnimationController<>(this, 20, state -> { // Apply our generic idle animation. // Whether it plays or not is decided down below. state.getController().setAnimation(DefaultAnimations.IDLE); // Let's gather some data from the state to use below // This is the entity that is currently wearing/holding the item Entity entity = state.getData(DataTickets.ENTITY); // We'll just have ArmorStands always animate, so we can return here if (entity instanceof ArmorStand) return PlayState.CONTINUE; // For this example, we only want the animation to play if the entity is wearing all pieces of the armor // Let's collect the armor pieces the entity is currently wearing Set wornArmor = new ObjectOpenHashSet<>(); for (ItemStack stack : entity.getArmorSlots()) { // We can stop immediately if any of the slots are empty if (stack.isEmpty()) return PlayState.STOP; wornArmor.add(stack.getItem()); } // Check each of the pieces match our set boolean isFullSet = wornArmor.containsAll(ObjectArrayList.of( ItemRegistry.EXAMPLE_ARMOR_BOOTS, ItemRegistry.EXAMPLE_ARMOR_LEGGINGS, ItemRegistry.EXAMPLE_ARMOR_CHESTPLATE, ItemRegistry.EXAMPLE_ARMOR_HELMET)); // Play the animation if the full set is being worn, otherwise stop return isFullSet ? PlayState.CONTINUE : PlayState.STOP; })); } @Override public AnimatableInstanceCache getAnimatableInstanceCache() { return this.cache; } } ``` -------------------------------- ### Example Item Class with GeoRenderProvider Holder Source: https://github.com/bernie-g/geckolib/wiki/Split-Sources-Support-(Geckolib4) This Java code demonstrates how to create a GeoItem class that holds a GeoRenderProvider using MutableObject for split-sources support. It initializes the renderProviderHolder and retrieves its value in createGeoRenderer. ```java public class ExampleItem extends Item implements GeoItem { // Create the object to store the RenderProvider public final MutableObject renderProviderHolder = new MutableObject<>(); private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this); public ExampleItem(Settings settings) { super(settings); } @Override public void createGeoRenderer(Consumer consumer) { // Return the cached RenderProvider consumer.accept(this.renderProviderHolder.getValue()); } @Override public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {} @Override public AnimatableInstanceCache getAnimatableInstanceCache() { return this.geoCache; } } ``` -------------------------------- ### Play and Control Animations in StatelessAnimatable Source: https://github.com/bernie-g/geckolib/wiki/Stateless-Animations-(Geckolib4) Use the `playAnimation` and `stopAnimation` methods from the `StatelessAnimatable` interface to control animations. This example demonstrates playing a living animation constantly and switching between walking and idle animations based on movement. It's recommended to prefer client-side animation updates unless server-side logic is specifically required. ```java public class MyEntity extends PathfinderMob implements StatelessGeoEntity { //... @Override public void tick() { super.tick(); // Preference the client side unless you need the server side for some reason. The code is the same either way. if (level().isClientSide()) { // Just play the living animation all the time playAnimation(DefaultAnimations.LIVING); if (getDeltaMovement().horizontalDistanceSqr() > 0.01) { // Play the walking animation if we're moving, and stop the idle animation playAnimation(DefaultAnimations.WALK); stopAnimation(DefaultAnimations.IDLE); } else { // Play the idle animation if we're not moving, and stop the walking animation playAnimation(DefaultAnimations.IDLE); stopAnimation(DefaultAnimations.WALK); } } } } ``` -------------------------------- ### Geckolib 1.21.1+ GeoRenderer Setup Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Items-(Geckolib4) For Geckolib versions 1.21.1 and later, override createGeoRenderer to provide a GeoRenderProvider. The getGeoItemRenderer method within this provider should cache and return your renderer instance. ```java @Override public void createGeoRenderer(Consumer consumer) { consumer.accept(new GeoRenderProvider() { private ExampleItemRenderer renderer; @Override public BlockEntityWithoutLevelRenderer getGeoItemRenderer() { if (this.renderer == null) this.renderer = new ExampleItemRenderer(); return renderer; } }); } ``` -------------------------------- ### Complex Molang Expression Example Source: https://github.com/bernie-g/geckolib/wiki/Molang-(Geckolib4) A complex Molang expression combining arithmetic, absolute value, modulo, queries, and multiplication. This demonstrates the power and flexibility of Molang for intricate animation logic. ```molang ((-0.2 + 1.5 * (math.abs(math.mod(query.ground_speed, 13) - 6.5) - 3.25) / 3.25) * query.ground_speed) * 57.3 ``` -------------------------------- ### Implement StatelessAnimatable Interface Source: https://github.com/bernie-g/geckolib/wiki/Stateless-Animations-(Geckolib4) When using stateless animations, implement the appropriate stateless animatable interface for your entity type instead of the default one. This example shows implementing StatelessGeoEntity for a custom entity. ```java public class MyEntity extends PathfinderMob implements StatelessGeoEntity { //... } ``` -------------------------------- ### Create RawAnimation with begin() Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-4-Changes Create `RawAnimation` instances using `RawAnimation.begin()` followed by chaining animation methods. Cache these instances in static fields to avoid recreation. ```java private static final RawAnimation SPIN_ANIM = RawAnimation.begin().thenPlay("misc.spin"); ``` -------------------------------- ### Get Animatable Instance Cache Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Items-(Geckolib4) Implement this method to provide the AnimatableInstanceCache for your item, which is essential for Geckolib's animation management. ```java @Override public AnimatableInstanceCache getAnimatableInstanceCache() { return this.cache; } } ``` -------------------------------- ### Basic Walking Animation Controller Source: https://github.com/bernie-g/geckolib/wiki/The-Animation-Controller-(Geckolib4) Sets up an AnimationController to play a walking animation when the entity is moving, and stops playback otherwise. This is useful for simple movement-based animations. ```java public void registerControllers(AnimatableManager.ControllerRegistrar controllers) { controllers.add(new AnimationController<>(this, "Walking", state -> { return state.isMoving() ? state.setAndContinue(DefaultAnimations.WALK) : PlayState.STOP; })); } ``` -------------------------------- ### DefaultedEntityGeoModel with Head Rotation Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-4-Changes Utilize the alternate constructor of DefaultedEntityGeoModel to automatically handle head bone rotation. This simplifies setup for entities that require head tracking. ```java public class MyEntityModel extends DefaultedEntityGeoModel { public MyEntityModel() { super(new ResourceLocation(MyMod.MOD_ID, "monster/my_entity"), true); } } ``` -------------------------------- ### Execute Java Command (Shell Script) Source: https://github.com/bernie-g/geckolib/blob/main/gradlew.txt Executes the Java command with the constructed arguments. This is the final step in launching the Gradle wrapper. ```shell exec "$JAVACMD" "$@" ``` -------------------------------- ### DefaultedEntityGeoModel Usage in GeckoLib 4 Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-4-Changes Example of extending DefaultedEntityGeoModel for simplified asset path management. This automatically sets up paths for animations, models, and textures based on the provided ResourceLocation. ```java public class MyEntityModel extends DefaultedEntityGeoModel { public MyEntityModel() { super(new ResourceLocation(MyMod.MOD_ID, "monster/my_entity")); } // This creates a new GeoModel with the following asset paths: // Animation Json: assets/mymod/animations/entity/monster/my_entity.animation.json // Model Json: assets/mymod/geo/entity/monster/my_entity.geo.json // Texture: assets/mymod/textures/entity/monster/my_entity.png } ``` -------------------------------- ### Arc Movement in Molang Source: https://github.com/bernie-g/geckolib/wiki/Molang Moves an object along a curved path using linear interpolation. This example arcs a bone between two points, with `temp.control_height` defining the apex of the arc. ```Molang X: Math.lerp(-10, 10, query.anim_time) ``` ```Molang Y: Math.lerp(Math.lerp(0, temp.control_height, query.anim_time), Math.lerp(temp.control_height, 0, query.anim_time), query.anim_time) ``` ```Molang Z: 0 ``` -------------------------------- ### Using Math Functions Source: https://github.com/bernie-g/geckolib/wiki/Molang-(Geckolib4) Shows how to use built-in math functions like `math.cos` in Molang expressions. This allows for procedural animation effects. ```molang math.cos(5) ``` -------------------------------- ### Forge Armor Rendering with IClientItemExtensions Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-4-Changes For Forge, implement `IClientItemExtensions` to provide a custom `GeoArmorRenderer` for armor. The `prepForRender` method is used to prepare the renderer for the current frame. ```java public void initializeClient(Consumer consumer) { consumer.accept(new IClientItemExtensions() { private GeoArmorRenderer renderer; @Override public @NotNull HumanoidModel getHumanoidArmorModel(LivingEntity livingEntity, ItemStack itemStack, EquipmentSlot equipmentSlot, HumanoidModel original) { if (this.renderer == null) this.renderer = new MyArmorRenderer(); // This prepares our GeoArmorRenderer for the current render frame. // These parameters may be null however, so we don't do anything further with them renderer.prepForRender(livingEntity, itemStack, equipmentSlot, original); return this.renderer; } }); } ``` -------------------------------- ### Fabric GeoItem Renderer Setup Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Items-(Geckolib4) For Fabric, use GeoItem#makeRenderer to create a render provider for animatable items. This provider must be cached as a Supplier and returned by getRenderProvider. ```java private final Supplier renderProvider = GeoItem.makeRenderer(this); ``` ```java @Override public Supplier getRenderProvider() { return this.renderProvider; } ``` -------------------------------- ### Using Game Queries Source: https://github.com/bernie-g/geckolib/wiki/Molang-(Geckolib4) Illustrates the use of game queries, such as `query.anim_time`, to retrieve in-game values for use in Molang expressions. This enables animations to react to game state. ```molang math.cos(query.anim_time) ``` -------------------------------- ### Add GeckoLib Repository (1.20.5+) Source: https://github.com/bernie-g/geckolib/wiki/Installation-(Geckolib4) Configure your build.gradle to include the GeckoLib Maven repository. This is required for all mod loaders. ```groovy // This is the repositories block in your build.gradle. NOT the one in publishing, or in buildscript. If it does not exist already, create it. repositories { maven { name = 'GeckoLib' url 'https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/' content { includeGroup("software.bernie.geckolib") } } } ``` -------------------------------- ### Basic Arithmetic Expression Source: https://github.com/bernie-g/geckolib/wiki/Molang-(Geckolib4) Demonstrates a simple arithmetic expression in Molang. This can be used in animation keyframes to define values dynamically. ```molang 5 * 4 ``` -------------------------------- ### Parsing JVM Options with xargs and sed (Shell Script) Source: https://github.com/bernie-g/geckolib/blob/main/gradlew.txt Parses JVM options from environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, GRADLE_OPTS) using 'xargs' and 'sed' to safely pass them to the 'set' command. This handles shell metacharacters by escaping them. ```shell # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. # # In Bash we could simply go: # # readarray ARGS < <( xargs -n1 <<<"$var" ) && # set -- "${ARGS[@]}" "$@" # # but POSIX shell has neither arrays nor command substitution, so instead we # post-process each arg (as a line of input to sed) to backslash-escape any # character that might be a shell metacharacter, then use eval to reverse # that process (while maintaining the separation between arguments), and wrap # the whole thing up as a single "set" statement. # # This will of course break if any of these variables contains a newline or # an unmatched quote. # eval "set -- $( printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | xargs -n1 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | tr '\n' ' ' )" '"$@"' ``` -------------------------------- ### Item and Rendering Queries Source: https://github.com/bernie-g/geckolib/wiki/Molang-(Geckolib4) Queries related to item properties like stackability and maximum use duration, as well as entity rendering time. ```APIDOC ## query.is_stackable ### Description Returns 1 if the itemstack is stackable, otherwise 0. ### Applies To Item ``` ```APIDOC ## query.item_max_use_duration ### Description The number of ticks the item can be used for at a maximum. ### Applies To Item ``` ```APIDOC ## query.life_time ### Description The amount of time (in seconds) that the entity has been rendering for since the game started. ### Applies To Any animatable ``` -------------------------------- ### Default JVM Options (Shell Script) Source: https://github.com/bernie-g/geckolib/blob/main/gradlew.txt Sets default JVM options for memory allocation. These can be overridden by environment variables like JAVA_OPTS and GRADLE_OPTS. ```shell # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' ``` -------------------------------- ### Add GeckoLib Repository and Dependencies (Forge 1.19.3-1.20.4) Source: https://github.com/bernie-g/geckolib/wiki/Installation-(Geckolib4) Configure your build.gradle with the GeckoLib repository and the Forge dependency for Minecraft 1.19.3 to 1.20.4. Also includes the mclib dependency. ```groovy // This is the repositories block in your build.gradle. NOT the one in publishing, or in buildscript. If it does not exist already, create it. maven { name = 'GeckoLib' url 'https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/' content { includeGroupByRegex("software\.bernie.*") includeGroup("com.eliotlash.mclib") } } dependencies { implementation fg.deobf("software.bernie.geckolib:geckolib-forge-${minecraft_version}:${geckolib_version}") implementation("com.eliotlash.mclib:mclib:20") } ``` -------------------------------- ### Instantiate and Prepare GeoArmorRenderer (Fabric) Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Armor-(Geckolib4) Override the `createRenderer` method in your item class to instantiate your custom GeoArmorRenderer. Ensure the renderer is created only when needed to avoid potential mod incompatibilities. ```java @Override public void createRenderer(Consumer consumer) { consumer.accept(new RenderProvider() { private GeoArmorRenderer renderer; @Override public HumanoidModel getHumanoidArmorModel(LivingEntity livingEntity, ItemStack itemStack, EquipmentSlot equipmentSlot, HumanoidModel original) { if(this.renderer == null) // Important that we do this. If we just instantiate it directly in the field it can cause incompatibilities with some mods. this.renderer = new ExampleArmorRenderer(); // This prepares our GeoArmorRenderer for the current render frame. // These parameters may be null however, so we don't do anything further with them this.renderer.prepForRender(livingEntity, itemStack, equipmentSlot, original); return this.renderer; } }); } ``` -------------------------------- ### Argument Construction for Java Command (Shell Script) Source: https://github.com/bernie-g/geckolib/blob/main/gradlew.txt Constructs the arguments for the Java command, including application name, classpath, and the Gradle wrapper JAR. It also incorporates environment variables for JVM options. ```shell # Collect all arguments for the java command: # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" ``` -------------------------------- ### GeckoLib Dependency Configuration (Gradle) Source: https://github.com/bernie-g/geckolib/wiki/Installation-(Geckolib4) Configure your build.gradle file to include the GeckoLib repository and dependencies. This block should be placed in the repositories section of your build.gradle file. ```groovy // This is the repositories block in your build.gradle. NOT the one in publishing, or in buildscript. If it does not exist already, create it. maven { name = 'GeckoLib' url 'https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/' content { includeGroupByRegex("software\\.bernie.*") includeGroup("com.eliotlash.mclib") } } ``` -------------------------------- ### Preview Variables for Animation Speed Control Source: https://github.com/bernie-g/geckolib/wiki/Molang Sets up preview variables for controlling animation speed. `temp.control_height` defines the arc height, and `anim_speed` is dynamically set based on `query.anim_time`. ```Java temp.control_height = 80; anim_speed = query.anim_time / 2; ``` -------------------------------- ### Add GeckoLib Repository and Dependencies (Fabric 1.19.3-1.20.4) Source: https://github.com/bernie-g/geckolib/wiki/Installation-(Geckolib4) Configure your build.gradle with the GeckoLib repository and the Fabric dependency for Minecraft 1.19.3 to 1.20.4. Also includes the mclib dependency. ```groovy // This is the repositories block in your build.gradle. NOT the one in publishing, or in buildscript. If it does not exist already, create it. maven { name = 'GeckoLib' url 'https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/' content { includeGroupByRegex("software\.bernie.*") includeGroup("com.eliotlash.mclib") } } dependencies { modImplementation("software.bernie.geckolib:geckolib-fabric-${minecraft_version}:${geckolib_version}") implementation("com.eliotlash.mclib:mclib:20") } ``` -------------------------------- ### Forge Client Item Extensions Source: https://github.com/bernie-g/geckolib/wiki/Geckolib-Items-(Geckolib4) Implement IClientItemExtensions to provide custom item rendering on Forge. Ensure the renderer is instantiated only when needed to prevent race conditions. ```java @Override public void initializeClient(Consumer consumer) { consumer.accept(new IClientItemExtensions() { private ExampleItemRenderer renderer = null; // Don't instantiate until ready. This prevents race conditions breaking things @Override public BlockEntityWithoutLevelRenderer getItemStackRenderer() { if (this.renderer == null) this.renderer = new ExampleItemRenderer(); return renderer; } }); } ``` -------------------------------- ### Apply Mixins Plugin (Forge 1.20.5+) Source: https://github.com/bernie-g/geckolib/wiki/Installation-(Geckolib4) Configure your settings.gradle to include the SpongePowered Maven repository for the mixins plugin, then apply the plugin in your build.gradle. ```groovy pluginManagement { repositories { maven { url = 'https://repo.spongepowered.org/repository/maven-public/' } } } ``` ```groovy plugins { id 'org.spongepowered.mixin' version '0.7.+' } ``` -------------------------------- ### Define GeckoLib Version Property Source: https://github.com/bernie-g/geckolib/wiki/Installation-(Geckolib4) Add the geckolib_version property to your gradle.properties file, replacing the placeholder with the actual latest version. ```properties geckolib_version=??? Replace this with the current latest version of GeckoLib from Curseforge for your Minecraft version ``` -------------------------------- ### Add GeckoLib Dependency (NeoForge 1.20.5+) Source: https://github.com/bernie-g/geckolib/wiki/Installation-(Geckolib4) Include the GeckoLib NeoForge dependency in your build.gradle file for Minecraft 1.20.5 and newer. ```groovy dependencies { implementation "software.bernie.geckolib:geckolib-neoforge-${minecraft_version}:${geckolib_version}" } ``` -------------------------------- ### Controlling Animation Speed with Molang Variables Source: https://github.com/bernie-g/geckolib/wiki/Molang Demonstrates how to control animation speed dynamically. A custom variable `anim_speed` is used, which can be set externally or calculated, affecting the interpolation. ```Molang X: Math.lerp(-30, 30, query.anim_time * anim_speed) ``` ```Molang Y: Math.lerp(Math.lerp(0, temp.control_height, query.anim_time * anim_speed), Math.lerp(temp.control_height, 0, query.anim_time * anim_speed), query.anim_time * anim_speed) ``` ```Molang Z: 0 ``` -------------------------------- ### Basic .mcmeta Structure for Animated Textures Source: https://github.com/bernie-g/geckolib/wiki/Animated-Textures-(Geckolib4) This is the basic JSON structure required in the .png.mcmeta file to enable texture animation. Additional properties can be added within the 'animation' block to control specific animation behaviors. ```json { "animation": { } } ``` -------------------------------- ### Walking, Running, and Idling Animation Controller Source: https://github.com/bernie-g/geckolib/wiki/The-Animation-Controller-(Geckolib4) Implements a more complex controller that plays running, walking, or idling animations based on movement and sprinting status. Ensures an animation is always playing. ```java public void registerControllers(AnimatableManager.ControllerRegistrar controllers) { controllers.add(new AnimationController<>(this, "Walk/Run/Idle", state -> { if (state.isMoving()) return state.setAndContinue(MyEntity.this.isSprinting() ? DefaultAnimations.RUN : DefaultAnimations.WALK); return state.setAndContinue(DefaultAnimations.IDLE); })); } ```