Links
Tags
Creators
Details
1.21.1-1.0.0
Compatibility
Changes
1.0.0 — 2026-07-04
Minecraft 1.21.1
⚠️ Breaking changes. This release renames the core API classes across the entire framework. Any mod built against 0.1.0-alpha must update its imports. See the rename table below.
First stable release. Establishes the canonical Family / Variant / Appearance three-tier terminology across HZLib, adds the full NBT data pipeline, declarative bone visibility, and idle slot animation system.
Breaking: API Rename (ADR_018)
The Internal* prefix has been removed from all public API classes. Every name now reflects its tier and role directly.
| Old name | New name |
|---|---|
InternalEntity |
NativeEntity |
InternalEntityType<T> |
NativeEntityFamily<T> |
InternalLogic |
EntityLogic |
InternalParticle |
EntityParticles |
InternalLayerRenderer<T> (Common) |
LayerRenderPipeline<T> |
InternalAnimation (Fabric / Forge / NeoForge) |
NativeAnimation |
InternalModel<T> (Fabric / Forge / NeoForge) |
NativeModel<T> |
InternalLayerRenderer<T> (Fabric / Forge / NeoForge) |
NativeRenderer<T> |
Why: Internal had accumulated three unrelated meanings — entity base class, family descriptor, GeckoLib integration layer, and utility helpers. The new names encode both tier (Native* = HZLib root layer) and role (*Family = family descriptor, *Pipeline = render coordinator) so a class's responsibility is readable from its name alone.
Not yet renamed (deferred to a future release):
IInternalRenderLayer— render layer interfacenativeEntityfield onNativeEntity— field rename is a higher blast-radius operation
New: NBT Data Pipeline (ADR_019)
A version-agnostic, type-safe entity data pipeline. All HZLib pipeline code now operates on DataCompound — a pure-Java wrapper — never directly on MC-native tag types. This is what makes HZLib backportable to 1.12.2 and 1.7.10 without rewriting the save/load layer.
DataCompound— pure-Java version-agnostic NBT wrapper interface. The only point of contact with the MC NBT API is the adapter implementation, which lives in the version-specific source set.NbtAdapterFactory— registration point for the MC-version-specificDataCompoundimplementation. Registered once at mod init.CompoundTagDataCompound— the 1.21.1CompoundTagimplementation ofDataCompound.DataType<T>—INT,FLOAT,BOOLEAN,STRING,UUID. UUID handling is version-safe — the adapter selects the correct storage strategy per MC version automatically.DataField<T>— typed field handles. The NBT string key is encapsulated inside the handle — zero string literals at call sites. A typo in a field reference is a compile error, not a silent default value.EntityDataSchema— declares the ordered set ofDataField<?>handles that define an entity family's saved data. Write and read go through the schema — no field names appear in save/load methods.MigrationStep/MigrationChain— sole migration authority. Each step receives and returns aDataCompound, enabling cross-field migration. Per-field migrators are deliberately excluded — migration logic belongs here only.FieldValueProvider/FieldValueConsumer— typed interfaces for entity ↔ schema communication. No string keys at call sites.
New: Bone Visibility Feature (ADR_022)
BoneVisibilityFeature— declarative per-bone show/hide rules attached to aNativeEntityFamily. Evaluated each frame inNativeModel.setCustomAnimations().BoneCondition—@FunctionalInterface, evaluated client-side per render frame. Must be fast — no world queries, no allocations.BoneRule— pairs a bone name with aBoneConditionand a hide/show polarity.
Replaces all reflection-based bone access (getBone / setHidden via reflection). GeckoLib types remain in loader modules where they belong — BoneVisibilityFeature and its conditions are pure Java in HZLib Common.
New: Idle Slot Animation System (ADR_022)
Replaces tick-driven standby logic (handleStandbyAnimation()) with a declarative idle state profile. Eliminates standby animation flicker structurally.
IdleCondition—@FunctionalInterfaceevaluated per locomotion controller tick.IdleSlot— pairs anAnimationPoolwith anIdleCondition, a priority, and an activation threshold in ticks. Higher priority slots are evaluated first; a slot activates only once its condition has held for the threshold duration.idleStationaryTicksonNativeEntity— incremented each tick the entity is not moving and not in a vehicle; reset on movement.IdleSlotthreshold comparisons operate on this counter — stable once crossed, no per-frame re-evaluation.AnimationProfilegainsidleSlots— the existing.idle()shorthand implicitly creates a priority-0, always-true, zero-threshold slot, guaranteeing every profile has a fallback.onIdleSlotChanged()hook onNativeEntity— called when the winning idle slot changes; override in subclasses to react (e.g. update hitbox on sit/stand transition).
New: headBoneName on NativeEntityFamily
The head bone name used for look-tracking in NativeModel.setCustomAnimations() is now a configurable field on the family descriptor (.headBone("head_bone_name")). Eliminates the hardcoded "head" string that was embedded in model code. All existing families default to "head" — zero migration required.
New: Conditional and Composite Appearance Features
ConditionalAppearanceFeature— switches the active appearance based on runtime conditions evaluated against entity state.CompositeAppearanceFeature— composes multiple appearance layers into a single resolved appearance.
Known Issues / Deferred
hzlib.api.entity.dynamic.*andhzlib.api.entity.monsters.*packages contain confirmed dead code with zero consumers. They remain in this build and are flagged for deletion in a future cleanup release.IInternalRenderLayerrename deferred.nativeEntityfield rename deferred.
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle. To learn more about the Modrinth Maven API, click here.
Note: When available, you should use the creator's maven repo instead as it will have transitive dependency information that the Modrinth Maven API does not. You may also end up with duplicate dependencies if you use a mix of Modrinth and non-Modrinth Maven repositories for your dependencies, because the group identifier will be different when served through the Modrinth Maven API.
Maven coordinates:
Version ID:
build.gradle:
repositories {
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
// forRepositories(fg.repository) // Uncomment when using ForgeGradle
filter {
includeGroup "maven.modrinth"
}
}
}
// Standard Gradle dependency
dependencies {
implementation "maven.modrinth:KxsiDURd:QPjGyJV8"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:KxsiDURd:QPjGyJV8"
}

