├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── common ├── src │ └── main │ │ ├── resources │ │ ├── geckolib.png │ │ └── geckolib.mixins.json │ │ └── java │ │ └── software │ │ └── bernie │ │ └── geckolib │ │ ├── cache │ │ ├── model │ │ │ ├── package-info.java │ │ │ ├── cuboid │ │ │ │ ├── package-info.java │ │ │ │ └── CuboidGeoBone.java │ │ │ └── GeoVertex.java │ │ ├── texture │ │ │ └── package-info.java │ │ ├── animation │ │ │ ├── package-info.java │ │ │ ├── keyframeevent │ │ │ │ ├── package-info.java │ │ │ │ ├── SoundKeyframeData.java │ │ │ │ ├── CustomInstructionKeyframeData.java │ │ │ │ ├── KeyFrameData.java │ │ │ │ └── ParticleKeyframeData.java │ │ │ └── BoneAnimation.java │ │ ├── package-info.java │ │ └── AnimatableIdCache.java │ │ ├── loading │ │ ├── json │ │ │ ├── package-info.java │ │ │ ├── raw │ │ │ │ ├── package-info.java │ │ │ │ ├── LocatorValue.java │ │ │ │ ├── Model.java │ │ │ │ ├── UVUnion.java │ │ │ │ ├── LocatorClass.java │ │ │ │ ├── MinecraftGeometry.java │ │ │ │ ├── TextureMesh.java │ │ │ │ ├── PolyMesh.java │ │ │ │ ├── Cube.java │ │ │ │ ├── UVFaces.java │ │ │ │ └── PolysUnion.java │ │ │ ├── typeadapter │ │ │ │ └── package-info.java │ │ │ └── ModelFormatVersion.java │ │ ├── math │ │ │ ├── package-info.java │ │ │ ├── value │ │ │ │ ├── package-info.java │ │ │ │ ├── Constant.java │ │ │ │ ├── VariableAssignment.java │ │ │ │ ├── Group.java │ │ │ │ ├── BooleanNegate.java │ │ │ │ ├── Negative.java │ │ │ │ ├── CompoundValue.java │ │ │ │ ├── Ternary.java │ │ │ │ ├── Calculation.java │ │ │ │ └── Variable.java │ │ │ └── function │ │ │ │ ├── package-info.java │ │ │ │ ├── limit │ │ │ │ ├── package-info.java │ │ │ │ ├── MinFunction.java │ │ │ │ ├── MaxFunction.java │ │ │ │ └── ClampFunction.java │ │ │ │ ├── misc │ │ │ │ ├── package-info.java │ │ │ │ ├── ToDegFunction.java │ │ │ │ ├── ToRadFunction.java │ │ │ │ └── PiFunction.java │ │ │ │ ├── random │ │ │ │ └── package-info.java │ │ │ │ ├── round │ │ │ │ ├── package-info.java │ │ │ │ ├── RoundFunction.java │ │ │ │ ├── CeilFunction.java │ │ │ │ ├── FloorFunction.java │ │ │ │ ├── TruncateFunction.java │ │ │ │ ├── HermiteBlendFunction.java │ │ │ │ ├── LerpFunction.java │ │ │ │ └── LerpRotFunction.java │ │ │ │ └── generic │ │ │ │ ├── package-info.java │ │ │ │ ├── SqrtFunction.java │ │ │ │ ├── LogFunction.java │ │ │ │ ├── AbsFunction.java │ │ │ │ ├── ExpFunction.java │ │ │ │ ├── SinFunction.java │ │ │ │ ├── ASinFunction.java │ │ │ │ ├── CosFunction.java │ │ │ │ ├── ATanFunction.java │ │ │ │ ├── ACosFunction.java │ │ │ │ ├── PowFunction.java │ │ │ │ ├── ModFunction.java │ │ │ │ └── ATan2Function.java │ │ ├── object │ │ │ ├── package-info.java │ │ │ ├── BoneStructure.java │ │ │ ├── BakedAnimations.java │ │ │ └── GeometryTree.java │ │ └── package-info.java │ │ ├── renderer │ │ ├── base │ │ │ └── package-info.java │ │ ├── layer │ │ │ ├── package-info.java │ │ │ └── GeoRenderLayersContainer.java │ │ ├── internal │ │ │ ├── package-info.java │ │ │ ├── PerBoneRender.java │ │ │ ├── BoneSnapshots.java │ │ │ └── AnimationVariables.java │ │ ├── specialty │ │ │ └── package-info.java │ │ ├── texture │ │ │ └── package-info.java │ │ └── package-info.java │ │ ├── animation │ │ ├── state │ │ │ ├── package-info.java │ │ │ ├── EasingState.java │ │ │ └── KeyFrameEvent.java │ │ ├── object │ │ │ ├── package-info.java │ │ │ └── PlayState.java │ │ ├── keyframehandler │ │ │ └── package-info.java │ │ └── package-info.java │ │ ├── animatable │ │ ├── client │ │ │ └── package-info.java │ │ ├── manager │ │ │ └── package-info.java │ │ ├── instance │ │ │ ├── package-info.java │ │ │ ├── InstancedAnimatableInstanceCache.java │ │ │ └── SingletonAnimatableInstanceCache.java │ │ ├── stateless │ │ │ ├── package-info.java │ │ │ ├── StatelessGeoObject.java │ │ │ ├── StatelessAnimationController.java │ │ │ ├── StatelessGeoEntity.java │ │ │ └── StatelessGeoBlockEntity.java │ │ └── package-info.java │ │ ├── constant │ │ ├── dataticket │ │ │ ├── package-info.java │ │ │ └── DataTicket.java │ │ └── package-info.java │ │ ├── network │ │ ├── packet │ │ │ ├── entity │ │ │ │ └── package-info.java │ │ │ ├── singleton │ │ │ │ ├── package-info.java │ │ │ │ ├── StatelessSingletonStopAnimPacket.java │ │ │ │ └── StatelessSingletonPlayAnimPacket.java │ │ │ ├── blockentity │ │ │ │ ├── package-info.java │ │ │ │ ├── BlockEntityAnimTriggerPacket.java │ │ │ │ ├── StatelessBlockEntityStopAnimPacket.java │ │ │ │ ├── StatelessBlockEntityPlayAnimPacket.java │ │ │ │ ├── StopTriggeredBlockEntityAnimPacket.java │ │ │ │ └── BlockEntityDataSyncPacket.java │ │ │ └── MultiloaderPacket.java │ │ └── package-info.java │ │ ├── event │ │ └── package-info.java │ │ ├── package-info.java │ │ ├── model │ │ └── package-info.java │ │ ├── object │ │ ├── package-info.java │ │ ├── CompoundException.java │ │ └── DeferredCache.java │ │ ├── service │ │ ├── package-info.java │ │ └── GeckoLibPlatform.java │ │ ├── util │ │ ├── package-info.java │ │ └── MiscUtil.java │ │ ├── GeckoLibServices.java │ │ └── mixin │ │ ├── client │ │ ├── SpecialModelRenderersMixin.java │ │ └── SpecialModelWrapperMixin.java │ │ └── common │ │ ├── LivingEntityMixin.java │ │ └── SynchronizedRemoteSlotMixin.java └── build.gradle.kts ├── fabric └── src │ └── main │ ├── resources │ ├── META-INF │ │ └── services │ │ │ ├── software.bernie.geckolib.service.GeckoLibEvents │ │ │ ├── software.bernie.geckolib.service.GeckoLibPlatform │ │ │ ├── software.bernie.geckolib.service.GeckoLibClient │ │ │ └── software.bernie.geckolib.service.GeckoLibNetworking │ └── fabric.mod.json │ └── java │ └── software │ └── bernie │ └── geckolib │ ├── event │ ├── item │ │ ├── package-info.java │ │ └── CompileItemRenderLayersEvent.java │ ├── armor │ │ └── package-info.java │ ├── block │ │ └── package-info.java │ ├── entity │ │ └── package-info.java │ ├── object │ │ ├── package-info.java │ │ └── CompileObjectRenderLayersEvent.java │ └── replacedentity │ │ └── package-info.java │ ├── platform │ ├── package-info.java │ └── GeckoLibFabric.java │ ├── GeckoLib.java │ └── GeckoLibClient.java ├── forge └── src │ └── main │ ├── resources │ ├── META-INF │ │ ├── services │ │ │ ├── software.bernie.geckolib.service.GeckoLibClient │ │ │ ├── software.bernie.geckolib.service.GeckoLibEvents │ │ │ ├── software.bernie.geckolib.service.GeckoLibPlatform │ │ │ └── software.bernie.geckolib.service.GeckoLibNetworking │ │ └── mods.toml │ └── pack.mcmeta │ └── java │ └── software │ └── bernie │ └── geckolib │ ├── event │ ├── item │ │ ├── package-info.java │ │ ├── CompileItemRenderLayersEvent.java │ │ └── CompileItemRenderStateEvent.java │ ├── armor │ │ ├── package-info.java │ │ ├── CompileArmorRenderLayersEvent.java │ │ └── CompileArmorRenderStateEvent.java │ ├── block │ │ ├── package-info.java │ │ ├── CompileBlockRenderLayersEvent.java │ │ └── CompileBlockRenderStateEvent.java │ ├── entity │ │ ├── package-info.java │ │ ├── CompileEntityRenderLayersEvent.java │ │ └── CompileEntityRenderStateEvent.java │ ├── object │ │ ├── package-info.java │ │ ├── CompileObjectRenderLayersEvent.java │ │ └── CompileObjectRenderStateEvent.java │ └── replacedentity │ │ ├── package-info.java │ │ └── CompileReplacedEntityRenderLayersEvent.java │ ├── platform │ └── package-info.java │ ├── GeckoLibClient.java │ └── GeckoLib.java ├── neoforge └── src │ └── main │ ├── resources │ └── META-INF │ │ ├── services │ │ ├── software.bernie.geckolib.service.GeckoLibEvents │ │ ├── software.bernie.geckolib.service.GeckoLibPlatform │ │ ├── software.bernie.geckolib.service.GeckoLibClient │ │ └── software.bernie.geckolib.service.GeckoLibNetworking │ │ └── neoforge.mods.toml │ └── java │ └── software │ └── bernie │ └── geckolib │ ├── event │ ├── armor │ │ ├── package-info.java │ │ └── CompileArmorRenderLayersEvent.java │ ├── block │ │ ├── package-info.java │ │ ├── CompileBlockRenderLayersEvent.java │ │ └── CompileBlockRenderStateEvent.java │ ├── entity │ │ ├── package-info.java │ │ ├── CompileEntityRenderLayersEvent.java │ │ └── CompileEntityRenderStateEvent.java │ ├── item │ │ ├── package-info.java │ │ ├── CompileItemRenderLayersEvent.java │ │ └── CompileItemRenderStateEvent.java │ ├── object │ │ ├── package-info.java │ │ ├── CompileObjectRenderLayersEvent.java │ │ └── CompileObjectRenderStateEvent.java │ └── replacedentity │ │ ├── package-info.java │ │ └── CompileReplacedEntityRenderLayersEvent.java │ ├── platform │ └── package-info.java │ ├── GeckoLibClient.java │ └── GeckoLib.java ├── .gitattributes ├── changelog.md ├── gradle.properties ├── .gitignore ├── .github └── FUNDING.yml ├── LICENSE └── settings.gradle.kts /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bernie-g/geckolib/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /common/src/main/resources/geckolib.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bernie-g/geckolib/HEAD/common/src/main/resources/geckolib.png -------------------------------------------------------------------------------- /fabric/src/main/resources/META-INF/services/software.bernie.geckolib.service.GeckoLibEvents: -------------------------------------------------------------------------------- 1 | software.bernie.geckolib.event.GeckoLibEventsFabric -------------------------------------------------------------------------------- /fabric/src/main/resources/META-INF/services/software.bernie.geckolib.service.GeckoLibPlatform: -------------------------------------------------------------------------------- 1 | software.bernie.geckolib.platform.GeckoLibFabric -------------------------------------------------------------------------------- /forge/src/main/resources/META-INF/services/software.bernie.geckolib.service.GeckoLibClient: -------------------------------------------------------------------------------- 1 | software.bernie.geckolib.platform.GeckoLibClientForge -------------------------------------------------------------------------------- /forge/src/main/resources/META-INF/services/software.bernie.geckolib.service.GeckoLibEvents: -------------------------------------------------------------------------------- 1 | software.bernie.geckolib.event.GeckoLibEventsForge -------------------------------------------------------------------------------- /forge/src/main/resources/META-INF/services/software.bernie.geckolib.service.GeckoLibPlatform: -------------------------------------------------------------------------------- 1 | software.bernie.geckolib.platform.GeckoLibForge -------------------------------------------------------------------------------- /fabric/src/main/resources/META-INF/services/software.bernie.geckolib.service.GeckoLibClient: -------------------------------------------------------------------------------- 1 | software.bernie.geckolib.platform.GeckoLibClientFabric -------------------------------------------------------------------------------- /neoforge/src/main/resources/META-INF/services/software.bernie.geckolib.service.GeckoLibEvents: -------------------------------------------------------------------------------- 1 | software.bernie.geckolib.event.GeckoLibEventsNeoForge -------------------------------------------------------------------------------- /neoforge/src/main/resources/META-INF/services/software.bernie.geckolib.service.GeckoLibPlatform: -------------------------------------------------------------------------------- 1 | software.bernie.geckolib.platform.GeckoLibNeoForge -------------------------------------------------------------------------------- /fabric/src/main/resources/META-INF/services/software.bernie.geckolib.service.GeckoLibNetworking: -------------------------------------------------------------------------------- 1 | software.bernie.geckolib.network.GeckoLibNetworkingFabric -------------------------------------------------------------------------------- /forge/src/main/resources/META-INF/services/software.bernie.geckolib.service.GeckoLibNetworking: -------------------------------------------------------------------------------- 1 | software.bernie.geckolib.network.GeckoLibNetworkingForge -------------------------------------------------------------------------------- /neoforge/src/main/resources/META-INF/services/software.bernie.geckolib.service.GeckoLibClient: -------------------------------------------------------------------------------- 1 | software.bernie.geckolib.platform.GeckoLibClientNeoForge -------------------------------------------------------------------------------- /forge/src/main/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "description": "GeckoLib resources", 4 | "pack_format": 26 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /neoforge/src/main/resources/META-INF/services/software.bernie.geckolib.service.GeckoLibNetworking: -------------------------------------------------------------------------------- 1 | software.bernie.geckolib.network.GeckoLibNetworkingNeoForge -------------------------------------------------------------------------------- /fabric/src/main/java/software/bernie/geckolib/event/item/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.event.item; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/cache/model/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.cache.model; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/cache/texture/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.cache.texture; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/json/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.loading.json; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.loading.math; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/renderer/base/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.renderer.base; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /fabric/src/main/java/software/bernie/geckolib/event/armor/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.event.armor; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /fabric/src/main/java/software/bernie/geckolib/event/block/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.event.block; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /fabric/src/main/java/software/bernie/geckolib/event/entity/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.event.entity; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /fabric/src/main/java/software/bernie/geckolib/event/object/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.event.object; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/event/item/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.animatable.client; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/event/armor/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.event.armor; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/event/block/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.event.block; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/event/entity/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.event.entity; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/event/item/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.event.item; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/event/object/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.event.object; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/animation/state/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.animation.state; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/cache/animation/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.cache.animation; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/object/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.loading.object; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/renderer/layer/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.renderer.layer; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/event/armor/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.animatable.client; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/event/block/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.animatable.client; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/event/entity/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.animatable.client; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/event/object/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.animatable.client; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/animatable/client/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.animatable.client; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/animatable/manager/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.animatable.manager; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/animation/object/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.animation.object; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/json/raw/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.loading.json.raw; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/value/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.loading.math.value; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/renderer/internal/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.renderer.internal; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/renderer/specialty/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.renderer.specialty; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/renderer/texture/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.renderer.texture; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/event/replacedentity/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.animatable.client; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/animatable/instance/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.animatable.instance; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/animatable/stateless/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.animatable.stateless; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/constant/dataticket/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.constant.dataticket; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /fabric/src/main/java/software/bernie/geckolib/event/replacedentity/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.event.replacedentity; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.loading.math.function; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/network/packet/entity/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.network.packet.entity; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/event/replacedentity/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.event.replacedentity; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/animation/keyframehandler/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.animation.keyframehandler; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/json/typeadapter/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.loading.json.typeadapter; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/network/packet/singleton/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.network.packet.singleton; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/limit/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.loading.math.function.limit; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/misc/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.loading.math.function.misc; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/random/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.loading.math.function.random; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/round/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.loading.math.function.round; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/network/packet/blockentity/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.network.packet.blockentity; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/cache/animation/keyframeevent/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.cache.animation.keyframeevent; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/generic/package-info.java: -------------------------------------------------------------------------------- 1 | @NullMarked 2 | package software.bernie.geckolib.loading.math.function.generic; 3 | 4 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /fabric/src/main/java/software/bernie/geckolib/platform/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Fabric-specific platform functionality 3 | */ 4 | @NullMarked 5 | package software.bernie.geckolib.platform; 6 | 7 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/platform/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Forge-specific platform functionality 3 | */ 4 | @NullMarked 5 | package software.bernie.geckolib.animatable.client; 6 | 7 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/platform/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * NeoForge-specific platform functionality 3 | */ 4 | @NullMarked 5 | package software.bernie.geckolib.platform; 6 | 7 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/event/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains classes relating to GeckoLib's event hooks and callbacks 3 | */ 4 | @NullMarked 5 | package software.bernie.geckolib.event; 6 | 7 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/network/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains classes relating to GeckoLib's networking functionality 3 | */ 4 | @NullMarked 5 | package software.bernie.geckolib.network; 6 | 7 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * GeckoLib's root package, containing only the root-level classes for project-wide functionality 3 | */ 4 | @NullMarked 5 | package software.bernie.geckolib; 6 | 7 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/cache/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains classes relating to various cached objects and their associated data records. 3 | */ 4 | @NullMarked 5 | package software.bernie.geckolib.cache; 6 | 7 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/model/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains the various {@link software.bernie.geckolib.model.GeoModel} implementations 3 | */ 4 | @NullMarked 5 | package software.bernie.geckolib.model; 6 | 7 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/animation/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains classes relating to animations, their handling, and other related objects 3 | */ 4 | @NullMarked 5 | package software.bernie.geckolib.animation; 6 | 7 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/cache/model/cuboid/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * GeckoLib model objects specifically for cuboid-based rendering 3 | */ 4 | @NullMarked 5 | package software.bernie.geckolib.cache.model.cuboid; 6 | 7 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/object/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains miscellaneous object classes that don't belong anywhere else; 3 | * usually utility classes or types 4 | */ 5 | @NullMarked 6 | package software.bernie.geckolib.object; 7 | 8 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/service/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains GeckoLib's service interfaces 3 | */ 4 | @NullMarked 5 | package software.bernie.geckolib.service; 6 | 7 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/constant/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains classes storing constant fields or providing constant factory methods not generic enough for a util class 3 | */ 4 | @NullMarked 5 | package software.bernie.geckolib.constant; 6 | 7 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/util/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains GeckoLib's various utility classes 3 | *

4 | * All classes in this package should be static final helper classes 5 | */ 6 | @NullMarked 7 | package software.bernie.geckolib.util; 8 | 9 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/animatable/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains classes for creating and managing {@link software.bernie.geckolib.animatable.GeoAnimatable} instances and objects 3 | */ 4 | @NullMarked 5 | package software.bernie.geckolib.animatable; 6 | 7 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | *.bat text eol=crlf 3 | *.patch text eol=lf 4 | *.java text eol=lf 5 | *.gradle text eol=crlf 6 | *.png binary 7 | *.gif binary 8 | *.exe binary 9 | *.dll binary 10 | *.jar binary 11 | *.lzma binary 12 | *.zip binary 13 | *.pyd binary 14 | *.cfg text eol=lf 15 | *.jks binary 16 | *.ogg binary -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | ## GeckoLib v5.4-alpha-2 2 | 3 | ## Changes: 4 | ### Internal: 5 | * Moved GeckoLib's nullability annotations to the [JSpecify](https://jspecify.dev) spec 6 | * Cleaned up more Javadocs 7 | * Renamed RawAnimation#additionalTicks to RawAnimation#waitTicks 8 | * Removed `bind_pose_rotation` legacy support from the Bone format -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains classes relating to the loading stage of GeckoLib.
3 | * Objects here may be used outside of loading, but are rarely interacted with by end-users. 4 | */ 5 | @NullMarked 6 | package software.bernie.geckolib.loading; 7 | 8 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/renderer/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains classes related to the actual rendering functionality of GeckoLib. 3 | *

4 | * Rendering-tangential functionality such as animating is not kept here 5 | */ 6 | @NullMarked 7 | package software.bernie.geckolib.renderer; 8 | 9 | import org.jspecify.annotations.NullMarked; -------------------------------------------------------------------------------- /fabric/src/main/java/software/bernie/geckolib/GeckoLib.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib; 2 | 3 | import net.fabricmc.api.ModInitializer; 4 | import software.bernie.geckolib.service.GeckoLibNetworking; 5 | 6 | /** 7 | * Main GeckoLib entrypoint 8 | */ 9 | public final class GeckoLib implements ModInitializer { 10 | @Override 11 | public void onInitialize() { 12 | GeckoLibConstants.init(); 13 | GeckoLibNetworking.init(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Environment Settings 2 | org.gradle.jvmargs=-Xmx3G 3 | org.gradle.daemon=false 4 | 5 | # Project Settings 6 | modId=geckolib 7 | modDisplayName=GeckoLib 5 8 | group=software.bernie.geckolib 9 | modLicense=MIT 10 | modAuthors=Tslat, Gecko 11 | modContributors=Eliot, AzureDoom, DerToaster, Witixin 12 | modDescription=GeckoLib is an animation engine for Minecraft Mods, with support for complex 3D keyframe-based animations, 30+ easings, concurrent animation support, sound and particle keyframes, event keyframes, and more. 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # eclipse 2 | bin 3 | *.launch 4 | .settings 5 | .metadata 6 | .classpath 7 | .project 8 | mcmodsrepo 9 | 10 | # idea 11 | out 12 | *.ipr 13 | *.iws 14 | *.iml 15 | .idea 16 | caches 17 | daemon 18 | wrapper 19 | native 20 | 21 | # gradle 22 | build 23 | .gradle 24 | logs 25 | # other 26 | eclipse 27 | run 28 | runs/ 29 | key.properties 30 | 31 | # Files from Forge MDK 32 | forge*changelog.txt 33 | build.bat 34 | *.bat 35 | 36 | # allow gradlew 37 | !core/gradle/wrapper 38 | !core/gradlew.bat 39 | !gradle/wrapper 40 | !gradlew.bat 41 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/object/BoneStructure.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.object; 2 | 3 | import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; 4 | import software.bernie.geckolib.loading.json.raw.Bone; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * Container class for holding a {@link Bone} structure. Used at startup in deserialization 10 | */ 11 | public record BoneStructure(Bone self, Map children) { 12 | public BoneStructure(Bone self) { 13 | this(self, new Object2ObjectOpenHashMap<>()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/animatable/stateless/StatelessGeoObject.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.animatable.stateless; 2 | 3 | import software.bernie.geckolib.animatable.GeoAnimatable; 4 | import software.bernie.geckolib.animation.RawAnimation; 5 | 6 | /** 7 | * Extension of {@link StatelessAnimatable} for custom {@link GeoAnimatable}s 8 | *

9 | * Implementation of {@link StatelessAnimatable#playAnimation(RawAnimation)} and {@link StatelessAnimatable#stopAnimation(String)} is left up 10 | * to the implementers of this interface, as well as any additional handling required 11 | */ 12 | public non-sealed interface StatelessGeoObject extends StatelessAnimatable, GeoAnimatable {} 13 | -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/GeckoLibClient.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib; 2 | 3 | import net.minecraftforge.api.distmarker.Dist; 4 | import net.minecraftforge.client.event.RegisterClientReloadListenersEvent; 5 | import net.minecraftforge.eventbus.api.listener.SubscribeEvent; 6 | import net.minecraftforge.fml.common.Mod; 7 | import software.bernie.geckolib.cache.GeckoLibResources; 8 | 9 | @Mod.EventBusSubscriber(value = Dist.CLIENT, modid = GeckoLibConstants.MODID) 10 | public class GeckoLibClient { 11 | @SubscribeEvent 12 | public static void registerReloadListeners(final RegisterClientReloadListenersEvent ev) { 13 | ev.registerReloadListener(GeckoLibResources::reload); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/GeckoLibClient.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib; 2 | 3 | import net.neoforged.api.distmarker.Dist; 4 | import net.neoforged.bus.api.SubscribeEvent; 5 | import net.neoforged.fml.common.EventBusSubscriber; 6 | import net.neoforged.neoforge.client.event.AddClientReloadListenersEvent; 7 | import software.bernie.geckolib.cache.GeckoLibResources; 8 | 9 | /** 10 | * Main GeckoLib client entrypoint 11 | */ 12 | @EventBusSubscriber(value = Dist.CLIENT, modid = GeckoLibConstants.MODID) 13 | public final class GeckoLibClient { 14 | @SubscribeEvent 15 | public static void registerReloadListeners(final AddClientReloadListenersEvent ev) { 16 | ev.addListener(GeckoLibResources.RELOAD_LISTENER_ID, GeckoLibResources::reload); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/object/BakedAnimations.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.object; 2 | 3 | import org.jspecify.annotations.Nullable; 4 | import software.bernie.geckolib.cache.animation.Animation; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * Container object that holds a deserialized map of {@link Animation Animations} 10 | *

11 | * Kept as a unique object so that it can be registered as a {@link com.google.gson.JsonDeserializer deserializer} for {@link com.google.gson.Gson Gson} 12 | */ 13 | public record BakedAnimations(Map animations) { 14 | /** 15 | * Gets an {@link Animation} by its name, if present 16 | */ 17 | public @Nullable Animation getAnimation(String name) { 18 | return this.animations.get(name); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/value/Constant.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.value; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | 6 | /** 7 | * {@link MathValue} value supplier 8 | * 9 | *

10 | * Contract: 11 | *
12 | * An immutable double value 13 | */ 14 | public record Constant(double value) implements MathValue { 15 | @Override 16 | public double get(ControllerState controllerState) { 17 | return this.value; 18 | } 19 | 20 | @Override 21 | public boolean isMutable() { 22 | return false; 23 | } 24 | 25 | @Override 26 | public String toString() { 27 | return String.valueOf(this.value); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: geckolib 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /common/src/main/resources/geckolib.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "package": "software.bernie.geckolib.mixin", 4 | "compatibilityLevel": "JAVA_17", 5 | "refmap": "geckolib.refmap.json", 6 | "minVersion": "0.8", 7 | "injectors": { 8 | "defaultRequire": 1 9 | }, 10 | "mixins": [ 11 | "common.AbstractContainerMenuMixin", 12 | "common.HashedStackMixin", 13 | "common.ItemStackMixin", 14 | "common.LivingEntityMixin", 15 | "common.SynchronizedRemoteSlotMixin" 16 | ], 17 | "client": [ 18 | "client.BlockEntityRenderStateMixin", 19 | "client.EntityRendererMixin", 20 | "client.EntityRenderStateMixin", 21 | "client.HumanoidArmorLayerMixin", 22 | "client.SpecialModelRenderersMixin", 23 | "client.SpecialModelWrapperMixin", 24 | "client.TextureManagerMixin" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/GeckoLib.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib; 2 | 3 | import net.minecraft.core.registries.Registries; 4 | import net.neoforged.bus.api.IEventBus; 5 | import net.neoforged.fml.common.Mod; 6 | import net.neoforged.neoforge.registries.DeferredRegister; 7 | import software.bernie.geckolib.network.GeckoLibNetworkingNeoForge; 8 | 9 | @Mod(GeckoLibConstants.MODID) 10 | public final class GeckoLib { 11 | public static final DeferredRegister.DataComponents DATA_COMPONENTS_REGISTER = DeferredRegister.createDataComponents(Registries.DATA_COMPONENT_TYPE, GeckoLibConstants.MODID); 12 | 13 | public GeckoLib(IEventBus modBus) { 14 | GeckoLibNetworkingNeoForge.init(modBus); 15 | DATA_COMPONENTS_REGISTER.register(modBus); 16 | GeckoLibConstants.init(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/cache/animation/keyframeevent/SoundKeyframeData.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.cache.animation.keyframeevent; 2 | 3 | import software.bernie.geckolib.cache.animation.Keyframe; 4 | 5 | import java.util.Objects; 6 | 7 | /** 8 | * Sound {@link Keyframe} instruction holder 9 | */ 10 | public class SoundKeyframeData extends KeyFrameData { 11 | private final String sound; 12 | 13 | public SoundKeyframeData(double time, String sound) { 14 | super(time); 15 | 16 | this.sound = sound; 17 | } 18 | 19 | /** 20 | * Gets the sound data given by the {@link Keyframe} instruction from the {@code animation.json} 21 | */ 22 | public String getSound() { 23 | return this.sound; 24 | } 25 | 26 | @Override 27 | public int hashCode() { 28 | return Objects.hash(getTime(), this.sound); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/animation/object/PlayState.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.animation.object; 2 | 3 | import software.bernie.geckolib.animation.AnimationController; 4 | 5 | /** 6 | * State enum to define whether an {@link AnimationController} should continue or stop 7 | * 8 | * 9 | * 10 | * 11 | * 12 | * 13 | * 14 | *
States
StateDescription
{@link #CONTINUE}Play the currently playing animation
{@link #PAUSE}Pause the currently playing animation, freezing its position in the timeline
{@link #STOP}Stop the currently playing animation, resetting the animation time to 0
15 | */ 16 | public enum PlayState { 17 | CONTINUE, 18 | PAUSE, 19 | STOP 20 | } 21 | -------------------------------------------------------------------------------- /forge/src/main/resources/META-INF/mods.toml: -------------------------------------------------------------------------------- 1 | modLoader="javafml" 2 | loaderVersion="${forge_loader_range}" 3 | issueTrackerURL="https://github.com/bernie-g/geckolib/issues" 4 | license="${mod_license}" 5 | 6 | [[mods]] 7 | modId="${mod_id}" 8 | version="${version}" 9 | displayName="${mod_display_name}" 10 | displayURL="http://geckolib.com/" 11 | logoFile="geckolib.png" 12 | authors="${mod_authors}" 13 | credits="${mod_contributors}" 14 | description=''' 15 | ${mod_description} 16 | ''' 17 | 18 | [[dependencies.geckolib]] 19 | modId="forge" 20 | mandatory=true 21 | versionRange="${forge_version_range}" 22 | ordering="NONE" 23 | side="BOTH" 24 | [[dependencies.geckolib]] 25 | modId="minecraft" 26 | mandatory=true 27 | versionRange="${minecraft_version_range}" 28 | ordering="NONE" 29 | side="BOTH" -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/cache/model/GeoVertex.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.cache.model; 2 | 3 | /** 4 | * Vertex data holder 5 | * 6 | * @param posX The x-coordinate position of the vertex 7 | * @param posY The y-coordinate position of the vertex 8 | * @param posZ The z-coordinate position of the vertex 9 | * @param texU The texture U coordinate 10 | * @param texV The texture V coordinate 11 | */ 12 | public record GeoVertex(float posX, float posY, float posZ, float texU, float texV) { 13 | public GeoVertex(double x, double y, double z) { 14 | this((float)x, (float)y, (float)z, 0, 0); 15 | } 16 | 17 | /** 18 | * Create a copy of this vertex with new UV coordinates 19 | */ 20 | public GeoVertex withUVs(float texU, float texV) { 21 | return new GeoVertex(this.posX, this.posY, this.posZ, texU, texV); 22 | } 23 | } -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/GeckoLib.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib; 2 | 3 | import net.minecraft.core.component.DataComponentType; 4 | import net.minecraft.core.registries.BuiltInRegistries; 5 | import net.minecraftforge.fml.common.Mod; 6 | import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; 7 | import net.minecraftforge.registries.DeferredRegister; 8 | import software.bernie.geckolib.network.GeckoLibNetworkingForge; 9 | 10 | @Mod(GeckoLibConstants.MODID) 11 | public final class GeckoLib { 12 | public static final DeferredRegister> DATA_COMPONENTS_REGISTER = DeferredRegister.create(BuiltInRegistries.DATA_COMPONENT_TYPE.key(), GeckoLibConstants.MODID); 13 | 14 | public GeckoLib(FMLJavaModLoadingContext context) { 15 | DATA_COMPONENTS_REGISTER.register(context.getModBusGroup()); 16 | GeckoLibNetworkingForge.init(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/network/packet/MultiloaderPacket.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.network.packet; 2 | 3 | import net.minecraft.network.protocol.common.custom.CustomPacketPayload; 4 | import net.minecraft.world.entity.player.Player; 5 | import org.jspecify.annotations.Nullable; 6 | 7 | import java.util.function.Consumer; 8 | 9 | /** 10 | * Multiloader implementation of a packet base, for loader-agnostic packet handling 11 | */ 12 | public interface MultiloaderPacket extends CustomPacketPayload { 13 | /** 14 | * Handle the message after being received and decoded 15 | *

16 | * This method is side-agnostic, so make sure you call out to client proxies as needed 17 | *

18 | * The player may be null if the packet is being sent before the player loads in 19 | */ 20 | void receiveMessage(@Nullable Player sender, Consumer workQueue); 21 | } 22 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/cache/animation/keyframeevent/CustomInstructionKeyframeData.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.cache.animation.keyframeevent; 2 | 3 | import software.bernie.geckolib.cache.animation.Keyframe; 4 | 5 | import java.util.Objects; 6 | 7 | /** 8 | * Custom instruction {@link Keyframe} instruction holder 9 | */ 10 | public class CustomInstructionKeyframeData extends KeyFrameData { 11 | private final String instructions; 12 | 13 | public CustomInstructionKeyframeData(double time, String instructions) { 14 | super(time); 15 | 16 | this.instructions = instructions; 17 | } 18 | 19 | /** 20 | * Gets the instructions string given by the {@link Keyframe} instruction from the {@code animation.json} 21 | */ 22 | public String getInstructions() { 23 | return this.instructions; 24 | } 25 | 26 | @Override 27 | public int hashCode() { 28 | return Objects.hash(getTime(), this.instructions); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /neoforge/src/main/resources/META-INF/neoforge.mods.toml: -------------------------------------------------------------------------------- 1 | modLoader="javafml" 2 | loaderVersion="${neoforge_loader_range}" 3 | issueTrackerURL="https://github.com/bernie-g/geckolib/issues" 4 | license="${mod_license}" 5 | 6 | [[mods]] 7 | modId="${mod_id}" 8 | version="${version}" 9 | displayName="${mod_display_name}" 10 | displayURL="http://geckolib.com/" 11 | logoFile="geckolib.png" 12 | authors="${mod_authors}" 13 | credits="${mod_contributors}" 14 | description=''' 15 | ${mod_description} 16 | ''' 17 | 18 | [[mixins]] 19 | config = "${mod_id}.mixins.json" 20 | 21 | [[accessTransformers]] 22 | file = "META-INF/accesstransformer.cfg" 23 | 24 | [[dependencies.geckolib]] 25 | modId="neoforge" 26 | type="required" 27 | versionRange="${neoforge_version_range}" 28 | ordering="NONE" 29 | side="BOTH" 30 | [[dependencies.geckolib]] 31 | modId="minecraft" 32 | type="required" 33 | versionRange="${minecraft_version_range}" 34 | ordering="NONE" 35 | side="BOTH" -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/value/VariableAssignment.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.value; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | 6 | import java.util.Set; 7 | 8 | /** 9 | * {@link MathValue} value supplier 10 | * 11 | *

12 | * Contract: 13 | *
14 | * Assigns a variable to the given value, then returns 0 15 | */ 16 | public record VariableAssignment(Variable variable, MathValue value) implements MathValue { 17 | @Override 18 | public double get(ControllerState controllerState) { 19 | this.variable.set(this.value.get(controllerState)); 20 | 21 | return 0; 22 | } 23 | 24 | @Override 25 | public Set getUsedVariables() { 26 | return this.value.getUsedVariables(); 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return this.variable.name() + "=" + this.value.toString(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/value/Group.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.value; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | 6 | import java.util.Set; 7 | 8 | /** 9 | * {@link MathValue} value supplier 10 | * 11 | *

12 | * Contract: 13 | *
14 | * An unaltered return of the stored MathValue 15 | */ 16 | public record Group(MathValue contents) implements MathValue { 17 | @Override 18 | public double get(ControllerState controllerState) { 19 | return this.contents.get(controllerState); 20 | } 21 | 22 | @Override 23 | public boolean isMutable() { 24 | return this.contents.isMutable(); 25 | } 26 | 27 | @Override 28 | public Set getUsedVariables() { 29 | return this.contents.getUsedVariables(); 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return "(" + this.contents.toString() + ")"; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/json/raw/LocatorValue.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.json.raw; 2 | 3 | import com.google.gson.JsonDeserializer; 4 | import com.google.gson.JsonParseException; 5 | import org.jspecify.annotations.Nullable; 6 | import software.bernie.geckolib.util.JsonUtil; 7 | 8 | /** 9 | * Container class for locator value information, only used in deserialization at startup 10 | */ 11 | public record LocatorValue(@Nullable LocatorClass locatorClass, double[] values) { 12 | public static JsonDeserializer deserializer() throws JsonParseException { 13 | return (json, type, context) -> { 14 | if (json.isJsonArray()) { 15 | return new LocatorValue(null, JsonUtil.jsonArrayToDoubleArray(json.getAsJsonArray())); 16 | } 17 | else if (json.isJsonObject()) { 18 | return new LocatorValue(context.deserialize(json.getAsJsonObject(), LocatorClass.class), new double[0]); 19 | } 20 | else { 21 | throw new JsonParseException("Invalid format for LocatorValue in json"); 22 | } 23 | }; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/json/raw/Model.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.json.raw; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonDeserializer; 5 | import com.google.gson.JsonObject; 6 | import com.google.gson.JsonParseException; 7 | import net.minecraft.util.GsonHelper; 8 | import software.bernie.geckolib.util.JsonUtil; 9 | 10 | /** 11 | * Container class for model information, only used in deserialization at startup 12 | */ 13 | public record Model(String formatVersion, MinecraftGeometry[] minecraftGeometry) { 14 | public static JsonDeserializer deserializer() throws JsonParseException { 15 | return (json, type, context) -> { 16 | JsonObject obj = json.getAsJsonObject(); 17 | String formatVersion = obj.get("format_version").getAsString(); 18 | MinecraftGeometry[] minecraftGeometry = JsonUtil.jsonArrayToObjectArray(GsonHelper.getAsJsonArray(obj, "minecraft:geometry", new JsonArray(0)), context, MinecraftGeometry.class); 19 | 20 | return new Model(formatVersion, minecraftGeometry); 21 | }; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/json/raw/UVUnion.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.json.raw; 2 | 3 | import com.google.gson.JsonDeserializer; 4 | import com.google.gson.JsonParseException; 5 | import org.jspecify.annotations.Nullable; 6 | import software.bernie.geckolib.util.JsonUtil; 7 | 8 | /** 9 | * Container class for UV information, only used in deserialization at startup 10 | */ 11 | public record UVUnion(double[] boxUVCoords, @Nullable UVFaces faceUV, boolean isBoxUV) { 12 | public static JsonDeserializer deserializer() throws JsonParseException { 13 | return (json, type, context) -> { 14 | if (json.isJsonObject()) { 15 | return new UVUnion(new double[0], context.deserialize(json.getAsJsonObject(), UVFaces.class), false); 16 | } 17 | else if (json.isJsonArray()) { 18 | return new UVUnion(JsonUtil.jsonArrayToDoubleArray(json.getAsJsonArray()), null, true); 19 | } 20 | else { 21 | throw new JsonParseException("Invalid format provided for UVUnion, must be either double array or UVFaces collection"); 22 | } 23 | }; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/value/BooleanNegate.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.value; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | 6 | import java.util.Set; 7 | 8 | /** 9 | * {@link MathValue} value supplier 10 | * 11 | *

12 | * Contract: 13 | *
14 | * Returns 1 if the contained value is equal to 0, otherwise returns 0 15 | */ 16 | public record BooleanNegate(MathValue value) implements MathValue { 17 | @Override 18 | public double get(ControllerState controllerState) { 19 | return this.value.get(controllerState) == 0 ? 1 : 0; 20 | } 21 | 22 | @Override 23 | public boolean isMutable() { 24 | return this.value.isMutable(); 25 | } 26 | 27 | @Override 28 | public Set getUsedVariables() { 29 | return this.value.getUsedVariables(); 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return "!" + this.value.toString(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/cache/animation/keyframeevent/KeyFrameData.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.cache.animation.keyframeevent; 2 | 3 | import software.bernie.geckolib.cache.animation.Keyframe; 4 | 5 | import java.util.Objects; 6 | 7 | /** 8 | * Base class for custom {@link Keyframe} events 9 | * 10 | * @see ParticleKeyframeData 11 | * @see SoundKeyframeData 12 | */ 13 | public abstract class KeyFrameData { 14 | private final double animationTime; 15 | 16 | public KeyFrameData(double time) { 17 | this.animationTime = time; 18 | } 19 | 20 | /** 21 | * Gets the time position (in seconds) of the keyframe instruction in its animation 22 | */ 23 | public double getTime() { 24 | return this.animationTime; 25 | } 26 | 27 | @Override 28 | public boolean equals(Object obj) { 29 | if (this == obj) 30 | return true; 31 | 32 | if (obj == null || getClass() != obj.getClass()) 33 | return false; 34 | 35 | return this.hashCode() == obj.hashCode(); 36 | } 37 | 38 | @Override 39 | public int hashCode() { 40 | return Objects.hashCode(this.animationTime); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 GeckoLib 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /common/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("geckolib-convention") 3 | 4 | alias(libs.plugins.moddevgradle) 5 | } 6 | 7 | version = libs.versions.geckolib.get() 8 | 9 | base { 10 | archivesName = "geckolib-common-${libs.versions.minecraft.asProvider().get()}" 11 | } 12 | 13 | neoForge { 14 | neoFormVersion = libs.versions.neoform.get() 15 | accessTransformers.files.setFrom("src/main/resources/META-INF/accesstransformer.cfg") 16 | 17 | parchment.minecraftVersion.set(libs.versions.parchment.minecraft.get()) 18 | parchment.mappingsVersion.set(libs.versions.parchment.asProvider().get()) 19 | } 20 | 21 | dependencies { 22 | compileOnly(libs.mixin) 23 | compileOnly(libs.mixinextras.common) 24 | //compileOnly(libs.iris) 25 | 26 | // Only enable for testing as needed 27 | // Disable before publishing 28 | //implementation(libs.examplemod.common) 29 | } 30 | 31 | publishing { 32 | publishing { 33 | publications { 34 | create("geckolib") { 35 | from(components["java"]) 36 | artifactId = base.archivesName.get() 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /fabric/src/main/resources/fabric.mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": 1, 3 | "id": "geckolib", 4 | "version": "${version}", 5 | "name": "${mod_display_name}", 6 | "description": "${mod_description}", 7 | "authors": [ 8 | "${mod_authors}" 9 | ], 10 | "contributors": [ 11 | "${mod_contributors}" 12 | ], 13 | "contact": { 14 | "homepage": "https://www.curseforge.com/minecraft/mc-mods/geckolib", 15 | "issues": "https://github.com/bernie-g/geckolib/issues", 16 | "sources": "https://github.com/bernie-g/geckolib" 17 | }, 18 | "license": "${mod_license}", 19 | "icon": "${mod_id}.png", 20 | "environment": "*", 21 | "entrypoints": { 22 | "main": [ 23 | "software.bernie.geckolib.GeckoLib" 24 | ], 25 | "client": [ 26 | "software.bernie.geckolib.GeckoLibClient" 27 | ] 28 | }, 29 | "mixins": [ 30 | "geckolib.mixins.json" 31 | ], 32 | "accessWidener": "geckolib.accesswidener", 33 | "depends": { 34 | "fabricloader": ">=${fabric_loader_version_range}", 35 | "fabric-api": ">=${fabric_api_version_range}", 36 | "java": ">=17", 37 | "minecraft": ">=${minecraft_version}" 38 | }, 39 | "custom": { 40 | "modmenu": { 41 | "badges": [ "library" ] 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/animation/state/EasingState.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.animation.state; 2 | 3 | import software.bernie.geckolib.animation.object.EasingType; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | 6 | import java.util.Arrays; 7 | 8 | /** 9 | * Container object representing the variables used for performing easing operations 10 | * 11 | * @param easingType The EasingType to use to interpolate 12 | * @param easingArgs The easing arguments to use for interpolation 13 | * @param delta The current delta (position) between the start value and the end value 14 | * @param fromValue The start value to ease from 15 | * @param toValue The end value to ease to 16 | */ 17 | public record EasingState(EasingType easingType, MathValue[] easingArgs, double delta, double fromValue, double toValue) { 18 | @Override 19 | public String toString() { 20 | return "EasingType: " + this.easingType.toString() + 21 | " | EasingArgs: " + Arrays.toString(this.easingArgs) + 22 | " | Delta: " + this.delta + 23 | " | From: " + this.fromValue + 24 | " | To: " + this.toValue; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/json/raw/LocatorClass.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.json.raw; 2 | 3 | import com.google.gson.JsonDeserializer; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.JsonParseException; 6 | import net.minecraft.util.GsonHelper; 7 | import org.jspecify.annotations.Nullable; 8 | import software.bernie.geckolib.util.JsonUtil; 9 | 10 | /** 11 | * Container class for locator class information, only used in deserialization at startup 12 | */ 13 | public record LocatorClass(@Nullable Boolean ignoreInheritedScale, double[] offset, double[] rotation) { 14 | public static JsonDeserializer deserializer() throws JsonParseException { 15 | return (json, type, context) -> { 16 | JsonObject obj = json.getAsJsonObject(); 17 | Boolean ignoreInheritedScale = JsonUtil.getOptionalBoolean(obj, "ignore_inherited_scale"); 18 | double[] offset = JsonUtil.jsonArrayToDoubleArray(GsonHelper.getAsJsonArray(obj, "offset", null)); 19 | double[] rotation = JsonUtil.jsonArrayToDoubleArray(GsonHelper.getAsJsonArray(obj, "rotation", null)); 20 | 21 | return new LocatorClass(ignoreInheritedScale, offset, rotation); 22 | }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/event/item/CompileItemRenderLayersEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.item; 2 | 3 | import net.minecraft.world.item.Item; 4 | import net.neoforged.bus.api.Event; 5 | import software.bernie.geckolib.animatable.GeoAnimatable; 6 | import software.bernie.geckolib.event.GeoRenderEvent; 7 | import software.bernie.geckolib.renderer.GeoItemRenderer; 8 | 9 | /** 10 | * One-time event for a {@link GeoItemRenderer} called on first initialisation 11 | *

12 | * Use this event to add render layers to the renderer as needed 13 | *

14 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 15 | * 16 | * @see GeoRenderEvent 17 | * @see CompileRenderLayers 18 | */ 19 | public class CompileItemRenderLayersEvent extends Event implements GeoRenderEvent.Item.CompileRenderLayers { 20 | private final GeoItemRenderer renderer; 21 | 22 | public CompileItemRenderLayersEvent(GeoItemRenderer renderer) { 23 | this.renderer = renderer; 24 | } 25 | 26 | @Override 27 | public GeoItemRenderer getRenderer() { 28 | return this.renderer; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/generic/SqrtFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.generic; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | import software.bernie.geckolib.loading.math.function.MathFunction; 6 | 7 | /** 8 | * {@link MathFunction} value supplier 9 | * 10 | *

11 | * Contract: 12 | *
13 | * Returns the square root of the input value 14 | */ 15 | public final class SqrtFunction extends MathFunction { 16 | private final MathValue value; 17 | 18 | public SqrtFunction(MathValue... values) { 19 | super(values); 20 | 21 | this.value = values[0]; 22 | } 23 | 24 | @Override 25 | public String getName() { 26 | return "math.sqrt"; 27 | } 28 | 29 | @Override 30 | public double compute(ControllerState controllerState) { 31 | return Math.sqrt(this.value.get(controllerState)); 32 | } 33 | 34 | @Override 35 | public int getMinArgs() { 36 | return 1; 37 | } 38 | 39 | @Override 40 | public MathValue[] getArgs() { 41 | return new MathValue[] {this.value}; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/misc/ToDegFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.misc; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | import software.bernie.geckolib.loading.math.function.MathFunction; 6 | 7 | /** 8 | * {@link MathFunction} value supplier 9 | * 10 | *

11 | * Contract: 12 | *
13 | * Converts the input value to degrees 14 | */ 15 | public final class ToDegFunction extends MathFunction { 16 | private final MathValue value; 17 | 18 | public ToDegFunction(MathValue... values) { 19 | super(values); 20 | 21 | this.value = values[0]; 22 | } 23 | 24 | @Override 25 | public String getName() { 26 | return "math.to_deg"; 27 | } 28 | 29 | @Override 30 | public double compute(ControllerState controllerState) { 31 | return Math.toDegrees(this.value.get(controllerState)); 32 | } 33 | 34 | @Override 35 | public int getMinArgs() { 36 | return 1; 37 | } 38 | 39 | @Override 40 | public MathValue[] getArgs() { 41 | return new MathValue[] {this.value}; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/misc/ToRadFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.misc; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | import software.bernie.geckolib.loading.math.function.MathFunction; 6 | 7 | /** 8 | * {@link MathFunction} value supplier 9 | * 10 | *

11 | * Contract: 12 | *
13 | * Converts the input value to radians 14 | */ 15 | public final class ToRadFunction extends MathFunction { 16 | private final MathValue value; 17 | 18 | public ToRadFunction(MathValue... values) { 19 | super(values); 20 | 21 | this.value = values[0]; 22 | } 23 | 24 | @Override 25 | public String getName() { 26 | return "math.to_rad"; 27 | } 28 | 29 | @Override 30 | public double compute(ControllerState controllerState) { 31 | return Math.toRadians(this.value.get(controllerState)); 32 | } 33 | 34 | @Override 35 | public int getMinArgs() { 36 | return 1; 37 | } 38 | 39 | @Override 40 | public MathValue[] getArgs() { 41 | return new MathValue[] {this.value}; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/value/Negative.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.value; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | 6 | import java.util.Set; 7 | 8 | /** 9 | * {@link MathValue} value supplier 10 | * 11 | *

12 | * Contract: 13 | *
14 | * Negated equivalent of the stored value; returning a positive number if the stored value is negative, or a negative value if the stored value is positive 15 | */ 16 | public record Negative(MathValue value) implements MathValue { 17 | @Override 18 | public double get(ControllerState controllerState) { 19 | return -this.value.get(controllerState); 20 | } 21 | 22 | @Override 23 | public boolean isMutable() { 24 | return this.value.isMutable(); 25 | } 26 | 27 | @Override 28 | public Set getUsedVariables() { 29 | return this.value.getUsedVariables(); 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | if (this.value instanceof Constant) 35 | return "-" + this.value; 36 | 37 | return "-" + "(" + this.value + ")"; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /fabric/src/main/java/software/bernie/geckolib/GeckoLibClient.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib; 2 | 3 | import net.fabricmc.api.ClientModInitializer; 4 | import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; 5 | import net.fabricmc.fabric.api.resource.v1.ResourceLoader; 6 | import net.minecraft.network.protocol.common.custom.CustomPacketPayload; 7 | import net.minecraft.server.packs.PackType; 8 | import org.jetbrains.annotations.ApiStatus; 9 | import software.bernie.geckolib.cache.GeckoLibResources; 10 | import software.bernie.geckolib.network.packet.MultiloaderPacket; 11 | 12 | /** 13 | * Main GeckoLib client entrypoint 14 | */ 15 | public class GeckoLibClient implements ClientModInitializer { 16 | @Override 17 | public void onInitializeClient() { 18 | ResourceLoader.get(PackType.CLIENT_RESOURCES).registerReloader(GeckoLibResources.RELOAD_LISTENER_ID, GeckoLibResources::reload); 19 | } 20 | 21 | @ApiStatus.Internal 22 | public static

void registerPacket(CustomPacketPayload.Type

packetType) { 23 | ClientPlayNetworking.registerGlobalReceiver(packetType, (packet, context) -> packet.receiveMessage(context.player(), context.client()::execute)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/GeckoLibServices.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib; 2 | 3 | import software.bernie.geckolib.service.GeckoLibEvents; 4 | import software.bernie.geckolib.service.GeckoLibNetworking; 5 | import software.bernie.geckolib.service.GeckoLibPlatform; 6 | import software.bernie.geckolib.service.GeckoLibClient; 7 | 8 | import java.util.ServiceLoader; 9 | 10 | public final class GeckoLibServices { 11 | public static final GeckoLibPlatform PLATFORM = load(GeckoLibPlatform.class); 12 | public static final GeckoLibNetworking NETWORK = load(GeckoLibNetworking.class); 13 | 14 | public static class Client { 15 | public static final GeckoLibEvents EVENTS = load(GeckoLibEvents.class); 16 | public static final GeckoLibClient ITEM_RENDERING = load(GeckoLibClient.class); 17 | } 18 | 19 | private static T load(Class clazz) { 20 | final T loadedService = ServiceLoader.load(clazz) 21 | .findFirst() 22 | .orElseThrow(() -> new NullPointerException("Failed to load service for " + clazz.getName())); 23 | GeckoLibConstants.LOGGER.debug("Loaded {} for service {}", loadedService, clazz); 24 | 25 | return loadedService; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/round/RoundFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.round; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | import software.bernie.geckolib.loading.math.function.MathFunction; 6 | 7 | /** 8 | * {@link MathFunction} value supplier 9 | * 10 | *

11 | * Contract: 12 | *
13 | * Returns the closest integer value to the input value 14 | */ 15 | public final class RoundFunction extends MathFunction { 16 | private final MathValue value; 17 | 18 | public RoundFunction(MathValue... values) { 19 | super(values); 20 | 21 | this.value = values[0]; 22 | } 23 | 24 | @Override 25 | public String getName() { 26 | return "math.round"; 27 | } 28 | 29 | @Override 30 | public double compute(ControllerState controllerState) { 31 | return Math.round(this.value.get(controllerState)); 32 | } 33 | 34 | @Override 35 | public int getMinArgs() { 36 | return 1; 37 | } 38 | 39 | @Override 40 | public MathValue[] getArgs() { 41 | return new MathValue[] {this.value}; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/generic/LogFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.generic; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | import software.bernie.geckolib.loading.math.function.MathFunction; 6 | 7 | /** 8 | * {@link MathFunction} value supplier 9 | * 10 | *

11 | * Contract: 12 | *
13 | * Returns the log value (euler base) of the input value 14 | */ 15 | public final class LogFunction extends MathFunction { 16 | private final MathValue value; 17 | 18 | public LogFunction(MathValue... values) { 19 | super(values); 20 | 21 | this.value = values[0]; 22 | } 23 | 24 | @Override 25 | public String getName() { 26 | return "math.ln"; 27 | } 28 | 29 | @Override 30 | public double compute(ControllerState controllerState) { 31 | return Math.log((float)this.value.get(controllerState)); 32 | } 33 | 34 | @Override 35 | public int getMinArgs() { 36 | return 1; 37 | } 38 | 39 | @Override 40 | public MathValue[] getArgs() { 41 | return new MathValue[] {this.value}; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/generic/AbsFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.generic; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | import software.bernie.geckolib.loading.math.function.MathFunction; 6 | 7 | /** 8 | * {@link MathFunction} value supplier 9 | * 10 | *

11 | * Contract: 12 | *
13 | * Returns the absolute (non-negative) equivalent of the input value 14 | */ 15 | public final class AbsFunction extends MathFunction { 16 | private final MathValue value; 17 | 18 | public AbsFunction(MathValue... values) { 19 | super(values); 20 | 21 | this.value = values[0]; 22 | } 23 | 24 | @Override 25 | public String getName() { 26 | return "math.abs"; 27 | } 28 | 29 | @Override 30 | public double compute(ControllerState controllerState) { 31 | return Math.abs(this.value.get(controllerState)); 32 | } 33 | 34 | @Override 35 | public int getMinArgs() { 36 | return 1; 37 | } 38 | 39 | @Override 40 | public MathValue[] getArgs() { 41 | return new MathValue[] {this.value}; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/generic/ExpFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.generic; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | import software.bernie.geckolib.loading.math.function.MathFunction; 6 | 7 | /** 8 | * {@link MathFunction} value supplier 9 | * 10 | *

11 | * Contract: 12 | *
13 | * Returns euler's number raised to the power of the input value 14 | */ 15 | public final class ExpFunction extends MathFunction { 16 | private final MathValue value; 17 | 18 | public ExpFunction(MathValue... values) { 19 | super(values); 20 | 21 | this.value = values[0]; 22 | } 23 | 24 | @Override 25 | public String getName() { 26 | return "math.exp"; 27 | } 28 | 29 | @Override 30 | public double compute(ControllerState controllerState) { 31 | return Math.exp((float)this.value.get(controllerState)); 32 | } 33 | 34 | @Override 35 | public int getMinArgs() { 36 | return 1; 37 | } 38 | 39 | @Override 40 | public MathValue[] getArgs() { 41 | return new MathValue[] {this.value}; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/json/raw/MinecraftGeometry.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.json.raw; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonDeserializer; 5 | import com.google.gson.JsonObject; 6 | import com.google.gson.JsonParseException; 7 | import net.minecraft.util.GsonHelper; 8 | import org.jspecify.annotations.Nullable; 9 | import software.bernie.geckolib.util.JsonUtil; 10 | 11 | /** 12 | * Container class for generic geometry information, only used in deserialization at startup 13 | */ 14 | public record MinecraftGeometry(Bone[] bones, @Nullable String cape, @Nullable ModelProperties modelProperties) { 15 | public static JsonDeserializer deserializer() throws JsonParseException { 16 | return (json, type, context) -> { 17 | JsonObject obj = json.getAsJsonObject(); 18 | Bone[] bones = JsonUtil.jsonArrayToObjectArray(GsonHelper.getAsJsonArray(obj, "bones", new JsonArray(0)), context, Bone.class); 19 | String cape = GsonHelper.getAsString(obj, "cape", null); 20 | ModelProperties modelProperties = GsonHelper.getAsObject(obj, "description", null, context, ModelProperties.class); 21 | 22 | return new MinecraftGeometry(bones, cape, modelProperties); 23 | }; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/renderer/internal/PerBoneRender.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.renderer.internal; 2 | 3 | import com.mojang.blaze3d.vertex.PoseStack; 4 | import net.minecraft.client.renderer.SubmitNodeCollector; 5 | import software.bernie.geckolib.cache.model.GeoBone; 6 | import software.bernie.geckolib.renderer.base.GeoRenderState; 7 | import software.bernie.geckolib.renderer.layer.GeoRenderLayer; 8 | 9 | /** 10 | * A functional interface for submitting a render operation at the {@link PoseStack.Pose pose} of a bone. 11 | *

12 | * Typically you would submit an instance of this to {@link GeoRenderLayer#addPerBoneRender} 13 | */ 14 | @FunctionalInterface 15 | public interface PerBoneRender { 16 | /** 17 | * Submit your per-bone render task for this render pass 18 | * 19 | * @param renderPassInfo The collated render-related data for this render pass. The contained PoseStack is pre-posed at your bone's pose 20 | * @param bone The GeoBone to submit the task for 21 | * @param renderTasks The render submission collector for this render pass. Submit your render task to this 22 | */ 23 | void submitRenderTask(RenderPassInfo renderPassInfo, GeoBone bone, SubmitNodeCollector renderTasks); 24 | } -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/round/CeilFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.round; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | import software.bernie.geckolib.loading.math.function.MathFunction; 6 | 7 | /** 8 | * {@link MathFunction} value supplier 9 | * 10 | *

11 | * Contract: 12 | *
13 | * Returns the smallest value that is greater than or equal to the input value and is equal to an integer 14 | */ 15 | public final class CeilFunction extends MathFunction { 16 | private final MathValue value; 17 | 18 | public CeilFunction(MathValue... values) { 19 | super(values); 20 | 21 | this.value = values[0]; 22 | } 23 | 24 | @Override 25 | public String getName() { 26 | return "math.ceil"; 27 | } 28 | 29 | @Override 30 | public double compute(ControllerState controllerState) { 31 | return Math.ceil(this.value.get(controllerState)); 32 | } 33 | 34 | @Override 35 | public int getMinArgs() { 36 | return 1; 37 | } 38 | 39 | @Override 40 | public MathValue[] getArgs() { 41 | return new MathValue[] {this.value}; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/round/FloorFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.round; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | import software.bernie.geckolib.loading.math.function.MathFunction; 6 | 7 | /** 8 | * {@link MathFunction} value supplier 9 | * 10 | *

11 | * Contract: 12 | *
13 | * Returns the largest value that is less than or equal to the input value and is equal to an integer 14 | */ 15 | public final class FloorFunction extends MathFunction { 16 | private final MathValue value; 17 | 18 | public FloorFunction(MathValue... values) { 19 | super(values); 20 | 21 | this.value = values[0]; 22 | } 23 | 24 | @Override 25 | public String getName() { 26 | return "math.floor"; 27 | } 28 | 29 | @Override 30 | public double compute(ControllerState controllerState) { 31 | return Math.floor(this.value.get(controllerState)); 32 | } 33 | 34 | @Override 35 | public int getMinArgs() { 36 | return 1; 37 | } 38 | 39 | @Override 40 | public MathValue[] getArgs() { 41 | return new MathValue[] {this.value}; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/event/item/CompileItemRenderLayersEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.item; 2 | 3 | import net.minecraft.world.item.Item; 4 | import net.minecraftforge.eventbus.api.bus.EventBus; 5 | import net.minecraftforge.eventbus.api.event.RecordEvent; 6 | import software.bernie.geckolib.animatable.GeoAnimatable; 7 | import software.bernie.geckolib.event.GeoRenderEvent; 8 | import software.bernie.geckolib.renderer.GeoItemRenderer; 9 | 10 | /** 11 | * One-time event for a {@link GeoItemRenderer} called on first initialisation 12 | *

13 | * Use this event to add render layers to the renderer as needed 14 | *

15 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 16 | * 17 | * @see GeoRenderEvent 18 | * @see CompileRenderLayers 19 | */ 20 | public record CompileItemRenderLayersEvent 21 | (GeoItemRenderer renderer) 22 | implements GeoRenderEvent.Item.CompileRenderLayers, RecordEvent { 23 | public static final EventBus BUS = EventBus.create(CompileItemRenderLayersEvent.class); 24 | 25 | @Override 26 | public GeoItemRenderer getRenderer() { 27 | return this.renderer; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/round/TruncateFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.round; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | import software.bernie.geckolib.loading.math.function.MathFunction; 6 | 7 | /** 8 | * {@link MathFunction} value supplier 9 | * 10 | *

11 | * Contract: 12 | *
13 | * Returns the closest value that is equal to the input value or closer to zero, and is equal to an integer 14 | */ 15 | public final class TruncateFunction extends MathFunction { 16 | private final MathValue value; 17 | 18 | public TruncateFunction(MathValue... values) { 19 | super(values); 20 | 21 | this.value = values[0]; 22 | } 23 | 24 | @Override 25 | public String getName() { 26 | return "math.trunc"; 27 | } 28 | 29 | @Override 30 | public double compute(ControllerState controllerState) { 31 | return (long)this.value.get(controllerState); 32 | } 33 | 34 | @Override 35 | public int getMinArgs() { 36 | return 1; 37 | } 38 | 39 | @Override 40 | public MathValue[] getArgs() { 41 | return new MathValue[] {this.value}; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/misc/PiFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.misc; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | import software.bernie.geckolib.loading.math.function.MathFunction; 6 | import software.bernie.geckolib.loading.math.value.Constant; 7 | 8 | /** 9 | * {@link MathFunction} value supplier 10 | * 11 | *

12 | * Contract: 13 | *
14 | * Returns PI 15 | */ 16 | public final class PiFunction extends MathFunction { 17 | public PiFunction(MathValue... values) { 18 | super(values); 19 | } 20 | 21 | @Override 22 | public String getName() { 23 | return "math.pi"; 24 | } 25 | 26 | @Override 27 | public double compute(ControllerState controllerState) { 28 | return Math.PI; 29 | } 30 | 31 | @Override 32 | public boolean isMutable(MathValue... values) { 33 | return false; 34 | } 35 | 36 | @Override 37 | public int getMinArgs() { 38 | return 0; 39 | } 40 | 41 | @Override 42 | public MathValue[] getArgs() { 43 | return new MathValue[] {new Constant(Math.PI)}; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/event/object/CompileObjectRenderLayersEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.object; 2 | 3 | import net.neoforged.bus.api.Event; 4 | import software.bernie.geckolib.animatable.GeoAnimatable; 5 | import software.bernie.geckolib.event.GeoRenderEvent; 6 | import software.bernie.geckolib.renderer.GeoObjectRenderer; 7 | import software.bernie.geckolib.renderer.base.GeoRenderState; 8 | 9 | /** 10 | * One-time event for a {@link GeoObjectRenderer} called on first initialisation 11 | *

12 | * Use this event to add render layers to the renderer as needed 13 | *

14 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 15 | * 16 | * @see GeoRenderEvent 17 | * @see CompileRenderLayers 18 | */ 19 | public class CompileObjectRenderLayersEvent extends Event implements GeoRenderEvent.Object.CompileRenderLayers { 20 | private final GeoObjectRenderer renderer; 21 | 22 | public CompileObjectRenderLayersEvent(GeoObjectRenderer renderer) { 23 | this.renderer = renderer; 24 | } 25 | 26 | @Override 27 | public GeoObjectRenderer getRenderer() { 28 | return this.renderer; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/generic/SinFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.generic; 2 | 3 | import net.minecraft.util.Mth; 4 | import software.bernie.geckolib.animation.state.ControllerState; 5 | import software.bernie.geckolib.loading.math.MathValue; 6 | import software.bernie.geckolib.loading.math.function.MathFunction; 7 | 8 | /** 9 | * {@link MathFunction} value supplier 10 | * 11 | *

12 | * Contract: 13 | *
14 | * Returns the sine of the input value angle, with the input angle converted to radians 15 | */ 16 | public final class SinFunction extends MathFunction { 17 | private final MathValue value; 18 | 19 | public SinFunction(MathValue... values) { 20 | super(values); 21 | 22 | this.value = values[0]; 23 | } 24 | 25 | @Override 26 | public String getName() { 27 | return "math.sin"; 28 | } 29 | 30 | @Override 31 | public double compute(ControllerState controllerState) { 32 | return Math.sin(this.value.get(controllerState) * Mth.DEG_TO_RAD); 33 | } 34 | 35 | @Override 36 | public int getMinArgs() { 37 | return 1; 38 | } 39 | 40 | @Override 41 | public MathValue[] getArgs() { 42 | return new MathValue[] {this.value}; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/generic/ASinFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.generic; 2 | 3 | import net.minecraft.util.Mth; 4 | import software.bernie.geckolib.animation.state.ControllerState; 5 | import software.bernie.geckolib.loading.math.MathValue; 6 | import software.bernie.geckolib.loading.math.function.MathFunction; 7 | 8 | /** 9 | * {@link MathFunction} value supplier 10 | * 11 | *

12 | * Contract: 13 | *
14 | * Returns the arc-sine of the input value angle, with the input angle converted to radians 15 | */ 16 | public final class ASinFunction extends MathFunction { 17 | private final MathValue value; 18 | 19 | public ASinFunction(MathValue... values) { 20 | super(values); 21 | 22 | this.value = values[0]; 23 | } 24 | 25 | @Override 26 | public String getName() { 27 | return "math.asin"; 28 | } 29 | 30 | @Override 31 | public double compute(ControllerState controllerState) { 32 | return Math.asin(this.value.get(controllerState) * Mth.DEG_TO_RAD); 33 | } 34 | 35 | @Override 36 | public int getMinArgs() { 37 | return 1; 38 | } 39 | 40 | @Override 41 | public MathValue[] getArgs() { 42 | return new MathValue[] {this.value}; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/generic/CosFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.generic; 2 | 3 | import net.minecraft.util.Mth; 4 | import software.bernie.geckolib.animation.state.ControllerState; 5 | import software.bernie.geckolib.loading.math.MathValue; 6 | import software.bernie.geckolib.loading.math.function.MathFunction; 7 | 8 | /** 9 | * {@link MathFunction} value supplier 10 | * 11 | *

12 | * Contract: 13 | *
14 | * Returns the cosine of the input value angle, with the input angle converted to radians 15 | */ 16 | public final class CosFunction extends MathFunction { 17 | private final MathValue value; 18 | 19 | public CosFunction(MathValue... values) { 20 | super(values); 21 | 22 | this.value = values[0]; 23 | } 24 | 25 | @Override 26 | public String getName() { 27 | return "math.cos"; 28 | } 29 | 30 | @Override 31 | public double compute(ControllerState controllerState) { 32 | return Mth.cos((float)this.value.get(controllerState) * Mth.DEG_TO_RAD); 33 | } 34 | 35 | @Override 36 | public int getMinArgs() { 37 | return 1; 38 | } 39 | 40 | @Override 41 | public MathValue[] getArgs() { 42 | return new MathValue[] {this.value}; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/generic/ATanFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.generic; 2 | 3 | import net.minecraft.util.Mth; 4 | import software.bernie.geckolib.animation.state.ControllerState; 5 | import software.bernie.geckolib.loading.math.MathValue; 6 | import software.bernie.geckolib.loading.math.function.MathFunction; 7 | 8 | /** 9 | * {@link MathFunction} value supplier 10 | * 11 | *

12 | * Contract: 13 | *
14 | * Returns the arc-tangent of the input value angle, with the input angle converted to radians 15 | */ 16 | public final class ATanFunction extends MathFunction { 17 | private final MathValue value; 18 | 19 | public ATanFunction(MathValue... values) { 20 | super(values); 21 | 22 | this.value = values[0]; 23 | } 24 | 25 | @Override 26 | public String getName() { 27 | return "math.atan"; 28 | } 29 | 30 | @Override 31 | public double compute(ControllerState controllerState) { 32 | return Math.atan(this.value.get(controllerState) * Mth.DEG_TO_RAD); 33 | } 34 | 35 | @Override 36 | public int getMinArgs() { 37 | return 1; 38 | } 39 | 40 | @Override 41 | public MathValue[] getArgs() { 42 | return new MathValue[] {this.value}; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/generic/ACosFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.generic; 2 | 3 | import net.minecraft.util.Mth; 4 | import software.bernie.geckolib.animation.state.ControllerState; 5 | import software.bernie.geckolib.loading.math.MathValue; 6 | import software.bernie.geckolib.loading.math.function.MathFunction; 7 | 8 | /** 9 | * {@link MathFunction} value supplier 10 | * 11 | *

12 | * Contract: 13 | *
14 | * Returns the arc-cosine of the input value angle, with the input angle converted to radians 15 | */ 16 | public final class ACosFunction extends MathFunction { 17 | private final MathValue value; 18 | 19 | public ACosFunction(MathValue... values) { 20 | super(values); 21 | 22 | this.value = values[0]; 23 | } 24 | 25 | @Override 26 | public String getName() { 27 | return "math.acos"; 28 | } 29 | 30 | @Override 31 | public double compute(ControllerState controllerState) { 32 | return Math.acos((float)this.value.get(controllerState) * Mth.DEG_TO_RAD); 33 | } 34 | 35 | @Override 36 | public int getMinArgs() { 37 | return 1; 38 | } 39 | 40 | @Override 41 | public MathValue[] getArgs() { 42 | return new MathValue[] {this.value}; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/limit/MinFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.limit; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | import software.bernie.geckolib.loading.math.function.MathFunction; 6 | 7 | /** 8 | * {@link MathFunction} value supplier 9 | * 10 | *

11 | * Contract: 12 | *
13 | * Returns the lesser of the two input values 14 | */ 15 | public final class MinFunction extends MathFunction { 16 | private final MathValue valueA; 17 | private final MathValue valueB; 18 | 19 | public MinFunction(MathValue... values) { 20 | super(values); 21 | 22 | this.valueA = values[0]; 23 | this.valueB = values[1]; 24 | } 25 | 26 | @Override 27 | public String getName() { 28 | return "math.min"; 29 | } 30 | 31 | @Override 32 | public double compute(ControllerState controllerState) { 33 | return Math.min(this.valueA.get(controllerState), this.valueB.get(controllerState)); 34 | } 35 | 36 | @Override 37 | public int getMinArgs() { 38 | return 2; 39 | } 40 | 41 | @Override 42 | public MathValue[] getArgs() { 43 | return new MathValue[] {this.valueA, this.valueB}; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/limit/MaxFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.limit; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | import software.bernie.geckolib.loading.math.function.MathFunction; 6 | 7 | /** 8 | * {@link MathFunction} value supplier 9 | * 10 | *

11 | * Contract: 12 | *
13 | * Returns the greater of the two input values 14 | */ 15 | public final class MaxFunction extends MathFunction { 16 | private final MathValue valueA; 17 | private final MathValue valueB; 18 | 19 | public MaxFunction(MathValue... values) { 20 | super(values); 21 | 22 | this.valueA = values[0]; 23 | this.valueB = values[1]; 24 | } 25 | 26 | @Override 27 | public String getName() { 28 | return "math.max"; 29 | } 30 | 31 | @Override 32 | public double compute(ControllerState controllerState) { 33 | return Math.max(this.valueA.get(controllerState), this.valueB.get(controllerState)); 34 | } 35 | 36 | @Override 37 | public int getMinArgs() { 38 | return 2; 39 | } 40 | 41 | @Override 42 | public MathValue[] getArgs() { 43 | return new MathValue[] {this.valueA, this.valueB}; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/generic/PowFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.generic; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | import software.bernie.geckolib.loading.math.function.MathFunction; 6 | 7 | /** 8 | * {@link MathFunction} value supplier 9 | * 10 | *

11 | * Contract: 12 | *
13 | * Returns the input value raised to the power of the second input value 14 | */ 15 | public final class PowFunction extends MathFunction { 16 | private final MathValue value; 17 | private final MathValue power; 18 | 19 | public PowFunction(MathValue... values) { 20 | super(values); 21 | 22 | this.value = values[0]; 23 | this.power = values[1]; 24 | } 25 | 26 | @Override 27 | public String getName() { 28 | return "math.pow"; 29 | } 30 | 31 | @Override 32 | public double compute(ControllerState controllerState) { 33 | return Math.pow(this.value.get(controllerState), this.power.get(controllerState)); 34 | } 35 | 36 | @Override 37 | public int getMinArgs() { 38 | return 2; 39 | } 40 | 41 | @Override 42 | public MathValue[] getArgs() { 43 | return new MathValue[] {this.value, this.power}; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/event/object/CompileObjectRenderLayersEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.object; 2 | 3 | import net.minecraftforge.eventbus.api.bus.EventBus; 4 | import net.minecraftforge.eventbus.api.event.RecordEvent; 5 | import software.bernie.geckolib.animatable.GeoAnimatable; 6 | import software.bernie.geckolib.event.GeoRenderEvent; 7 | import software.bernie.geckolib.renderer.GeoObjectRenderer; 8 | import software.bernie.geckolib.renderer.base.GeoRenderState; 9 | 10 | /** 11 | * One-time event for a {@link GeoObjectRenderer} called on first initialisation 12 | *

13 | * Use this event to add render layers to the renderer as needed 14 | *

15 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 16 | * 17 | * @see GeoRenderEvent 18 | * @see CompileRenderLayers 19 | */ 20 | public record CompileObjectRenderLayersEvent 21 | (GeoObjectRenderer renderer) 22 | implements GeoRenderEvent.Object.CompileRenderLayers, RecordEvent { 23 | public static final EventBus BUS = EventBus.create(CompileObjectRenderLayersEvent.class); 24 | 25 | @Override 26 | public GeoObjectRenderer getRenderer() { 27 | return this.renderer; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/generic/ModFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.generic; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | import software.bernie.geckolib.loading.math.function.MathFunction; 6 | 7 | /** 8 | * {@link MathFunction} value supplier 9 | * 10 | *

11 | * Contract: 12 | *
13 | * Returns the remainder value of the input value when modulo'd by the modulus value 14 | */ 15 | public final class ModFunction extends MathFunction { 16 | private final MathValue value; 17 | private final MathValue modulus; 18 | 19 | public ModFunction(MathValue... values) { 20 | super(values); 21 | 22 | this.value = values[0]; 23 | this.modulus = values[1]; 24 | } 25 | 26 | @Override 27 | public String getName() { 28 | return "math.mod"; 29 | } 30 | 31 | @Override 32 | public double compute(ControllerState controllerState) { 33 | return this.value.get(controllerState) % this.modulus.get(controllerState); 34 | } 35 | 36 | @Override 37 | public int getMinArgs() { 38 | return 2; 39 | } 40 | 41 | @Override 42 | public MathValue[] getArgs() { 43 | return new MathValue[] {this.value, this.modulus}; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/renderer/internal/BoneSnapshots.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.renderer.internal; 2 | 3 | import software.bernie.geckolib.animation.state.BoneSnapshot; 4 | import software.bernie.geckolib.cache.model.GeoBone; 5 | 6 | import java.util.Optional; 7 | import java.util.function.Consumer; 8 | 9 | /** 10 | * Getter interface for {@link BoneSnapshot}s at render time. 11 | *

12 | * This is where you access scale/rotation/translation values for bones for a render pass 13 | */ 14 | @FunctionalInterface 15 | public interface BoneSnapshots { 16 | /** 17 | * Get a {@link GeoBone}'s {@link BoneSnapshot} by the bone's name, if the bone exists 18 | * 19 | * @param boneName The name of the bone to get the snapshot for 20 | */ 21 | Optional get(String boneName); 22 | 23 | /** 24 | * Get a {@link GeoBone}'s {@link BoneSnapshot} by the bone's name.
25 | * If it exists, run the given action. 26 | */ 27 | default void ifPresent(String boneName, Consumer action) { 28 | get(boneName).ifPresent(action); 29 | } 30 | 31 | /** 32 | * Get a {@link GeoBone}'s {@link BoneSnapshot} by the bone itself 33 | */ 34 | default BoneSnapshot get(GeoBone bone) { 35 | return bone.frameSnapshot != null ? bone.frameSnapshot : get(bone.name()).get(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/animatable/instance/InstancedAnimatableInstanceCache.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.animatable.instance; 2 | 3 | import software.bernie.geckolib.animatable.GeoAnimatable; 4 | import software.bernie.geckolib.animatable.manager.AnimatableManager; 5 | 6 | /** 7 | * AnimatableInstanceCache implementation for instantiated objects such as Entities or BlockEntities. Returns a single {@link AnimatableManager} instance per cache 8 | *

9 | * You should NOT be instantiating this directly unless you know what you are doing. 10 | * Use {@link software.bernie.geckolib.util.GeckoLibUtil#createInstanceCache GeckoLibUtil.createInstanceCache} instead 11 | */ 12 | public class InstancedAnimatableInstanceCache extends AnimatableInstanceCache { 13 | protected AnimatableManager manager; 14 | 15 | public InstancedAnimatableInstanceCache(GeoAnimatable animatable) { 16 | super(animatable); 17 | } 18 | 19 | /** 20 | * Gets the {@link AnimatableManager} instance from this cache 21 | *

22 | * Because this cache subclass expects a 1:1 relationship of cache to animatable, only one {@code AnimatableManager} instance is used 23 | */ 24 | @Override 25 | public AnimatableManager getManagerForId(long uniqueId) { 26 | if (this.manager == null) 27 | this.manager = new AnimatableManager<>(this.animatable); 28 | 29 | return this.manager; 30 | } 31 | } -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/renderer/internal/AnimationVariables.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.renderer.internal; 2 | 3 | import com.google.common.base.Supplier; 4 | import com.google.common.base.Suppliers; 5 | import it.unimi.dsi.fastutil.objects.Reference2DoubleMap; 6 | import it.unimi.dsi.fastutil.objects.Reference2DoubleOpenHashMap; 7 | import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; 8 | import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; 9 | import software.bernie.geckolib.animatable.GeoAnimatable; 10 | import software.bernie.geckolib.animation.AnimationController; 11 | import software.bernie.geckolib.loading.math.value.Variable; 12 | 13 | /** 14 | * Container object for holding compiled {@link Variable} values for an upcoming render pass 15 | */ 16 | public record AnimationVariables(Supplier, Reference2DoubleMap>> variables) { 17 | public AnimationVariables() { 18 | this(Suppliers.memoize(Reference2ObjectOpenHashMap::new)); 19 | } 20 | 21 | /** 22 | * Get the variable map for a given controller, creating it anew if required 23 | */ 24 | public Reference2DoubleMap forController(AnimationController controller) { 25 | return this.variables.get().computeIfAbsent(controller, key -> new Reference2DoubleOpenHashMap<>()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/json/raw/TextureMesh.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.json.raw; 2 | 3 | import com.google.gson.JsonDeserializer; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.JsonParseException; 6 | import net.minecraft.util.GsonHelper; 7 | import org.jspecify.annotations.Nullable; 8 | import software.bernie.geckolib.util.JsonUtil; 9 | 10 | /** 11 | * Container class for texture mesh information, only used in deserialization at startup 12 | */ 13 | public record TextureMesh(double[] localPivot, double[] position, double[] rotation, double[] scale, @Nullable String texture) { 14 | public static JsonDeserializer deserializer() throws JsonParseException { 15 | return (json, type, context) -> { 16 | JsonObject obj = json.getAsJsonObject(); 17 | double[] pivot = JsonUtil.jsonArrayToDoubleArray(GsonHelper.getAsJsonArray(obj, "local_pivot", null)); 18 | double[] position = JsonUtil.jsonArrayToDoubleArray(GsonHelper.getAsJsonArray(obj, "position", null)); 19 | double[] rotation = JsonUtil.jsonArrayToDoubleArray(GsonHelper.getAsJsonArray(obj, "rotation", null)); 20 | double[] scale = JsonUtil.jsonArrayToDoubleArray(GsonHelper.getAsJsonArray(obj, "scale", null)); 21 | String texture = GsonHelper.getAsString(obj, "texture", null); 22 | 23 | return new TextureMesh(pivot, position, rotation, scale, texture); 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/cache/animation/BoneAnimation.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.cache.animation; 2 | 3 | import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; 4 | import software.bernie.geckolib.loading.math.value.Variable; 5 | 6 | import java.util.Set; 7 | 8 | /** 9 | * A record of a deserialized animation for a given bone 10 | *

11 | * Responsible for holding the various {@link Keyframe Keyframes} for the bone's animation transformations 12 | * 13 | * @param boneName The name of the bone as listed in the {@code animation.json} 14 | * @param rotationKeyFrames The deserialized rotation {@code Keyframe} stack 15 | * @param positionKeyFrames The deserialized position {@code Keyframe} stack 16 | * @param scaleKeyFrames The deserialized scale {@code Keyframe} stack 17 | */ 18 | public record BoneAnimation(String boneName, KeyframeStack rotationKeyFrames, KeyframeStack positionKeyFrames, KeyframeStack scaleKeyFrames) { 19 | /** 20 | * Extract and collect all {@link Variable}s used in this bone animation 21 | */ 22 | public Set getUsedVariables() { 23 | Set usedVariables = new ReferenceOpenHashSet<>(); 24 | 25 | usedVariables.addAll(this.rotationKeyFrames.getUsedVariables()); 26 | usedVariables.addAll(this.positionKeyFrames.getUsedVariables()); 27 | usedVariables.addAll(this.scaleKeyFrames.getUsedVariables()); 28 | 29 | return usedVariables; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/json/raw/PolyMesh.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.json.raw; 2 | 3 | import com.google.gson.JsonDeserializer; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.JsonParseException; 6 | import net.minecraft.util.GsonHelper; 7 | import org.jspecify.annotations.Nullable; 8 | import software.bernie.geckolib.util.JsonUtil; 9 | 10 | /** 11 | * Container class for poly mesh information, only used in deserialization at startup 12 | */ 13 | public record PolyMesh(@Nullable Boolean normalizedUVs, double[] normals, @Nullable PolysUnion polysUnion, double[] positions, double[] uvs) { 14 | public static JsonDeserializer deserializer() throws JsonParseException { 15 | return (json, type, context) -> { 16 | JsonObject obj = json.getAsJsonObject(); 17 | Boolean normalizedUVs = JsonUtil.getOptionalBoolean(obj, "normalized_uvs"); 18 | double[] normals = JsonUtil.jsonArrayToDoubleArray(GsonHelper.getAsJsonArray(obj, "normals", null)); 19 | PolysUnion polysUnion = GsonHelper.getAsObject(obj, "polys", null, context, PolysUnion.class); 20 | double[] positions = JsonUtil.jsonArrayToDoubleArray(GsonHelper.getAsJsonArray(obj, "positions", null)); 21 | double[] uvs = JsonUtil.jsonArrayToDoubleArray(GsonHelper.getAsJsonArray(obj, "uvs", null)); 22 | 23 | return new PolyMesh(normalizedUVs, normals, polysUnion, positions, uvs); 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/cache/animation/keyframeevent/ParticleKeyframeData.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.cache.animation.keyframeevent; 2 | 3 | import software.bernie.geckolib.cache.animation.Keyframe; 4 | 5 | import java.util.Objects; 6 | 7 | /** 8 | * Particle {@link Keyframe} instruction holder 9 | */ 10 | public class ParticleKeyframeData extends KeyFrameData { 11 | private final String effect; 12 | private final String locator; 13 | private final String script; 14 | 15 | public ParticleKeyframeData(double time, String effect, String locator, String script) { 16 | super(time); 17 | 18 | this.script = script; 19 | this.locator = locator; 20 | this.effect = effect; 21 | } 22 | 23 | /** 24 | * Gets the effect id given by the {@link Keyframe} instruction from the {@code animation.json} 25 | */ 26 | public String getEffect() { 27 | return this.effect; 28 | } 29 | 30 | /** 31 | * Gets the locator string given by the {@link Keyframe} instruction from the {@code animation.json} 32 | */ 33 | public String getLocator() { 34 | return this.locator; 35 | } 36 | 37 | /** 38 | * Gets the script string given by the {@link Keyframe} instruction from the {@code animation.json} 39 | */ 40 | public String script() { 41 | return this.script; 42 | } 43 | 44 | @Override 45 | public int hashCode() { 46 | return Objects.hash(getTime(), this.effect, this.locator, this.script); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/event/entity/CompileEntityRenderLayersEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.entity; 2 | 3 | import net.minecraft.client.renderer.entity.state.EntityRenderState; 4 | import net.minecraft.world.entity.Entity; 5 | import net.neoforged.bus.api.Event; 6 | import software.bernie.geckolib.animatable.GeoAnimatable; 7 | import software.bernie.geckolib.event.GeoRenderEvent; 8 | import software.bernie.geckolib.renderer.GeoEntityRenderer; 9 | import software.bernie.geckolib.renderer.base.GeoRenderState; 10 | 11 | /** 12 | * One-time event for a {@link GeoEntityRenderer} called on first initialisation 13 | *

14 | * Use this event to add render layers to the renderer as needed 15 | *

16 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 17 | * 18 | * @see GeoRenderEvent 19 | * @see CompileRenderLayers 20 | */ 21 | public class CompileEntityRenderLayersEvent extends Event implements GeoRenderEvent.Entity.CompileRenderLayers { 22 | private final GeoEntityRenderer renderer; 23 | 24 | public CompileEntityRenderLayersEvent(GeoEntityRenderer renderer) { 25 | this.renderer = renderer; 26 | } 27 | 28 | @Override 29 | public GeoEntityRenderer getRenderer() { 30 | return this.renderer; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/generic/ATan2Function.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.generic; 2 | 3 | import net.minecraft.util.Mth; 4 | import software.bernie.geckolib.animation.state.ControllerState; 5 | import software.bernie.geckolib.loading.math.MathValue; 6 | import software.bernie.geckolib.loading.math.function.MathFunction; 7 | 8 | /** 9 | * {@link MathFunction} value supplier 10 | * 11 | *

12 | * Contract: 13 | *
14 | * Returns the arc-tangent theta of the input rectangular coordinate values (y,x), with the output converted to degrees 15 | */ 16 | public final class ATan2Function extends MathFunction { 17 | private final MathValue y; 18 | private final MathValue x; 19 | 20 | public ATan2Function(MathValue... values) { 21 | super(values); 22 | 23 | this.y = values[0]; 24 | this.x = values[1]; 25 | } 26 | 27 | @Override 28 | public String getName() { 29 | return "math.atan2"; 30 | } 31 | 32 | @Override 33 | public double compute(ControllerState controllerState) { 34 | return Math.atan2(this.y.get(controllerState), this.x.get(controllerState)) * Mth.RAD_TO_DEG; 35 | } 36 | 37 | @Override 38 | public int getMinArgs() { 39 | return 2; 40 | } 41 | 42 | @Override 43 | public MathValue[] getArgs() { 44 | return new MathValue[] {this.y, this.x}; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/round/HermiteBlendFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.round; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | import software.bernie.geckolib.loading.math.function.MathFunction; 6 | 7 | /** 8 | * {@link MathFunction} value supplier 9 | * 10 | *

11 | * Contract: 12 | *
13 | * Returns the Hermite> basis {@code 3t^2 - 2t^3} curve interpolation value based on the input value 14 | */ 15 | public final class HermiteBlendFunction extends MathFunction { 16 | private final MathValue valueA; 17 | 18 | public HermiteBlendFunction(MathValue... values) { 19 | super(values); 20 | 21 | this.valueA = values[0]; 22 | } 23 | 24 | @Override 25 | public String getName() { 26 | return "math.hermite_blend"; 27 | } 28 | 29 | @Override 30 | public double compute(ControllerState controllerState) { 31 | final double value = this.valueA.get(controllerState); 32 | 33 | return (3 * value * value) - (2 * value * value * value); 34 | } 35 | 36 | @Override 37 | public int getMinArgs() { 38 | return 1; 39 | } 40 | 41 | @Override 42 | public MathValue[] getArgs() { 43 | return new MathValue[] {this.valueA}; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/event/armor/CompileArmorRenderLayersEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.armor; 2 | 3 | import net.minecraft.client.renderer.entity.state.HumanoidRenderState; 4 | import net.minecraft.world.item.Item; 5 | import net.neoforged.bus.api.Event; 6 | import software.bernie.geckolib.animatable.GeoItem; 7 | import software.bernie.geckolib.event.GeoRenderEvent; 8 | import software.bernie.geckolib.renderer.GeoArmorRenderer; 9 | import software.bernie.geckolib.renderer.GeoBlockRenderer; 10 | import software.bernie.geckolib.renderer.base.GeoRenderState; 11 | 12 | /** 13 | * One-time event for a {@link GeoBlockRenderer} called on first initialisation 14 | *

15 | * Use this event to add render layers to the renderer as needed 16 | *

17 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 18 | * 19 | * @see GeoRenderEvent 20 | * @see CompileRenderLayers 21 | */ 22 | public class CompileArmorRenderLayersEvent extends Event implements GeoRenderEvent.Armor.CompileRenderLayers { 23 | private final GeoArmorRenderer renderer; 24 | 25 | public CompileArmorRenderLayersEvent(GeoArmorRenderer renderer) { 26 | this.renderer = renderer; 27 | } 28 | 29 | @Override 30 | public GeoArmorRenderer getRenderer() { 31 | return this.renderer; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/mixin/client/SpecialModelRenderersMixin.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.mixin.client; 2 | 3 | import com.mojang.serialization.MapCodec; 4 | import net.minecraft.client.renderer.special.SpecialModelRenderer; 5 | import net.minecraft.client.renderer.special.SpecialModelRenderers; 6 | import net.minecraft.resources.Identifier; 7 | import net.minecraft.util.ExtraCodecs; 8 | import org.spongepowered.asm.mixin.Final; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Shadow; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Inject; 13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 14 | import software.bernie.geckolib.GeckoLibConstants; 15 | import software.bernie.geckolib.renderer.internal.GeckolibItemSpecialRenderer; 16 | 17 | @Mixin(SpecialModelRenderers.class) 18 | public class SpecialModelRenderersMixin { 19 | @Shadow 20 | @Final 21 | private static ExtraCodecs.LateBoundIdMapper> ID_MAPPER; 22 | 23 | /** 24 | * Inject GeckoLib's custom item model renderer into the vanilla map of special renderers 25 | */ 26 | @Inject(method = "bootstrap", at = @At("TAIL")) 27 | private static void geckolib$addSpecialRenderer(CallbackInfo ci) { 28 | ID_MAPPER.put(GeckoLibConstants.id("geckolib"), GeckolibItemSpecialRenderer.Unbaked.MAP_CODEC); 29 | } 30 | } -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/event/entity/CompileEntityRenderLayersEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.entity; 2 | 3 | import net.minecraft.client.renderer.entity.state.EntityRenderState; 4 | import net.minecraft.world.entity.Entity; 5 | import net.minecraftforge.eventbus.api.bus.EventBus; 6 | import net.minecraftforge.eventbus.api.event.RecordEvent; 7 | import software.bernie.geckolib.animatable.GeoAnimatable; 8 | import software.bernie.geckolib.event.GeoRenderEvent; 9 | import software.bernie.geckolib.renderer.GeoEntityRenderer; 10 | import software.bernie.geckolib.renderer.base.GeoRenderState; 11 | 12 | /** 13 | * One-time event for a {@link GeoEntityRenderer} called on first initialisation 14 | *

15 | * Use this event to add render layers to the renderer as needed 16 | *

17 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 18 | * 19 | * @see GeoRenderEvent 20 | * @see CompileRenderLayers 21 | */ 22 | public record CompileEntityRenderLayersEvent 23 | (GeoEntityRenderer renderer) 24 | implements GeoRenderEvent.Entity.CompileRenderLayers, RecordEvent { 25 | public static final EventBus BUS = EventBus.create(CompileEntityRenderLayersEvent.class); 26 | 27 | @Override 28 | public GeoEntityRenderer getRenderer() { 29 | return this.renderer; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/cache/model/cuboid/CuboidGeoBone.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.cache.model.cuboid; 2 | 3 | import com.mojang.blaze3d.vertex.PoseStack; 4 | import com.mojang.blaze3d.vertex.VertexConsumer; 5 | import org.jspecify.annotations.Nullable; 6 | import software.bernie.geckolib.cache.model.GeoBone; 7 | import software.bernie.geckolib.renderer.base.GeoRenderState; 8 | import software.bernie.geckolib.renderer.internal.RenderPassInfo; 9 | 10 | /** 11 | * Implementation of GeoBone for cuboid rendering 12 | */ 13 | public final class CuboidGeoBone extends GeoBone { 14 | public final GeoCube[] cubes; 15 | 16 | public CuboidGeoBone(@Nullable GeoBone parent, String name, GeoBone[] children, GeoCube[] cubes, float pivotX, float pivotY, float pivotZ, float rotX, float rotY, float rotZ) { 17 | super(parent, name, children, pivotX, pivotY, pivotZ, rotX, rotY, rotZ); 18 | 19 | this.cubes = cubes; 20 | } 21 | 22 | @Override 23 | public void render(RenderPassInfo renderPassInfo, PoseStack poseStack, VertexConsumer vertexConsumer, int packedLight, int packedOverlay, int renderColor) { 24 | if (this.frameSnapshot == null || !this.frameSnapshot.isHidden()) { 25 | for (GeoCube cube : this.cubes) { 26 | poseStack.pushPose(); 27 | cube.render(poseStack, vertexConsumer, packedLight, packedOverlay, renderColor); 28 | poseStack.popPose(); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/event/armor/CompileArmorRenderLayersEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.armor; 2 | 3 | import net.minecraft.client.renderer.entity.state.HumanoidRenderState; 4 | import net.minecraft.world.item.Item; 5 | import net.minecraftforge.eventbus.api.bus.EventBus; 6 | import net.minecraftforge.eventbus.api.event.RecordEvent; 7 | import software.bernie.geckolib.animatable.GeoItem; 8 | import software.bernie.geckolib.event.GeoRenderEvent; 9 | import software.bernie.geckolib.renderer.GeoArmorRenderer; 10 | import software.bernie.geckolib.renderer.GeoBlockRenderer; 11 | import software.bernie.geckolib.renderer.base.GeoRenderState; 12 | 13 | /** 14 | * One-time event for a {@link GeoBlockRenderer} called on first initialisation 15 | *

16 | * Use this event to add render layers to the renderer as needed 17 | *

18 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 19 | * 20 | * @see GeoRenderEvent 21 | * @see CompileRenderLayers 22 | */ 23 | public record CompileArmorRenderLayersEvent 24 | (GeoArmorRenderer renderer) 25 | implements GeoRenderEvent.Armor.CompileRenderLayers, RecordEvent { 26 | public static final EventBus BUS = EventBus.create(CompileArmorRenderLayersEvent.class); 27 | 28 | @Override 29 | public GeoArmorRenderer getRenderer() { 30 | return this.renderer; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/event/block/CompileBlockRenderLayersEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.block; 2 | 3 | import net.minecraft.client.renderer.blockentity.state.BlockEntityRenderState; 4 | import net.minecraft.world.level.block.entity.BlockEntity; 5 | import net.neoforged.bus.api.Event; 6 | import software.bernie.geckolib.animatable.GeoAnimatable; 7 | import software.bernie.geckolib.event.GeoRenderEvent; 8 | import software.bernie.geckolib.renderer.GeoArmorRenderer; 9 | import software.bernie.geckolib.renderer.GeoBlockRenderer; 10 | import software.bernie.geckolib.renderer.base.GeoRenderState; 11 | 12 | /** 13 | * One-time event for a {@link GeoArmorRenderer} called on first initialisation 14 | *

15 | * Use this event to add render layers to the renderer as needed 16 | *

17 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 18 | * 19 | * @see GeoRenderEvent 20 | * @see GeoRenderEvent.Armor.CompileRenderLayers 21 | */ 22 | public class CompileBlockRenderLayersEvent extends Event implements GeoRenderEvent.Block.CompileRenderLayers { 23 | private final GeoBlockRenderer renderer; 24 | 25 | public CompileBlockRenderLayersEvent(GeoBlockRenderer renderer) { 26 | this.renderer = renderer; 27 | } 28 | 29 | @Override 30 | public GeoBlockRenderer getRenderer() { 31 | return this.renderer; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/event/replacedentity/CompileReplacedEntityRenderLayersEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.replacedentity; 2 | 3 | import net.minecraft.client.renderer.entity.state.EntityRenderState; 4 | import net.minecraft.world.entity.Entity; 5 | import net.neoforged.bus.api.Event; 6 | import software.bernie.geckolib.animatable.GeoAnimatable; 7 | import software.bernie.geckolib.event.GeoRenderEvent; 8 | import software.bernie.geckolib.renderer.GeoReplacedEntityRenderer; 9 | import software.bernie.geckolib.renderer.base.GeoRenderState; 10 | 11 | /** 12 | * One-time event for a {@link GeoReplacedEntityRenderer} called on first initialisation 13 | *

14 | * Use this event to add render layers to the renderer as needed 15 | *

16 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 17 | * 18 | * @see GeoRenderEvent 19 | * @see CompileRenderLayers 20 | */ 21 | public class CompileReplacedEntityRenderLayersEvent extends Event implements GeoRenderEvent.ReplacedEntity.CompileRenderLayers { 22 | private final GeoReplacedEntityRenderer renderer; 23 | 24 | public CompileReplacedEntityRenderLayersEvent(GeoReplacedEntityRenderer renderer) { 25 | this.renderer = renderer; 26 | } 27 | 28 | @Override 29 | public GeoReplacedEntityRenderer getRenderer() { 30 | return this.renderer; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/value/CompoundValue.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.value; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | 6 | import java.util.Set; 7 | import java.util.StringJoiner; 8 | 9 | /** 10 | * {@link MathValue} value supplier 11 | * 12 | *

13 | * Contract: 14 | *
15 | * Contains a collection of sub-expressions that evaluate before returning the last expression, or 0 if no return is defined. 16 | * Sub-expressions have no bearing on the final return with exception for where they may be setting variable values 17 | */ 18 | public record CompoundValue(MathValue[] subValues, Set usedVariables) implements MathValue { 19 | public CompoundValue(MathValue[] subValues) { 20 | this(subValues, MathValue.collectUsedVariables(subValues)); 21 | } 22 | 23 | @Override 24 | public double get(ControllerState controllerState) { 25 | for (int i = 0; i < this.subValues.length - 1; i++) { 26 | this.subValues[i].get(controllerState); 27 | } 28 | 29 | return this.subValues[this.subValues.length - 1].get(controllerState); 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | final StringJoiner joiner = new StringJoiner("; "); 35 | 36 | for (MathValue subValue : this.subValues) { 37 | joiner.add(subValue.toString()); 38 | } 39 | 40 | return joiner.toString(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/json/raw/Cube.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.json.raw; 2 | 3 | import com.google.gson.JsonDeserializer; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.JsonParseException; 6 | import net.minecraft.util.GsonHelper; 7 | import org.jspecify.annotations.Nullable; 8 | import software.bernie.geckolib.util.JsonUtil; 9 | 10 | /** 11 | * Container class for cube information, only used in deserialization at startup 12 | */ 13 | public record Cube(@Nullable Double inflate, @Nullable Boolean mirror, double[] origin, double[] pivot, double[] rotation, double[] size, UVUnion uv) { 14 | public static JsonDeserializer deserializer() throws JsonParseException { 15 | return (json, type, context) -> { 16 | JsonObject obj = json.getAsJsonObject(); 17 | Double inflate = JsonUtil.getOptionalDouble(obj, "inflate"); 18 | Boolean mirror = JsonUtil.getOptionalBoolean(obj, "mirror"); 19 | double[] origin = JsonUtil.jsonArrayToDoubleArray(GsonHelper.getAsJsonArray(obj, "origin", null)); 20 | double[] pivot = JsonUtil.jsonArrayToDoubleArray(GsonHelper.getAsJsonArray(obj, "pivot", null)); 21 | double[] rotation = JsonUtil.jsonArrayToDoubleArray(GsonHelper.getAsJsonArray(obj, "rotation", null)); 22 | double[] size = JsonUtil.jsonArrayToDoubleArray(GsonHelper.getAsJsonArray(obj, "size", null)); 23 | UVUnion uvUnion = GsonHelper.getAsObject(obj, "uv", null, context, UVUnion.class); 24 | 25 | return new Cube(inflate, mirror, origin, pivot, rotation, size, uvUnion); 26 | }; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/round/LerpFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.round; 2 | 3 | import net.minecraft.util.Mth; 4 | import software.bernie.geckolib.animation.state.ControllerState; 5 | import software.bernie.geckolib.loading.math.MathValue; 6 | import software.bernie.geckolib.loading.math.function.MathFunction; 7 | 8 | /** 9 | * {@link MathFunction} value supplier 10 | * 11 | *

12 | * Contract: 13 | *
14 | * Returns the first value plus the difference between the first and second input values multiplied by the third input value 15 | */ 16 | public final class LerpFunction extends MathFunction { 17 | private final MathValue min; 18 | private final MathValue max; 19 | private final MathValue delta; 20 | 21 | public LerpFunction(MathValue... values) { 22 | super(values); 23 | 24 | this.min = values[0]; 25 | this.max = values[1]; 26 | this.delta = values[2]; 27 | } 28 | 29 | @Override 30 | public String getName() { 31 | return "math.lerp"; 32 | } 33 | 34 | @Override 35 | public double compute(ControllerState controllerState) { 36 | return Mth.lerp(this.delta.get(controllerState), this.min.get(controllerState), this.max.get(controllerState)); 37 | } 38 | 39 | @Override 40 | public int getMinArgs() { 41 | return 3; 42 | } 43 | 44 | @Override 45 | public MathValue[] getArgs() { 46 | return new MathValue[] {this.min, this.max, this.delta}; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/service/GeckoLibPlatform.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.service; 2 | 3 | import net.minecraft.core.component.DataComponentType; 4 | import net.minecraft.world.entity.Entity; 5 | 6 | import java.nio.file.Path; 7 | import java.util.function.Supplier; 8 | import java.util.function.UnaryOperator; 9 | 10 | /** 11 | * Loader-agnostic service interface for general loader-specific functions 12 | */ 13 | public interface GeckoLibPlatform { 14 | /** 15 | * @return Whether the current runtime is an in-dev (non-production) environment, for running debug-only tasks 16 | */ 17 | boolean isDevelopmentEnvironment(); 18 | 19 | /** 20 | * @return Whether the current runtime is on the client side regardless of logical context 21 | */ 22 | boolean isPhysicalClient(); 23 | 24 | /** 25 | * @return The root game directory (./run) 26 | */ 27 | Path getGameDir(); 28 | 29 | /** 30 | * Helper method to account for Forge/NeoForge's custom fluid implementation in relation to swimming in fluids 31 | * 32 | * @return Whether the entity is in a swimmable fluid or not 33 | */ 34 | default boolean isInSwimmableFluid(Entity entity) { 35 | return entity.isInWater(); 36 | } 37 | 38 | /** 39 | * Register a {@link DataComponentType} 40 | *

41 | * This is mostly just used for storing the animatable ID on ItemStacks 42 | */ 43 | Supplier> registerDataComponent(String id, UnaryOperator> builder); 44 | } 45 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/value/Ternary.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.value; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | 6 | import java.util.Set; 7 | 8 | /** 9 | * {@link MathValue} value supplier 10 | * 11 | *

12 | * Contract: 13 | *
14 | * Returns one of two stored values dependent on the result of the stored condition value. 15 | * This returns such that a non-zero result from the condition will return the true stored value, otherwise returning the false stored value 16 | */ 17 | public record Ternary(MathValue condition, MathValue trueValue, MathValue falseValue, Set usedVariables) implements MathValue { 18 | public Ternary(MathValue condition, MathValue trueValue, MathValue falseValue) { 19 | this(condition, trueValue, falseValue, MathValue.collectUsedVariables(condition, trueValue, falseValue)); 20 | } 21 | 22 | @Override 23 | public double get(ControllerState controllerState) { 24 | return this.condition.get(controllerState) != 0 ? this.trueValue.get(controllerState) : this.falseValue.get(controllerState); 25 | } 26 | 27 | @Override 28 | public boolean isMutable() { 29 | return this.condition.isMutable() || this.trueValue.isMutable() || this.falseValue.isMutable(); 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return this.condition.toString() + " ? " + this.trueValue.toString() + " : " + this.falseValue.toString(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/event/block/CompileBlockRenderLayersEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.block; 2 | 3 | import net.minecraft.client.renderer.blockentity.state.BlockEntityRenderState; 4 | import net.minecraft.world.level.block.entity.BlockEntity; 5 | import net.minecraftforge.eventbus.api.bus.EventBus; 6 | import net.minecraftforge.eventbus.api.event.RecordEvent; 7 | import software.bernie.geckolib.animatable.GeoAnimatable; 8 | import software.bernie.geckolib.event.GeoRenderEvent; 9 | import software.bernie.geckolib.renderer.GeoArmorRenderer; 10 | import software.bernie.geckolib.renderer.GeoBlockRenderer; 11 | import software.bernie.geckolib.renderer.base.GeoRenderState; 12 | 13 | /** 14 | * One-time event for a {@link GeoArmorRenderer} called on first initialisation 15 | *

16 | * Use this event to add render layers to the renderer as needed 17 | *

18 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 19 | * 20 | * @see GeoRenderEvent 21 | * @see Armor.CompileRenderLayers 22 | */ 23 | public record CompileBlockRenderLayersEvent 24 | (GeoBlockRenderer renderer) 25 | implements GeoRenderEvent.Block.CompileRenderLayers, RecordEvent { 26 | public static final EventBus BUS = EventBus.create(CompileBlockRenderLayersEvent.class); 27 | 28 | @Override 29 | public GeoBlockRenderer getRenderer() { 30 | return this.renderer; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/limit/ClampFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.limit; 2 | 3 | import net.minecraft.util.Mth; 4 | import software.bernie.geckolib.animation.state.ControllerState; 5 | import software.bernie.geckolib.loading.math.MathValue; 6 | import software.bernie.geckolib.loading.math.function.MathFunction; 7 | 8 | /** 9 | * {@link MathFunction} value supplier 10 | * 11 | *

12 | * Contract: 13 | *
14 | * Returns the first input value if is larger than the second input value and less than the third input value; or else returns the nearest of the second two input values 15 | */ 16 | public final class ClampFunction extends MathFunction { 17 | private final MathValue value; 18 | private final MathValue min; 19 | private final MathValue max; 20 | 21 | public ClampFunction(MathValue... values) { 22 | super(values); 23 | 24 | this.value = values[0]; 25 | this.min = values[1]; 26 | this.max = values[2]; 27 | } 28 | 29 | @Override 30 | public String getName() { 31 | return "math.clamp"; 32 | } 33 | 34 | @Override 35 | public double compute(ControllerState controllerState) { 36 | return Mth.clamp(this.value.get(controllerState), this.min.get(controllerState), this.max.get(controllerState)); 37 | } 38 | 39 | @Override 40 | public int getMinArgs() { 41 | return 3; 42 | } 43 | 44 | @Override 45 | public MathValue[] getArgs() { 46 | return new MathValue[] {this.value, this.min, this.max}; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/event/replacedentity/CompileReplacedEntityRenderLayersEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.replacedentity; 2 | 3 | import net.minecraft.client.renderer.entity.state.EntityRenderState; 4 | import net.minecraft.world.entity.Entity; 5 | import net.minecraftforge.eventbus.api.bus.EventBus; 6 | import net.minecraftforge.eventbus.api.event.RecordEvent; 7 | import software.bernie.geckolib.animatable.GeoAnimatable; 8 | import software.bernie.geckolib.event.GeoRenderEvent; 9 | import software.bernie.geckolib.renderer.GeoReplacedEntityRenderer; 10 | import software.bernie.geckolib.renderer.base.GeoRenderState; 11 | 12 | /** 13 | * One-time event for a {@link GeoReplacedEntityRenderer} called on first initialisation 14 | *

15 | * Use this event to add render layers to the renderer as needed 16 | *

17 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 18 | * 19 | * @see GeoRenderEvent 20 | * @see CompileRenderLayers 21 | */ 22 | public record CompileReplacedEntityRenderLayersEvent 23 | (GeoReplacedEntityRenderer renderer) 24 | implements GeoRenderEvent.ReplacedEntity.CompileRenderLayers, RecordEvent { 25 | public static final EventBus BUS = EventBus.create(CompileReplacedEntityRenderLayersEvent.class); 26 | 27 | @Override 28 | public GeoReplacedEntityRenderer getRenderer() { 29 | return this.renderer; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/json/raw/UVFaces.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.json.raw; 2 | 3 | import com.google.gson.JsonDeserializer; 4 | import com.google.gson.JsonObject; 5 | import net.minecraft.core.Direction; 6 | import net.minecraft.util.GsonHelper; 7 | import org.jspecify.annotations.Nullable; 8 | 9 | /** 10 | * Container class for UV face information, only used in deserialization at startup 11 | */ 12 | public record UVFaces(@Nullable FaceUV north, @Nullable FaceUV south, @Nullable FaceUV east, @Nullable FaceUV west, @Nullable FaceUV up, @Nullable FaceUV down) { 13 | public static JsonDeserializer deserializer() { 14 | return (json, type, context) -> { 15 | JsonObject obj = json.getAsJsonObject(); 16 | FaceUV north = GsonHelper.getAsObject(obj, "north", null, context, FaceUV.class); 17 | FaceUV south = GsonHelper.getAsObject(obj, "south", null, context, FaceUV.class); 18 | FaceUV east = GsonHelper.getAsObject(obj, "east", null, context, FaceUV.class); 19 | FaceUV west = GsonHelper.getAsObject(obj, "west", null, context, FaceUV.class); 20 | FaceUV up = GsonHelper.getAsObject(obj, "up", null, context, FaceUV.class); 21 | FaceUV down = GsonHelper.getAsObject(obj, "down", null, context, FaceUV.class); 22 | 23 | return new UVFaces(north, south, east, west, up, down); 24 | }; 25 | } 26 | 27 | public FaceUV fromDirection(Direction direction) { 28 | return switch(direction) { 29 | case NORTH -> north; 30 | case SOUTH -> south; 31 | case EAST -> east; 32 | case WEST -> west; 33 | case UP -> up; 34 | case DOWN -> down; 35 | }; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/function/round/LerpRotFunction.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.function.round; 2 | 3 | import software.bernie.geckolib.animation.state.ControllerState; 4 | import software.bernie.geckolib.loading.math.MathValue; 5 | import software.bernie.geckolib.loading.math.function.MathFunction; 6 | import software.bernie.geckolib.util.MiscUtil; 7 | 8 | /** 9 | * {@link MathFunction} value supplier 10 | * 11 | *

12 | * Contract: 13 | *
14 | * Returns the first value plus the difference between the first and second input values multiplied by the third input value, wrapping the end result as a degrees value 15 | */ 16 | public final class LerpRotFunction extends MathFunction { 17 | private final MathValue min; 18 | private final MathValue max; 19 | private final MathValue delta; 20 | 21 | public LerpRotFunction(MathValue... values) { 22 | super(values); 23 | 24 | this.min = values[0]; 25 | this.max = values[1]; 26 | this.delta = values[2]; 27 | } 28 | 29 | @Override 30 | public String getName() { 31 | return "math.lerprotate"; 32 | } 33 | 34 | @Override 35 | public double compute(ControllerState controllerState) { 36 | return MiscUtil.lerpYaw(this.delta.get(controllerState), this.min.get(controllerState), this.max.get(controllerState)); 37 | } 38 | 39 | @Override 40 | public int getMinArgs() { 41 | return 3; 42 | } 43 | 44 | @Override 45 | public MathValue[] getArgs() { 46 | return new MathValue[] {this.min, this.max, this.delta}; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/mixin/common/LivingEntityMixin.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.mixin.common; 2 | 3 | import com.llamalad7.mixinextras.injector.wrapoperation.Operation; 4 | import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; 5 | import net.minecraft.world.entity.LivingEntity; 6 | import net.minecraft.world.item.ItemStack; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.injection.At; 9 | import software.bernie.geckolib.GeckoLibConstants; 10 | 11 | /** 12 | * Injection into the equipment change handling to allow for bypassing GeckoLib ItemStack ID parity 13 | */ 14 | @Mixin(LivingEntity.class) 15 | public class LivingEntityMixin { 16 | /** 17 | * In {@code ItemStackMixin#geckolib$skipGeckolibIdOnCompare}, we tell Minecraft to ignore the contents of GeckoLib 18 | * stack ids for the purposes of ItemStack parity. 19 | *

20 | * We temporarily reinstate it here so that the game syncs changes to this specific component 21 | */ 22 | @WrapOperation(method = "equipmentHasChanged", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;matches(Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemStack;)Z")) 23 | public boolean geckolib$allowLazyStackIdParity(ItemStack remoteStack, ItemStack localStack, Operation original) { 24 | return original.call(remoteStack, localStack) && remoteStack.getOrDefault(GeckoLibConstants.STACK_ANIMATABLE_ID_COMPONENT.get(), Integer.MIN_VALUE).equals(localStack.getOrDefault(GeckoLibConstants.STACK_ANIMATABLE_ID_COMPONENT.get(), Integer.MIN_VALUE)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/animatable/stateless/StatelessAnimationController.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.animatable.stateless; 2 | 3 | import org.jetbrains.annotations.ApiStatus; 4 | import org.jspecify.annotations.Nullable; 5 | import software.bernie.geckolib.animatable.GeoAnimatable; 6 | import software.bernie.geckolib.animation.AnimationController; 7 | import software.bernie.geckolib.animation.RawAnimation; 8 | import software.bernie.geckolib.animation.object.PlayState; 9 | import software.bernie.geckolib.animation.state.AnimationTest; 10 | 11 | /** 12 | * Stateless wrapper for {@link AnimationController} 13 | * 14 | * @see StatelessAnimatable 15 | */ 16 | public class StatelessAnimationController extends AnimationController { 17 | protected @Nullable RawAnimation currentAnim = null; 18 | 19 | public StatelessAnimationController(String name) { 20 | super(name, StatelessAnimationController::overrideStateHandler); 21 | } 22 | 23 | /** 24 | * Set the current animation for this controller 25 | *

26 | * This will be used to handle the {@link AnimationTest} at each render pass 27 | */ 28 | public void setCurrentAnimation(@Nullable RawAnimation animation) { 29 | this.currentAnim = animation; 30 | } 31 | 32 | @ApiStatus.Internal 33 | protected static PlayState overrideStateHandler(AnimationTest test) { 34 | if (test.controller() instanceof StatelessAnimationController controller && controller.currentAnim != null) 35 | return test.setAndContinue(controller.currentAnim); 36 | 37 | return PlayState.STOP; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/mixin/common/SynchronizedRemoteSlotMixin.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.mixin.common; 2 | 3 | import com.llamalad7.mixinextras.injector.wrapoperation.Operation; 4 | import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; 5 | import net.minecraft.world.inventory.RemoteSlot; 6 | import net.minecraft.world.item.ItemStack; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.injection.At; 9 | import software.bernie.geckolib.GeckoLibConstants; 10 | 11 | /** 12 | * Injection into the RemoteSlot handling to allow for bypassing GeckoLib ItemStack ID parity 13 | */ 14 | @Mixin(RemoteSlot.Synchronized.class) 15 | public class SynchronizedRemoteSlotMixin { 16 | /** 17 | * In {@code ItemStackMixin#geckolib$skipGeckolibIdOnCompare}, we tell Minecraft to ignore the contents of GeckoLib 18 | * stack ids for the purposes of ItemStack parity. 19 | *

20 | * We temporarily reinstate it here so that the game syncs changes to this specific component 21 | */ 22 | @WrapOperation(method = "matches", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;matches(Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemStack;)Z")) 23 | public boolean geckolib$allowLazyStackIdParity(ItemStack remoteStack, ItemStack localStack, Operation original) { 24 | return original.call(remoteStack, localStack) && remoteStack.getOrDefault(GeckoLibConstants.STACK_ANIMATABLE_ID_COMPONENT.get(), Integer.MIN_VALUE).equals(localStack.getOrDefault(GeckoLibConstants.STACK_ANIMATABLE_ID_COMPONENT.get(), Integer.MIN_VALUE)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | maven { 5 | name = "Forge" 6 | url = uri("https://maven.minecraftforge.net/") 7 | content { 8 | includeGroupAndSubgroups("net.minecraftforge") 9 | } 10 | } 11 | maven { 12 | name = "Fabric" 13 | url = uri("https://maven.fabricmc.net/") 14 | content { 15 | includeGroupAndSubgroups("net.fabricmc") 16 | includeGroup("fabric-loom") 17 | } 18 | } 19 | maven { 20 | name = "Parchment" 21 | url = uri("https://maven.parchmentmc.org") 22 | content { 23 | includeGroupAndSubgroups("org.parchmentmc") 24 | } 25 | } 26 | maven { 27 | name = "NeoForge" 28 | url = uri("https://maven.neoforged.net/") 29 | content { 30 | includeGroupAndSubgroups("net.neoforged") 31 | includeGroup("codechicken") 32 | includeGroup("net.covers1624") 33 | } 34 | } 35 | maven { 36 | name = "Sponge" 37 | url = uri("https://repo.spongepowered.org/repository/maven-public/") 38 | content { 39 | includeGroupAndSubgroups("org.spongepowered") 40 | } 41 | } 42 | } 43 | } 44 | 45 | plugins { 46 | id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" 47 | } 48 | 49 | rootProject.name = "geckolib" 50 | 51 | include("common") 52 | include("fabric") 53 | //include("forge") 54 | include("neoforge") 55 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/animatable/instance/SingletonAnimatableInstanceCache.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.animatable.instance; 2 | 3 | import it.unimi.dsi.fastutil.longs.Long2ObjectMap; 4 | import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; 5 | import org.jetbrains.annotations.ApiStatus; 6 | import software.bernie.geckolib.animatable.GeoAnimatable; 7 | import software.bernie.geckolib.animatable.manager.AnimatableManager; 8 | 9 | /** 10 | * AnimatableInstanceCache implementation for singleton/flyweight objects such as Items. Utilises a keyed map to differentiate different instances of the object 11 | *

12 | * You should NOT be instantiating this directly unless you know what you are doing. 13 | * Use {@link software.bernie.geckolib.util.GeckoLibUtil#createInstanceCache GeckoLibUtil.createInstanceCache} instead 14 | */ 15 | public class SingletonAnimatableInstanceCache extends AnimatableInstanceCache { 16 | protected final Long2ObjectMap> managers = new Long2ObjectOpenHashMap<>(); 17 | 18 | @ApiStatus.Internal 19 | public SingletonAnimatableInstanceCache(GeoAnimatable animatable) { 20 | super(animatable); 21 | } 22 | 23 | /** 24 | * Gets an {@link AnimatableManager} instance from this cache, cached under the id provided, or a new one if one doesn't already exist 25 | *

26 | * This subclass assumes that all animatable instances will be sharing this cache instance, and so differentiates data by ids 27 | */ 28 | @SuppressWarnings("unchecked") 29 | @Override 30 | public AnimatableManager getManagerForId(long uniqueId) { 31 | return (AnimatableManager)this.managers.computeIfAbsent(uniqueId, key -> new AnimatableManager<>(this.animatable)); 32 | } 33 | } -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/json/ModelFormatVersion.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.json; 2 | 3 | import com.google.common.base.Suppliers; 4 | import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; 5 | import net.minecraft.util.Util; 6 | import org.jspecify.annotations.Nullable; 7 | 8 | import java.util.Map; 9 | import java.util.function.Supplier; 10 | 11 | /** 12 | * Geo format version enum, mostly just used in deserialization at startup 13 | */ 14 | public enum ModelFormatVersion { 15 | V_1_12_0("1.12.0"), 16 | V_1_14_0("1.14.0"), 17 | V_1_21_0("1.21.0"); 18 | 19 | private static final Supplier> LOOKUP = Suppliers.memoize(() -> Util.make(new Object2ObjectOpenHashMap<>(), map -> { 20 | for (ModelFormatVersion formatVersion : values()) { 21 | map.put(formatVersion.serializedName, formatVersion); 22 | map.put(formatVersion.name(), formatVersion); 23 | } 24 | })); 25 | 26 | private final String serializedName; 27 | private final boolean supported; 28 | private final String errorMessage; 29 | 30 | ModelFormatVersion(String serializedName) { 31 | this(serializedName, null); 32 | } 33 | 34 | ModelFormatVersion(String serializedName, @Nullable String errorMessage) { 35 | this.serializedName = serializedName; 36 | this.supported = errorMessage == null; 37 | this.errorMessage = errorMessage; 38 | } 39 | 40 | public String getSerializedName() { 41 | return this.serializedName; 42 | } 43 | 44 | public boolean isSupported() { 45 | return this.supported; 46 | } 47 | 48 | public String getErrorMessage() { 49 | return this.errorMessage; 50 | } 51 | 52 | public static @Nullable ModelFormatVersion match(String version) { 53 | return LOOKUP.get().get(version); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/renderer/layer/GeoRenderLayersContainer.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.renderer.layer; 2 | 3 | import it.unimi.dsi.fastutil.objects.ObjectArrayList; 4 | import org.jetbrains.annotations.ApiStatus; 5 | import software.bernie.geckolib.animatable.GeoAnimatable; 6 | import software.bernie.geckolib.renderer.base.GeoRenderState; 7 | import software.bernie.geckolib.renderer.base.GeoRenderer; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Base interface for a container for {@link GeoRenderLayer GeoRenderLayers} 13 | *

14 | * Each renderer should contain an instance of this, for holding its layers and handling events 15 | */ 16 | @ApiStatus.Internal 17 | public class GeoRenderLayersContainer { 18 | private final GeoRenderer renderer; 19 | private final List> layers = new ObjectArrayList<>(); 20 | private boolean compiledLayers = false; 21 | 22 | public GeoRenderLayersContainer(GeoRenderer renderer) { 23 | this.renderer = renderer; 24 | } 25 | 26 | /** 27 | * Get the {@link GeoRenderLayer} list for usage 28 | */ 29 | public List> getRenderLayers() { 30 | if (!this.compiledLayers) 31 | fireCompileRenderLayersEvent(); 32 | 33 | return this.layers; 34 | } 35 | 36 | /** 37 | * Add a new render layer to the container 38 | */ 39 | public void addLayer(GeoRenderLayer layer) { 40 | this.layers.add(layer); 41 | } 42 | 43 | /** 44 | * Create and fire the relevant {@code CompileRenderLayers} event hook for the owning renderer 45 | */ 46 | public void fireCompileRenderLayersEvent() { 47 | this.compiledLayers = true; 48 | 49 | this.renderer.fireCompileRenderLayersEvent(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/util/MiscUtil.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.util; 2 | 3 | import net.minecraft.core.Direction; 4 | import net.minecraft.util.Mth; 5 | 6 | /** 7 | * Helper class for miscellaneous functions that don't fit into the other util classes 8 | */ 9 | public final class MiscUtil { 10 | /** 11 | * Converts a {@link Direction} to a rotational float for rotation purposes 12 | */ 13 | public static float getDirectionAngle(Direction direction) { 14 | return switch(direction) { 15 | case SOUTH -> 90f; 16 | case NORTH -> 270f; 17 | case EAST -> 180f; 18 | default -> 0f; 19 | }; 20 | } 21 | 22 | /** 23 | * Return whether the two floating point values should be considered numerically equal 24 | *

25 | * This is important because of the way floating point values work, there may not necessarily be 26 | * 1:1 equality between two functionally equal floating point values 27 | */ 28 | public static boolean areFloatsEqual(double a, double b) { 29 | return Math.abs(a - b) < Mth.EPSILON; 30 | } 31 | 32 | /** 33 | * Special helper function for lerping yaw. 34 | *

35 | * This exists because yaw in Minecraft handles its yaw a bit strangely; and can cause incorrect results if lerped without accounting for special cases 36 | */ 37 | public static double lerpYaw(double delta, double start, double end) { 38 | start = Mth.wrapDegrees(start); 39 | end = Mth.wrapDegrees(end); 40 | double diff = start - end; 41 | end = diff > 180 || diff < -180 ? start + Math.copySign(360 - Math.abs(diff), diff) : end; 42 | 43 | return Mth.lerp(delta, start, end); 44 | } 45 | 46 | private MiscUtil() {} 47 | } 48 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/value/Calculation.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.value; 2 | 3 | import org.apache.commons.lang3.mutable.MutableDouble; 4 | import software.bernie.geckolib.animation.state.ControllerState; 5 | import software.bernie.geckolib.loading.math.MathValue; 6 | import software.bernie.geckolib.loading.math.Operator; 7 | 8 | import java.util.Set; 9 | 10 | /** 11 | * {@link MathValue} value supplier 12 | * 13 | *

14 | * Contract: 15 | *
16 | * A computed value of argA and argB defined by the contract of the {@link Operator} 17 | */ 18 | public record Calculation(Operator operator, MathValue argA, MathValue argB, boolean isMutable, Set usedVariables, MutableDouble cachedValue) implements MathValue { 19 | public Calculation(Operator operator, MathValue argA, MathValue argB) { 20 | this(operator, argA, argB, argA.isMutable() || argB.isMutable(), MathValue.collectUsedVariables(argA, argB), new MutableDouble(Double.MIN_VALUE)); 21 | } 22 | 23 | @Override 24 | public double get(ControllerState controllerState) { 25 | if (this.isMutable) 26 | return this.operator.compute(this.argA.get(controllerState), this.argB.get(controllerState)); 27 | 28 | if (this.cachedValue.getValue() == Double.MIN_VALUE) 29 | this.cachedValue.setValue(this.operator.compute(this.argA.get(controllerState), this.argB.get(controllerState))); 30 | 31 | return this.cachedValue.getValue(); 32 | } 33 | 34 | @Override 35 | public Set getUsedVariables() { 36 | return this.usedVariables; 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return this.argA.toString() + " " + this.operator.symbol() + " " + this.argB.toString(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/constant/dataticket/DataTicket.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.constant.dataticket; 2 | 3 | import it.unimi.dsi.fastutil.Pair; 4 | import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; 5 | 6 | import java.util.Map; 7 | import java.util.Objects; 8 | 9 | /** 10 | * Ticket object to define a typed data object 11 | * 12 | * @param Data type for this ticket 13 | */ 14 | public class DataTicket { 15 | static final Map, String>, DataTicket> IDENTITY_CACHE = new Object2ObjectOpenHashMap<>(); 16 | 17 | private final String id; 18 | private final Class objectType; 19 | 20 | /** 21 | * @see #create(String, Class) 22 | */ 23 | DataTicket(String id, Class objectType) { 24 | this.id = id; 25 | this.objectType = objectType; 26 | } 27 | 28 | /** 29 | * Create a new DataTicket for a given name and object type 30 | *

31 | * This DataTicket should then be stored statically somewhere and re-used. 32 | */ 33 | public static DataTicket create(String id, Class objectType) { 34 | return (DataTicket)IDENTITY_CACHE.computeIfAbsent(Pair.of(objectType, id), pair -> new DataTicket<>(id, objectType)); 35 | } 36 | 37 | public String id() { 38 | return this.id; 39 | } 40 | 41 | public Class objectType() { 42 | return this.objectType; 43 | } 44 | 45 | @Override 46 | public int hashCode() { 47 | return Objects.hash(this.id, this.objectType); 48 | } 49 | 50 | @Override 51 | public boolean equals(Object obj) { 52 | if (this == obj) 53 | return true; 54 | 55 | if (!(obj instanceof DataTicket other)) 56 | return false; 57 | 58 | return this.objectType == other.objectType && this.id.equals(other.id); 59 | } 60 | 61 | @Override 62 | public String toString() { 63 | return "DataTicket{" + this.id + ": " + this.objectType.getName() + "}"; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/object/CompoundException.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.object; 2 | 3 | import it.unimi.dsi.fastutil.objects.ObjectArrayList; 4 | 5 | import java.util.List; 6 | import java.util.StringJoiner; 7 | 8 | /** 9 | * Nestable {@link Exception} that allows for a stacktrace to additively append context to a singular exception without needing to re-build the stack trace for each wrapper. 10 | *

11 | * This allows for faster stacked exceptions without having errors land sporadically throughout the log as tasks are asynchronously completed. 12 | */ 13 | public class CompoundException extends RuntimeException { 14 | private final List messages = new ObjectArrayList<>(); 15 | 16 | public CompoundException(String message) { 17 | this.messages.add(message); 18 | } 19 | 20 | /** 21 | * Add a message to the stack. 22 | * The message will be given its own line in the log, displayed before any lines already added 23 | * 24 | * @param message The message to add 25 | * @return this 26 | */ 27 | public CompoundException withMessage(String message) { 28 | this.messages.add(message); 29 | 30 | return this; 31 | } 32 | 33 | @Override 34 | public String getLocalizedMessage() { 35 | final StringJoiner joiner = new StringJoiner("\n"); 36 | final int count = this.messages.size() - 1; 37 | 38 | for (int i = count; i >= 0; i--) { 39 | joiner.add((i == count ? "" : "\t".repeat(Math.max(0, count - i)) + "-> ") + this.messages.get(i)); 40 | } 41 | 42 | return joiner.toString(); 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | final String name = "Geckolib.CompoundException"; 48 | final String message = getLocalizedMessage(); 49 | 50 | return message != null ? name + ": " + message : name; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /fabric/src/main/java/software/bernie/geckolib/event/item/CompileItemRenderLayersEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.item; 2 | 3 | import net.fabricmc.fabric.api.event.Event; 4 | import net.fabricmc.fabric.api.event.EventFactory; 5 | import net.minecraft.world.item.Item; 6 | import software.bernie.geckolib.animatable.GeoAnimatable; 7 | import software.bernie.geckolib.event.GeoRenderEvent; 8 | import software.bernie.geckolib.renderer.GeoItemRenderer; 9 | 10 | /** 11 | * One-time event for a {@link GeoItemRenderer} called on first initialisation 12 | *

13 | * Use this event to add render layers to the renderer as needed 14 | *

15 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 16 | * 17 | * @param Item animatable class type 18 | * @see GeoRenderEvent 19 | * @see CompileRenderLayers 20 | */ 21 | public class CompileItemRenderLayersEvent implements GeoRenderEvent.Item.CompileRenderLayers { 22 | public static final Event EVENT = EventFactory.createArrayBacked(Listener.class, post -> {}, listeners -> event -> { 23 | for (Listener listener : listeners) { 24 | listener.handle(event); 25 | } 26 | }); 27 | private final GeoItemRenderer renderer; 28 | 29 | public CompileItemRenderLayersEvent(GeoItemRenderer renderer) { 30 | this.renderer = renderer; 31 | } 32 | 33 | @Override 34 | public GeoItemRenderer getRenderer() { 35 | return this.renderer; 36 | } 37 | 38 | /** 39 | * Event listener interface for the {@link Item.CompileRenderLayers} GeoRenderEvent 40 | * 41 | * @param Item animatable class type 42 | */ 43 | @FunctionalInterface 44 | public interface Listener { 45 | void handle(CompileItemRenderLayersEvent event); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/animation/state/KeyFrameEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.animation.state; 2 | 3 | import software.bernie.geckolib.animatable.GeoAnimatable; 4 | import software.bernie.geckolib.animation.AnimationController; 5 | import software.bernie.geckolib.cache.animation.Keyframe; 6 | import software.bernie.geckolib.cache.animation.keyframeevent.KeyFrameData; 7 | import software.bernie.geckolib.renderer.base.GeoRenderState; 8 | 9 | /** 10 | * Keyframe event object generated when a keyframe marker is encountered for the current render pass by an 11 | * {@link AnimationController} 12 | * 13 | * @param animatable The {@link GeoAnimatable} being animated 14 | * @param renderState The {@link GeoRenderState} for this render pass 15 | * @param controller The {@link software.bernie.geckolib.animation.AnimationController} responsible for the currently playing animation 16 | * @param keyframeData The {@link KeyFrameData} relevant to the encountered {@link Keyframe} 17 | * @param Animatable class type 18 | * @param Keyframe data class type 19 | * 20 | * @see AnimationController.KeyframeEventHandler 21 | */ 22 | public record KeyFrameEvent(T animatable, GeoRenderState renderState, software.bernie.geckolib.animation.AnimationController controller, E keyframeData) { 23 | /** 24 | * Return the partial tick value for the current render pass 25 | */ 26 | public float getPartialTick() { 27 | return this.renderState.getPartialTick(); 28 | } 29 | /** 30 | * Gets the amount of time (in ticks) that have passed in either the current transition or 31 | * animation, depending on the controller's AnimationState. 32 | *

33 | * Note that this does necessarily match the keyframe marker's time, as the controller may have passed the exact marker time 34 | */ 35 | public double getAnimationTick() { 36 | return this.controller.getCurrentAnimationTime(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/animatable/stateless/StatelessGeoEntity.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.animatable.stateless; 2 | 3 | import net.minecraft.world.entity.Entity; 4 | import software.bernie.geckolib.GeckoLibServices; 5 | import software.bernie.geckolib.animatable.GeoEntity; 6 | import software.bernie.geckolib.animation.RawAnimation; 7 | import software.bernie.geckolib.network.packet.entity.StatelessEntityPlayAnimPacket; 8 | import software.bernie.geckolib.network.packet.entity.StatelessEntityStopAnimPacket; 9 | 10 | /** 11 | * Extension of {@link StatelessAnimatable} for {@link GeoEntity} animatables 12 | */ 13 | public non-sealed interface StatelessGeoEntity extends StatelessAnimatable, GeoEntity { 14 | /** 15 | * Start or continue a pre-defined animation 16 | */ 17 | @Override 18 | default void playAnimation(RawAnimation animation) { 19 | if (!(this instanceof Entity self)) 20 | throw new ClassCastException("Cannot use StatelessGeoEntity on a non-entity animatable!"); 21 | 22 | if (self.level().isClientSide()) { 23 | handleClientAnimationPlay(this, self.getId(), animation); 24 | } 25 | else { 26 | GeckoLibServices.NETWORK.sendToAllPlayersTrackingEntity(new StatelessEntityPlayAnimPacket(self.getId(), false, animation), self); 27 | } 28 | } 29 | 30 | /** 31 | * Stop an already-playing animation 32 | */ 33 | @Override 34 | default void stopAnimation(String animation) { 35 | if (!(this instanceof Entity self)) 36 | throw new ClassCastException("Cannot use StatelessGeoEntity on a non-entity animatable!"); 37 | 38 | if (self.level().isClientSide()) { 39 | handleClientAnimationStop(this, self.getId(), animation); 40 | } 41 | else { 42 | GeckoLibServices.NETWORK.sendToAllPlayersTrackingEntity(new StatelessEntityStopAnimPacket(self.getId(), false, animation), self); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/event/entity/CompileEntityRenderStateEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.entity; 2 | 3 | import net.minecraft.client.renderer.entity.state.EntityRenderState; 4 | import net.minecraft.world.entity.Entity; 5 | import net.minecraftforge.eventbus.api.bus.EventBus; 6 | import net.minecraftforge.eventbus.api.event.RecordEvent; 7 | import org.jetbrains.annotations.ApiStatus; 8 | import software.bernie.geckolib.animatable.GeoAnimatable; 9 | import software.bernie.geckolib.event.GeoRenderEvent; 10 | import software.bernie.geckolib.renderer.GeoEntityRenderer; 11 | import software.bernie.geckolib.renderer.base.GeoRenderState; 12 | 13 | /** 14 | * Pre-render event for entities being rendered by {@link GeoEntityRenderer} 15 | *

16 | * This event is called in preparation for rendering, when the renderer is gathering data to pass through 17 | *

18 | * Use this event to add data that you may need in a later {@link Entity} event, or to override/replace data used in rendering 19 | *

20 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 21 | * 22 | * @see GeoRenderEvent 23 | * @see CompileRenderState 24 | */ 25 | public record CompileEntityRenderStateEvent 26 | (GeoEntityRenderer renderer, R renderState, T animatable) 27 | implements GeoRenderEvent.Entity.CompileRenderState, RecordEvent { 28 | public static final EventBus BUS = EventBus.create(CompileEntityRenderStateEvent.class); 29 | 30 | @Override 31 | public GeoEntityRenderer getRenderer() { 32 | return this.renderer; 33 | } 34 | 35 | @Override 36 | public T getAnimatable() { 37 | return this.animatable; 38 | } 39 | 40 | @ApiStatus.Internal 41 | @Override 42 | public R getRenderState() { 43 | return this.renderState; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/object/DeferredCache.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.object; 2 | 3 | import java.util.function.Function; 4 | 5 | /** 6 | * Functional object that acts as a two-stage memoizing function of sorts. 7 | *

8 | * Takes an input object and a mapping function. Up until the mapping function is called 9 | * 10 | * @param The input object type 11 | * @param The output object type 12 | */ 13 | public class DeferredCache { 14 | private I input; 15 | private O output = null; 16 | private boolean computed = false; 17 | private final Function mappingFunction; 18 | 19 | public DeferredCache(I input, Function mappingFunction) { 20 | this.input = input; 21 | this.mappingFunction = mappingFunction; 22 | } 23 | 24 | /** 25 | * Retrieve the input object for this cache. 26 | *

27 | * Can only be accessed until the output has been computed 28 | */ 29 | public I getInput() { 30 | if (this.computed) 31 | throw new IllegalStateException("Attempting to access input after output of deferred cache has been calculated!"); 32 | 33 | return this.input; 34 | } 35 | 36 | /** 37 | * Retrieve the output object for this cache. 38 | *

39 | * Can only be accessed once the output has been computed 40 | */ 41 | public O getOutput() { 42 | if (!this.computed) 43 | throw new IllegalStateException("Attempting to access output before it has been calculated!"); 44 | 45 | return this.output; 46 | } 47 | 48 | /** 49 | * Compute the output object for this cache and invalidate the input 50 | * 51 | * @return The computed output 52 | */ 53 | public O compute() { 54 | if (!this.computed) { 55 | this.output = this.mappingFunction.apply(this.input); 56 | this.input = null; 57 | this.computed = true; 58 | } 59 | 60 | return getOutput(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/event/block/CompileBlockRenderStateEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.block; 2 | 3 | import net.minecraft.client.renderer.blockentity.state.BlockEntityRenderState; 4 | import net.minecraft.world.level.block.entity.BlockEntity; 5 | import net.minecraftforge.eventbus.api.bus.EventBus; 6 | import net.minecraftforge.eventbus.api.event.RecordEvent; 7 | import org.jetbrains.annotations.ApiStatus; 8 | import software.bernie.geckolib.animatable.GeoAnimatable; 9 | import software.bernie.geckolib.event.GeoRenderEvent; 10 | import software.bernie.geckolib.renderer.GeoBlockRenderer; 11 | import software.bernie.geckolib.renderer.base.GeoRenderState; 12 | 13 | /** 14 | * Pre-render event for blocks being rendered by {@link GeoBlockRenderer} 15 | *

16 | * This event is called in preparation for rendering, when the renderer is gathering data to pass through 17 | *

18 | * Use this event to add data that you may need in a later {@link Block} event, or to override/replace data used in rendering 19 | *

20 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 21 | * 22 | * @see GeoRenderEvent 23 | * @see CompileRenderState 24 | */ 25 | public record CompileBlockRenderStateEvent 26 | (GeoBlockRenderer renderer, R renderState, T animatable) 27 | implements GeoRenderEvent.Block.CompileRenderState, RecordEvent { 28 | public static final EventBus BUS = EventBus.create(CompileBlockRenderStateEvent.class); 29 | 30 | @Override 31 | public GeoBlockRenderer getRenderer() { 32 | return this.renderer; 33 | } 34 | 35 | @Override 36 | public T getAnimatable() { 37 | return this.animatable; 38 | } 39 | 40 | @ApiStatus.Internal 41 | @Override 42 | public R getRenderState() { 43 | return this.renderState; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/event/item/CompileItemRenderStateEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.item; 2 | 3 | import net.minecraft.world.item.Item; 4 | import net.minecraftforge.eventbus.api.bus.EventBus; 5 | import net.minecraftforge.eventbus.api.event.RecordEvent; 6 | import org.jetbrains.annotations.ApiStatus; 7 | import software.bernie.geckolib.animatable.GeoAnimatable; 8 | import software.bernie.geckolib.event.GeoRenderEvent; 9 | import software.bernie.geckolib.renderer.GeoItemRenderer; 10 | import software.bernie.geckolib.renderer.base.GeoRenderState; 11 | 12 | /** 13 | * Pre-render event for items being rendered by {@link GeoItemRenderer} 14 | *

15 | * This event is called in preparation for rendering, when the renderer is gathering data to pass through 16 | *

17 | * Use this event to add data that you may need in a later {@link Item} event, or to override/replace data used in rendering 18 | *

19 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 20 | * 21 | * @see GeoRenderEvent 22 | * @see CompileRenderState 23 | */ 24 | public record CompileItemRenderStateEvent 25 | (GeoItemRenderer renderer, GeoRenderState renderState, T animatable, GeoItemRenderer.RenderData renderData) 26 | implements GeoRenderEvent.Item.CompileRenderState, RecordEvent { 27 | public static final EventBus BUS = EventBus.create(CompileItemRenderStateEvent.class); 28 | 29 | @Override 30 | public GeoItemRenderer getRenderer() { 31 | return this.renderer; 32 | } 33 | 34 | @Override 35 | public T getAnimatable() { 36 | return this.animatable; 37 | } 38 | 39 | @Override 40 | public GeoItemRenderer.RenderData getRenderData() { 41 | return this.renderData; 42 | } 43 | 44 | @ApiStatus.Internal 45 | @Override 46 | public GeoRenderState getRenderState() { 47 | return this.renderState; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/event/object/CompileObjectRenderStateEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.object; 2 | 3 | import net.minecraftforge.eventbus.api.bus.EventBus; 4 | import net.minecraftforge.eventbus.api.event.RecordEvent; 5 | import org.jetbrains.annotations.ApiStatus; 6 | import org.jspecify.annotations.Nullable; 7 | import software.bernie.geckolib.animatable.GeoAnimatable; 8 | import software.bernie.geckolib.event.GeoRenderEvent; 9 | import software.bernie.geckolib.renderer.GeoObjectRenderer; 10 | import software.bernie.geckolib.renderer.base.GeoRenderState; 11 | 12 | /** 13 | * Pre-render event for objects being rendered by {@link GeoObjectRenderer} 14 | *

15 | * This event is called in preparation for rendering, when the renderer is gathering data to pass through 16 | *

17 | * Use this event to add data that you may need in a later {@link Object} event, or to override/replace data used in rendering 18 | *

19 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 20 | * 21 | * @see GeoRenderEvent 22 | * @see CompileRenderState 23 | */ 24 | public record CompileObjectRenderStateEvent 25 | (GeoObjectRenderer renderer, R renderState, T animatable, @Nullable E relatedObject) 26 | implements GeoRenderEvent.Object.CompileRenderState, RecordEvent { 27 | public static final EventBus BUS = EventBus.create(CompileObjectRenderStateEvent.class); 28 | 29 | @Override 30 | public GeoObjectRenderer getRenderer() { 31 | return this.renderer; 32 | } 33 | 34 | @Override 35 | public T getAnimatable() { 36 | return this.animatable; 37 | } 38 | 39 | @ApiStatus.Internal 40 | @Override 41 | public R getRenderState() { 42 | return this.renderState; 43 | } 44 | 45 | @Override 46 | public @Nullable E getRelatedObject() { 47 | return this.relatedObject; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/network/packet/blockentity/BlockEntityAnimTriggerPacket.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.network.packet.blockentity; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.network.FriendlyByteBuf; 5 | import net.minecraft.network.codec.ByteBufCodecs; 6 | import net.minecraft.network.codec.StreamCodec; 7 | import net.minecraft.network.protocol.common.custom.CustomPacketPayload; 8 | import net.minecraft.world.entity.player.Player; 9 | import org.jspecify.annotations.Nullable; 10 | import software.bernie.geckolib.GeckoLibConstants; 11 | import software.bernie.geckolib.animatable.GeoBlockEntity; 12 | import software.bernie.geckolib.network.packet.MultiloaderPacket; 13 | import software.bernie.geckolib.util.ClientUtil; 14 | 15 | import java.util.Optional; 16 | import java.util.function.Consumer; 17 | 18 | public record BlockEntityAnimTriggerPacket(BlockPos pos, Optional controllerName, String animName) implements MultiloaderPacket { 19 | public static final CustomPacketPayload.Type TYPE = new Type<>(GeckoLibConstants.id("blockentity_anim_trigger")); 20 | public static final StreamCodec CODEC = StreamCodec.composite( 21 | BlockPos.STREAM_CODEC, BlockEntityAnimTriggerPacket::pos, 22 | ByteBufCodecs.STRING_UTF8.apply(ByteBufCodecs::optional), BlockEntityAnimTriggerPacket::controllerName, 23 | ByteBufCodecs.STRING_UTF8, BlockEntityAnimTriggerPacket::animName, 24 | BlockEntityAnimTriggerPacket::new); 25 | 26 | @Override 27 | public Type type() { 28 | return TYPE; 29 | } 30 | 31 | @Override 32 | public void receiveMessage(@Nullable Player sender, Consumer workQueue) { 33 | workQueue.accept(() -> { 34 | if (ClientUtil.getLevel().getBlockEntity(this.pos) instanceof GeoBlockEntity blockEntity) 35 | blockEntity.triggerAnim(this.controllerName.orElse(null), this.animName); 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/cache/AnimatableIdCache.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.cache; 2 | 3 | import com.mojang.serialization.Codec; 4 | import com.mojang.serialization.codecs.RecordCodecBuilder; 5 | import net.minecraft.server.level.ServerLevel; 6 | import net.minecraft.world.level.saveddata.SavedData; 7 | import net.minecraft.world.level.saveddata.SavedDataType; 8 | import software.bernie.geckolib.GeckoLibConstants; 9 | import software.bernie.geckolib.animatable.instance.SingletonAnimatableInstanceCache; 10 | 11 | /** 12 | * Storage class that keeps track of the last animatable id used, and provides new ones on request 13 | *

14 | * Generally only used for {@link net.minecraft.world.item.Item Items}, but any {@link SingletonAnimatableInstanceCache singleton} will likely use this. 15 | */ 16 | public final class AnimatableIdCache extends SavedData { 17 | private static final Codec CODEC = RecordCodecBuilder.create(builder -> builder.group( 18 | Codec.LONG.fieldOf("last_id").forGetter(cache -> cache.lastId) 19 | ).apply(builder, AnimatableIdCache::new)); 20 | public static final SavedDataType TYPE = new SavedDataType<>(GeckoLibConstants.MODID + "_id_cache", AnimatableIdCache::new, CODEC, null); 21 | 22 | private long lastId; 23 | 24 | private AnimatableIdCache() { 25 | this(0); 26 | } 27 | 28 | private AnimatableIdCache(long lastId) { 29 | this.lastId = lastId; 30 | } 31 | 32 | /** 33 | * Get the next free id from the id cache 34 | * 35 | * @param level An arbitrary ServerLevel. It doesn't matter which one 36 | * @return The next free ID, which is immediately reserved for use after calling this method 37 | */ 38 | public static long getFreeId(ServerLevel level) { 39 | return getCache(level.getServer().overworld()).getNextId(); 40 | } 41 | 42 | private long getNextId() { 43 | setDirty(); 44 | 45 | return ++this.lastId; 46 | } 47 | 48 | private static AnimatableIdCache getCache(ServerLevel level) { 49 | return level.getServer().overworld().getDataStorage().computeIfAbsent(TYPE); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/mixin/client/SpecialModelWrapperMixin.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.mixin.client; 2 | 3 | import com.llamalad7.mixinextras.injector.wrapoperation.Operation; 4 | import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; 5 | import net.minecraft.client.multiplayer.ClientLevel; 6 | import net.minecraft.client.renderer.item.ItemModelResolver; 7 | import net.minecraft.client.renderer.item.ItemStackRenderState; 8 | import net.minecraft.client.renderer.item.SpecialModelWrapper; 9 | import net.minecraft.client.renderer.special.SpecialModelRenderer; 10 | import net.minecraft.world.entity.ItemOwner; 11 | import net.minecraft.world.item.ItemDisplayContext; 12 | import net.minecraft.world.item.ItemStack; 13 | import org.jspecify.annotations.Nullable; 14 | import org.spongepowered.asm.mixin.Mixin; 15 | import org.spongepowered.asm.mixin.injection.At; 16 | import software.bernie.geckolib.renderer.internal.GeckolibItemSpecialRenderer; 17 | 18 | @Mixin(SpecialModelWrapper.class) 19 | public class SpecialModelWrapperMixin { 20 | /** 21 | * Expand the data points available for GeckoLib item rendering, since vanilla ignores most of it 22 | */ 23 | @WrapOperation(method = "update", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/special/SpecialModelRenderer;extractArgument(Lnet/minecraft/world/item/ItemStack;)Ljava/lang/Object;")) 24 | public T geckolib$extractAllArguments(SpecialModelRenderer instance, ItemStack itemStack, Operation original, 25 | ItemStackRenderState renderState, ItemStack itemStack2, ItemModelResolver modelResolver, 26 | ItemDisplayContext displayContext, @Nullable ClientLevel level, @Nullable ItemOwner itemOwner, int layerIndex) { 27 | return instance instanceof GeckolibItemSpecialRenderer geckolibRenderer ? 28 | (T)geckolibRenderer.extractArgument(itemStack, renderState, displayContext, level, itemOwner) : 29 | original.call(instance, itemStack); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/event/entity/CompileEntityRenderStateEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.entity; 2 | 3 | import net.minecraft.client.renderer.entity.state.EntityRenderState; 4 | import net.minecraft.world.entity.Entity; 5 | import net.neoforged.bus.api.Event; 6 | import org.jetbrains.annotations.ApiStatus; 7 | import software.bernie.geckolib.animatable.GeoAnimatable; 8 | import software.bernie.geckolib.event.GeoRenderEvent; 9 | import software.bernie.geckolib.renderer.GeoEntityRenderer; 10 | import software.bernie.geckolib.renderer.base.GeoRenderState; 11 | 12 | /** 13 | * Pre-render event for entities being rendered by {@link GeoEntityRenderer} 14 | *

15 | * This event is called in preparation for rendering, when the renderer is gathering data to pass through 16 | *

17 | * Use this event to add data that you may need in a later {@link Entity} event, or to override/replace data used in rendering 18 | *

19 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 20 | * 21 | * @see GeoRenderEvent 22 | * @see CompileRenderState 23 | */ 24 | public class CompileEntityRenderStateEvent extends Event implements GeoRenderEvent.Entity.CompileRenderState { 25 | private final GeoEntityRenderer renderer; 26 | private final R renderState; 27 | private final T animatable; 28 | 29 | public CompileEntityRenderStateEvent(GeoEntityRenderer renderer, R renderState, T animatable) { 30 | this.renderer = renderer; 31 | this.renderState = renderState; 32 | this.animatable = animatable; 33 | } 34 | 35 | @Override 36 | public GeoEntityRenderer getRenderer() { 37 | return this.renderer; 38 | } 39 | 40 | @Override 41 | public T getAnimatable() { 42 | return this.animatable; 43 | } 44 | 45 | @ApiStatus.Internal 46 | @Override 47 | public R getRenderState() { 48 | return this.renderState; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/network/packet/blockentity/StatelessBlockEntityStopAnimPacket.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.network.packet.blockentity; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.network.FriendlyByteBuf; 5 | import net.minecraft.network.codec.ByteBufCodecs; 6 | import net.minecraft.network.codec.StreamCodec; 7 | import net.minecraft.network.protocol.common.custom.CustomPacketPayload; 8 | import net.minecraft.world.entity.player.Player; 9 | import org.jspecify.annotations.Nullable; 10 | import software.bernie.geckolib.GeckoLibConstants; 11 | import software.bernie.geckolib.animatable.GeoBlockEntity; 12 | import software.bernie.geckolib.animatable.stateless.StatelessGeoBlockEntity; 13 | import software.bernie.geckolib.network.packet.MultiloaderPacket; 14 | import software.bernie.geckolib.util.ClientUtil; 15 | 16 | import java.util.function.Consumer; 17 | 18 | public record StatelessBlockEntityStopAnimPacket(BlockPos blockPos, String animation) implements MultiloaderPacket { 19 | public static final Type TYPE = new Type<>(GeckoLibConstants.id("stateless_block_entity_stop_anim")); 20 | public static final StreamCodec CODEC = StreamCodec.composite( 21 | BlockPos.STREAM_CODEC, StatelessBlockEntityStopAnimPacket::blockPos, 22 | ByteBufCodecs.STRING_UTF8, StatelessBlockEntityStopAnimPacket::animation, 23 | StatelessBlockEntityStopAnimPacket::new); 24 | 25 | @Override 26 | public Type type() { 27 | return TYPE; 28 | } 29 | 30 | @Override 31 | public void receiveMessage(@Nullable Player sender, Consumer workQueue) { 32 | workQueue.accept(() -> { 33 | if (ClientUtil.getLevel().getBlockEntity(this.blockPos) instanceof GeoBlockEntity blockEntity && blockEntity instanceof StatelessGeoBlockEntity statelessAnimatable) 34 | statelessAnimatable.handleClientAnimationStop(blockEntity, 0, this.animation); 35 | }); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/object/GeometryTree.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.object; 2 | 3 | import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; 4 | import software.bernie.geckolib.loading.json.raw.Bone; 5 | import software.bernie.geckolib.loading.json.raw.MinecraftGeometry; 6 | import software.bernie.geckolib.loading.json.raw.Model; 7 | import software.bernie.geckolib.loading.json.raw.ModelProperties; 8 | 9 | import java.util.Map; 10 | 11 | /** 12 | * Container class for a {@link Bone} structure, used at startup during deserialization 13 | */ 14 | public record GeometryTree(Map topLevelBones, ModelProperties properties) { 15 | public static GeometryTree fromModel(Model model) { 16 | final Map topLevelBones = new Object2ObjectOpenHashMap<>(); 17 | final MinecraftGeometry geometry = model.minecraftGeometry()[0]; 18 | final Bone[] bones = geometry.bones(); 19 | final Map lookup = new Object2ObjectOpenHashMap<>(bones.length); 20 | 21 | for (Bone bone : bones) { 22 | final BoneStructure boneStructure = new BoneStructure(bone); 23 | 24 | lookup.put(bone.name(), boneStructure); 25 | 26 | if (bone.parent() == null) 27 | topLevelBones.put(bone.name(), boneStructure); 28 | } 29 | 30 | for (Bone bone : bones) { 31 | final String parentName = bone.parent(); 32 | 33 | if (parentName != null) { 34 | final String boneName = bone.name(); 35 | 36 | if (parentName.equals(boneName)) 37 | throw new IllegalArgumentException("Invalid model definition. Bone has defined itself as its own parent: " + boneName); 38 | 39 | final BoneStructure parentStructure = lookup.get(parentName); 40 | 41 | if (parentStructure == null) 42 | throw new IllegalArgumentException("Invalid model definition. Found bone with undefined parent (child -> parent): " + boneName + " -> " + parentName); 43 | 44 | parentStructure.children().put(boneName, lookup.get(boneName)); 45 | } 46 | } 47 | 48 | return new GeometryTree(topLevelBones, geometry.modelProperties()); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/network/packet/blockentity/StatelessBlockEntityPlayAnimPacket.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.network.packet.blockentity; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.network.FriendlyByteBuf; 5 | import net.minecraft.network.codec.StreamCodec; 6 | import net.minecraft.network.protocol.common.custom.CustomPacketPayload; 7 | import net.minecraft.world.entity.player.Player; 8 | import org.jspecify.annotations.Nullable; 9 | import software.bernie.geckolib.GeckoLibConstants; 10 | import software.bernie.geckolib.animatable.GeoBlockEntity; 11 | import software.bernie.geckolib.animatable.stateless.StatelessGeoBlockEntity; 12 | import software.bernie.geckolib.animation.RawAnimation; 13 | import software.bernie.geckolib.network.packet.MultiloaderPacket; 14 | import software.bernie.geckolib.util.ClientUtil; 15 | 16 | import java.util.function.Consumer; 17 | 18 | public record StatelessBlockEntityPlayAnimPacket(BlockPos blockPos, RawAnimation animation) implements MultiloaderPacket { 19 | public static final Type TYPE = new Type<>(GeckoLibConstants.id("stateless_block_entity_play_anim")); 20 | public static final StreamCodec CODEC = StreamCodec.composite( 21 | BlockPos.STREAM_CODEC, StatelessBlockEntityPlayAnimPacket::blockPos, 22 | RawAnimation.STREAM_CODEC, StatelessBlockEntityPlayAnimPacket::animation, 23 | StatelessBlockEntityPlayAnimPacket::new); 24 | 25 | @Override 26 | public Type type() { 27 | return TYPE; 28 | } 29 | 30 | @Override 31 | public void receiveMessage(@Nullable Player sender, Consumer workQueue) { 32 | workQueue.accept(() -> { 33 | if (ClientUtil.getLevel().getBlockEntity(this.blockPos) instanceof GeoBlockEntity blockEntity && blockEntity instanceof StatelessGeoBlockEntity statelessAnimatable) 34 | statelessAnimatable.handleClientAnimationPlay(blockEntity, 0, this.animation); 35 | }); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/event/block/CompileBlockRenderStateEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.block; 2 | 3 | import net.minecraft.client.renderer.blockentity.state.BlockEntityRenderState; 4 | import net.minecraft.world.level.block.entity.BlockEntity; 5 | import net.neoforged.bus.api.Event; 6 | import org.jetbrains.annotations.ApiStatus; 7 | import software.bernie.geckolib.animatable.GeoAnimatable; 8 | import software.bernie.geckolib.event.GeoRenderEvent; 9 | import software.bernie.geckolib.renderer.GeoBlockRenderer; 10 | import software.bernie.geckolib.renderer.base.GeoRenderState; 11 | 12 | /** 13 | * Pre-render event for blocks being rendered by {@link GeoBlockRenderer} 14 | *

15 | * This event is called in preparation for rendering, when the renderer is gathering data to pass through 16 | *

17 | * Use this event to add data that you may need in a later {@link Block} event, or to override/replace data used in rendering 18 | *

19 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 20 | * 21 | * @see GeoRenderEvent 22 | * @see CompileRenderState 23 | */ 24 | public class CompileBlockRenderStateEvent extends Event implements GeoRenderEvent.Block.CompileRenderState { 25 | private final GeoBlockRenderer renderer; 26 | private final R renderState; 27 | private final T animatable; 28 | 29 | public CompileBlockRenderStateEvent(GeoBlockRenderer renderer, R renderState, T animatable) { 30 | this.renderer = renderer; 31 | this.renderState = renderState; 32 | this.animatable = animatable; 33 | } 34 | 35 | @Override 36 | public GeoBlockRenderer getRenderer() { 37 | return this.renderer; 38 | } 39 | 40 | @Override 41 | public T getAnimatable() { 42 | return this.animatable; 43 | } 44 | 45 | @ApiStatus.Internal 46 | @Override 47 | public R getRenderState() { 48 | return this.renderState; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /fabric/src/main/java/software/bernie/geckolib/platform/GeckoLibFabric.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.platform; 2 | 3 | import net.fabricmc.api.EnvType; 4 | import net.fabricmc.loader.api.FabricLoader; 5 | import net.minecraft.core.Registry; 6 | import net.minecraft.core.component.DataComponentType; 7 | import net.minecraft.core.registries.BuiltInRegistries; 8 | import software.bernie.geckolib.GeckoLibConstants; 9 | import software.bernie.geckolib.service.GeckoLibPlatform; 10 | 11 | import java.nio.file.Path; 12 | import java.util.function.Supplier; 13 | import java.util.function.UnaryOperator; 14 | 15 | /** 16 | * Fabric service for general loader-specific functions 17 | */ 18 | public final class GeckoLibFabric implements GeckoLibPlatform { 19 | /** 20 | * @return Whether the current runtime is an in-dev (non-production) environment, for running debug-only tasks 21 | */ 22 | @Override 23 | public boolean isDevelopmentEnvironment() { 24 | return FabricLoader.getInstance().isDevelopmentEnvironment(); 25 | } 26 | 27 | /** 28 | * @return The root game directory (./run) 29 | */ 30 | @Override 31 | public Path getGameDir() { 32 | return FabricLoader.getInstance().getGameDir(); 33 | } 34 | 35 | /** 36 | * @return Whether the current runtime is on the client side regardless of logical context 37 | */ 38 | @Override 39 | public boolean isPhysicalClient() { 40 | return FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT; 41 | } 42 | 43 | /** 44 | * Register a {@link DataComponentType} 45 | *

46 | * This is mostly just used for storing the animatable ID on ItemStacks 47 | */ 48 | @Override 49 | public Supplier> registerDataComponent(String id, UnaryOperator> builder) { 50 | final DataComponentType componentType = Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, GeckoLibConstants.id(id).toString(), builder.apply(DataComponentType.builder()).build()); 51 | 52 | return () -> componentType; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /forge/src/main/java/software/bernie/geckolib/event/armor/CompileArmorRenderStateEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.armor; 2 | 3 | import net.minecraft.client.renderer.entity.state.HumanoidRenderState; 4 | import net.minecraft.world.item.Item; 5 | import net.minecraftforge.eventbus.api.bus.EventBus; 6 | import net.minecraftforge.eventbus.api.event.RecordEvent; 7 | import org.jetbrains.annotations.ApiStatus; 8 | import software.bernie.geckolib.animatable.GeoItem; 9 | import software.bernie.geckolib.event.GeoRenderEvent; 10 | import software.bernie.geckolib.renderer.GeoArmorRenderer; 11 | import software.bernie.geckolib.renderer.base.GeoRenderState; 12 | 13 | /** 14 | * Pre-render event for armor pieces being rendered by {@link GeoArmorRenderer} 15 | *

16 | * This event is called in preparation for rendering, when the renderer is gathering data to pass through 17 | *

18 | * Use this event to add data that you may need in a later {@link Armor} event, or to override/replace data used in rendering 19 | *

20 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 21 | * 22 | * @see GeoRenderEvent 23 | * @see CompileRenderState 24 | */ 25 | public record CompileArmorRenderStateEvent 26 | (GeoArmorRenderer renderer, R renderState, T animatable, GeoArmorRenderer.RenderData renderData) 27 | implements GeoRenderEvent.Armor.CompileRenderState, RecordEvent { 28 | public static final EventBus BUS = EventBus.create(CompileArmorRenderStateEvent.class); 29 | 30 | @Override 31 | public GeoArmorRenderer getRenderer() { 32 | return this.renderer; 33 | } 34 | 35 | @Override 36 | public T getAnimatable() { 37 | return this.animatable; 38 | } 39 | 40 | @ApiStatus.Internal 41 | @Override 42 | public R getRenderState() { 43 | return this.renderState; 44 | } 45 | 46 | @Override 47 | public GeoArmorRenderer.RenderData getRenderData() { 48 | return this.renderData; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/math/value/Variable.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.math.value; 2 | 3 | import software.bernie.geckolib.GeckoLibConstants; 4 | import software.bernie.geckolib.animation.state.ControllerState; 5 | import software.bernie.geckolib.loading.math.MathValue; 6 | 7 | import java.util.Set; 8 | import java.util.concurrent.atomic.AtomicReference; 9 | import java.util.function.ToDoubleFunction; 10 | 11 | /** 12 | * {@link MathValue} value supplier 13 | * 14 | *

15 | * Contract: 16 | *
17 | * Returns the currently stored value, which may be modified at any given time via {@link #set}. Values may be lazily evaluated to eliminate wasteful usage 18 | */ 19 | public record Variable(String name, AtomicReference> value) implements MathValue { 20 | public Variable(String name, double value) { 21 | this(name, animationState -> value); 22 | } 23 | 24 | public Variable(String name, ToDoubleFunction value) { 25 | this(name, new AtomicReference<>(value)); 26 | } 27 | 28 | @Override 29 | public double get(ControllerState controllerState) { 30 | try { 31 | return this.value.get().applyAsDouble(controllerState); 32 | } 33 | catch (Exception ex) { 34 | GeckoLibConstants.LOGGER.error("Attempted to use Molang variable for incompatible animatable type (" + this.name + "). An animation json needs to be fixed", ex.getMessage()); 35 | 36 | return 0; 37 | } 38 | } 39 | 40 | public void set(final double value) { 41 | this.value.set(controllerState -> value); 42 | } 43 | 44 | public void set(final ToDoubleFunction value) { 45 | this.value.set(value); 46 | } 47 | 48 | @Override 49 | public Set getUsedVariables() { 50 | return Set.of(this); 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | return "variable(" + this.name + ")"; 56 | } 57 | 58 | @Override 59 | public int hashCode() { 60 | return this.name.hashCode(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/loading/json/raw/PolysUnion.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.loading.json.raw; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonDeserializer; 5 | import com.google.gson.JsonParseException; 6 | import com.google.gson.annotations.SerializedName; 7 | import org.jspecify.annotations.Nullable; 8 | import software.bernie.geckolib.util.JsonUtil; 9 | 10 | /** 11 | * Container class for poly union information, only used in deserialization at startup 12 | */ 13 | public record PolysUnion(double[][][] union, @Nullable Type type) { 14 | public static JsonDeserializer deserializer() throws JsonParseException { 15 | return (json, type, context) -> { 16 | if (json.isJsonPrimitive() && json.getAsJsonPrimitive().isString()) { 17 | return new PolysUnion(new double[0][0][0], context.deserialize(json.getAsJsonPrimitive(), Type.class)); 18 | } 19 | else if (json.isJsonArray()) { 20 | JsonArray array = json.getAsJsonArray(); 21 | double[][][] matrix = makeSizedMatrix(array); 22 | 23 | for (int x = 0; x < array.size(); x++) { 24 | JsonArray xArray = array.get(x).getAsJsonArray(); 25 | 26 | for (int y = 0; y < xArray.size(); y++) { 27 | JsonArray yArray = xArray.get(y).getAsJsonArray(); 28 | 29 | matrix[x][y] = JsonUtil.jsonArrayToDoubleArray(yArray); 30 | } 31 | } 32 | 33 | return new PolysUnion(matrix, null); 34 | } 35 | else { 36 | throw new JsonParseException("Invalid format for PolysUnion, must be either string or array"); 37 | } 38 | }; 39 | } 40 | 41 | private static double[][][] makeSizedMatrix(JsonArray array) { 42 | JsonArray subArray = array.size() > 0 ? array.get(0).getAsJsonArray() : null; 43 | JsonArray subSubArray = subArray != null && subArray.size() > 0 ? subArray.get(0).getAsJsonArray() : null; 44 | int ySize = subArray != null ? subArray.size() : 0; 45 | int zSize = subSubArray != null ? subSubArray.size() : 0; 46 | 47 | return new double[array.size()][ySize][zSize]; 48 | } 49 | 50 | public enum Type { 51 | @SerializedName(value = "quad_list") QUAD, 52 | @SerializedName(value = "tri_list") TRI; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/network/packet/blockentity/StopTriggeredBlockEntityAnimPacket.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.network.packet.blockentity; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.network.FriendlyByteBuf; 5 | import net.minecraft.network.codec.ByteBufCodecs; 6 | import net.minecraft.network.codec.StreamCodec; 7 | import net.minecraft.network.protocol.common.custom.CustomPacketPayload; 8 | import net.minecraft.world.entity.player.Player; 9 | import org.jspecify.annotations.Nullable; 10 | import software.bernie.geckolib.GeckoLibConstants; 11 | import software.bernie.geckolib.animatable.GeoBlockEntity; 12 | import software.bernie.geckolib.network.packet.MultiloaderPacket; 13 | import software.bernie.geckolib.util.ClientUtil; 14 | 15 | import java.util.Optional; 16 | import java.util.function.Consumer; 17 | 18 | public record StopTriggeredBlockEntityAnimPacket(BlockPos pos, Optional controllerName, Optional animName) implements MultiloaderPacket { 19 | public static final Type TYPE = new Type<>(GeckoLibConstants.id("stop_triggered_blockentity_anim")); 20 | public static final StreamCodec CODEC = StreamCodec.composite( 21 | BlockPos.STREAM_CODEC, StopTriggeredBlockEntityAnimPacket::pos, 22 | ByteBufCodecs.STRING_UTF8.apply(ByteBufCodecs::optional), StopTriggeredBlockEntityAnimPacket::controllerName, 23 | ByteBufCodecs.STRING_UTF8.apply(ByteBufCodecs::optional), StopTriggeredBlockEntityAnimPacket::animName, 24 | StopTriggeredBlockEntityAnimPacket::new); 25 | 26 | @Override 27 | public Type type() { 28 | return TYPE; 29 | } 30 | 31 | @Override 32 | public void receiveMessage(@Nullable Player sender, Consumer workQueue) { 33 | workQueue.accept(() -> { 34 | if (ClientUtil.getLevel().getBlockEntity(this.pos) instanceof GeoBlockEntity blockEntity) 35 | blockEntity.stopTriggeredAnim(this.controllerName.orElse(null), this.animName.orElse(null)); 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/animatable/stateless/StatelessGeoBlockEntity.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.animatable.stateless; 2 | 3 | import net.minecraft.server.level.ServerLevel; 4 | import net.minecraft.world.level.block.entity.BlockEntity; 5 | import software.bernie.geckolib.GeckoLibServices; 6 | import software.bernie.geckolib.animatable.GeoBlockEntity; 7 | import software.bernie.geckolib.animation.RawAnimation; 8 | import software.bernie.geckolib.network.packet.blockentity.StatelessBlockEntityPlayAnimPacket; 9 | import software.bernie.geckolib.network.packet.blockentity.StatelessBlockEntityStopAnimPacket; 10 | 11 | /** 12 | * Extension of {@link StatelessAnimatable} for {@link GeoBlockEntity} animatables 13 | */ 14 | public non-sealed interface StatelessGeoBlockEntity extends StatelessAnimatable, GeoBlockEntity { 15 | /** 16 | * Start or continue a pre-defined animation 17 | */ 18 | @Override 19 | default void playAnimation(RawAnimation animation) { 20 | if (!(this instanceof BlockEntity self)) 21 | throw new ClassCastException("Cannot use StatelessGeoBlockEntity on a non-blockentity animatable!"); 22 | 23 | if (self.getLevel() instanceof ServerLevel level) { 24 | GeckoLibServices.NETWORK.sendToAllPlayersTrackingBlock(new StatelessBlockEntityPlayAnimPacket(self.getBlockPos(), animation), level, self.getBlockPos()); 25 | } 26 | else { 27 | handleClientAnimationPlay(this, 0, animation); 28 | } 29 | } 30 | 31 | /** 32 | * Stop an already-playing animation 33 | */ 34 | @Override 35 | default void stopAnimation(String animation) { 36 | if (!(this instanceof BlockEntity self)) 37 | throw new ClassCastException("Cannot use StatelessGeoBlockEntity on a non-blockentity animatable!"); 38 | 39 | if (self.getLevel() instanceof ServerLevel level) { 40 | GeckoLibServices.NETWORK.sendToAllPlayersTrackingBlock(new StatelessBlockEntityStopAnimPacket(self.getBlockPos(), animation), level, self.getBlockPos()); 41 | } 42 | else { 43 | handleClientAnimationStop(this, 0, animation); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/network/packet/blockentity/BlockEntityDataSyncPacket.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.network.packet.blockentity; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.network.RegistryFriendlyByteBuf; 5 | import net.minecraft.network.codec.StreamCodec; 6 | import net.minecraft.network.protocol.common.custom.CustomPacketPayload; 7 | import net.minecraft.world.entity.player.Player; 8 | import org.jspecify.annotations.Nullable; 9 | import software.bernie.geckolib.GeckoLibConstants; 10 | import software.bernie.geckolib.animatable.GeoBlockEntity; 11 | import software.bernie.geckolib.constant.dataticket.SerializableDataTicket; 12 | import software.bernie.geckolib.network.packet.MultiloaderPacket; 13 | import software.bernie.geckolib.util.ClientUtil; 14 | 15 | import java.util.function.Consumer; 16 | 17 | public record BlockEntityDataSyncPacket(BlockPos pos, SerializableDataTicket dataTicket, D data) implements MultiloaderPacket { 18 | public static final CustomPacketPayload.Type> TYPE = new Type<>(GeckoLibConstants.id("blockentity_data_sync")); 19 | public static final StreamCodec> CODEC = StreamCodec.of((buf, packet) -> { 20 | SerializableDataTicket.STREAM_CODEC.encode(buf, packet.dataTicket); 21 | buf.writeBlockPos(packet.pos); 22 | ((StreamCodec)packet.dataTicket.streamCodec()).encode(buf, packet.data); 23 | }, buf -> { 24 | final SerializableDataTicket dataTicket = SerializableDataTicket.STREAM_CODEC.decode(buf); 25 | 26 | return new BlockEntityDataSyncPacket<>(buf.readBlockPos(), dataTicket, dataTicket.streamCodec().decode(buf)); 27 | }); 28 | 29 | @Override 30 | public Type type() { 31 | return TYPE; 32 | } 33 | 34 | @Override 35 | public void receiveMessage(@Nullable Player sender, Consumer workQueue) { 36 | workQueue.accept(() -> { 37 | if (ClientUtil.getLevel().getBlockEntity(this.pos) instanceof GeoBlockEntity blockEntity) 38 | blockEntity.setAnimData(this.dataTicket, this.data); 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/network/packet/singleton/StatelessSingletonStopAnimPacket.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.network.packet.singleton; 2 | 3 | import net.minecraft.network.FriendlyByteBuf; 4 | import net.minecraft.network.codec.ByteBufCodecs; 5 | import net.minecraft.network.codec.StreamCodec; 6 | import net.minecraft.network.protocol.common.custom.CustomPacketPayload; 7 | import net.minecraft.world.entity.player.Player; 8 | import org.jspecify.annotations.Nullable; 9 | import software.bernie.geckolib.GeckoLibConstants; 10 | import software.bernie.geckolib.animatable.GeoAnimatable; 11 | import software.bernie.geckolib.animatable.stateless.StatelessGeoSingletonAnimatable; 12 | import software.bernie.geckolib.cache.SyncedSingletonAnimatableCache; 13 | import software.bernie.geckolib.network.packet.MultiloaderPacket; 14 | 15 | import java.util.function.Consumer; 16 | 17 | public record StatelessSingletonStopAnimPacket(String syncableId, long instanceId, String animation) implements MultiloaderPacket { 18 | public static final Type TYPE = new Type<>(GeckoLibConstants.id("stateless_singleton_stop_anim")); 19 | public static final StreamCodec CODEC = StreamCodec.composite( 20 | ByteBufCodecs.STRING_UTF8, StatelessSingletonStopAnimPacket::syncableId, 21 | ByteBufCodecs.VAR_LONG, StatelessSingletonStopAnimPacket::instanceId, 22 | ByteBufCodecs.STRING_UTF8, StatelessSingletonStopAnimPacket::animation, 23 | StatelessSingletonStopAnimPacket::new); 24 | 25 | @Override 26 | public Type type() { 27 | return TYPE; 28 | } 29 | 30 | @Override 31 | public void receiveMessage(@Nullable Player sender, Consumer workQueue) { 32 | workQueue.accept(() -> { 33 | GeoAnimatable animatable = SyncedSingletonAnimatableCache.getSyncedAnimatable(this.syncableId); 34 | 35 | if (animatable instanceof StatelessGeoSingletonAnimatable statelessAnimatable) 36 | statelessAnimatable.handleClientAnimationStop(animatable, this.instanceId, this.animation); 37 | }); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/event/item/CompileItemRenderStateEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.item; 2 | 3 | import net.minecraft.world.item.Item; 4 | import net.neoforged.bus.api.Event; 5 | import org.jetbrains.annotations.ApiStatus; 6 | import software.bernie.geckolib.animatable.GeoAnimatable; 7 | import software.bernie.geckolib.event.GeoRenderEvent; 8 | import software.bernie.geckolib.renderer.GeoItemRenderer; 9 | import software.bernie.geckolib.renderer.base.GeoRenderState; 10 | 11 | /** 12 | * Pre-render event for items being rendered by {@link GeoItemRenderer} 13 | *

14 | * This event is called in preparation for rendering, when the renderer is gathering data to pass through 15 | *

16 | * Use this event to add data that you may need in a later {@link Item} event, or to override/replace data used in rendering 17 | *

18 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 19 | * 20 | * @see GeoRenderEvent 21 | * @see CompileRenderState 22 | */ 23 | public class CompileItemRenderStateEvent extends Event implements GeoRenderEvent.Item.CompileRenderState { 24 | private final GeoItemRenderer renderer; 25 | private final GeoRenderState renderState; 26 | private final T animatable; 27 | private final GeoItemRenderer.RenderData renderData; 28 | 29 | public CompileItemRenderStateEvent(GeoItemRenderer renderer, GeoRenderState renderState, T animatable, GeoItemRenderer.RenderData renderData) { 30 | this.renderer = renderer; 31 | this.renderState = renderState; 32 | this.animatable = animatable; 33 | this.renderData = renderData; 34 | } 35 | 36 | @Override 37 | public GeoItemRenderer getRenderer() { 38 | return this.renderer; 39 | } 40 | 41 | @Override 42 | public T getAnimatable() { 43 | return this.animatable; 44 | } 45 | 46 | @Override 47 | public GeoItemRenderer.RenderData getRenderData() { 48 | return this.renderData; 49 | } 50 | 51 | @ApiStatus.Internal 52 | @Override 53 | public GeoRenderState getRenderState() { 54 | return this.renderState; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /neoforge/src/main/java/software/bernie/geckolib/event/object/CompileObjectRenderStateEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.object; 2 | 3 | import net.neoforged.bus.api.Event; 4 | import org.jetbrains.annotations.ApiStatus; 5 | import org.jspecify.annotations.Nullable; 6 | import software.bernie.geckolib.animatable.GeoAnimatable; 7 | import software.bernie.geckolib.event.GeoRenderEvent; 8 | import software.bernie.geckolib.renderer.GeoObjectRenderer; 9 | import software.bernie.geckolib.renderer.base.GeoRenderState; 10 | 11 | /** 12 | * Pre-render event for objects being rendered by {@link GeoObjectRenderer} 13 | *

14 | * This event is called in preparation for rendering, when the renderer is gathering data to pass through 15 | *

16 | * Use this event to add data that you may need in a later {@link Object} event, or to override/replace data used in rendering 17 | *

18 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 19 | * 20 | * @see GeoRenderEvent 21 | * @see CompileRenderState 22 | */ 23 | public class CompileObjectRenderStateEvent extends Event implements GeoRenderEvent.Object.CompileRenderState { 24 | private final GeoObjectRenderer renderer; 25 | private final R renderState; 26 | private final T animatable; 27 | private final @Nullable E relatedObject; 28 | 29 | public CompileObjectRenderStateEvent(GeoObjectRenderer renderer, R renderState, T animatable, @Nullable E relatedObject) { 30 | this.renderer = renderer; 31 | this.renderState = renderState; 32 | this.animatable = animatable; 33 | this.relatedObject = relatedObject; 34 | } 35 | 36 | @Override 37 | public GeoObjectRenderer getRenderer() { 38 | return this.renderer; 39 | } 40 | 41 | @Override 42 | public T getAnimatable() { 43 | return this.animatable; 44 | } 45 | 46 | @ApiStatus.Internal 47 | @Override 48 | public R getRenderState() { 49 | return this.renderState; 50 | } 51 | 52 | @Override 53 | public @Nullable E getRelatedObject() { 54 | return this.relatedObject; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /fabric/src/main/java/software/bernie/geckolib/event/object/CompileObjectRenderLayersEvent.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.event.object; 2 | 3 | import net.fabricmc.fabric.api.event.Event; 4 | import net.fabricmc.fabric.api.event.EventFactory; 5 | import software.bernie.geckolib.animatable.GeoAnimatable; 6 | import software.bernie.geckolib.event.GeoRenderEvent; 7 | import software.bernie.geckolib.renderer.GeoObjectRenderer; 8 | import software.bernie.geckolib.renderer.base.GeoRenderState; 9 | 10 | /** 11 | * One-time event for a {@link GeoObjectRenderer} called on first initialisation 12 | *

13 | * Use this event to add render layers to the renderer as needed 14 | *

15 | * NOTE: Some methods on this event are not overridden in this class. Check {@link GeoRenderEvent} 16 | * 17 | * @param Object animatable class type 18 | * @param Associated object class type, or {@link Void} if none 19 | * @param RenderState class type 20 | * @see GeoRenderEvent 21 | * @see CompileRenderLayers 22 | */ 23 | public class CompileObjectRenderLayersEvent implements GeoRenderEvent.Object.CompileRenderLayers { 24 | public static final Event EVENT = EventFactory.createArrayBacked(Listener.class, post -> {}, listeners -> event -> { 25 | for (Listener listener : listeners) { 26 | listener.handle(event); 27 | } 28 | }); 29 | private final GeoObjectRenderer renderer; 30 | 31 | public CompileObjectRenderLayersEvent(GeoObjectRenderer renderer) { 32 | this.renderer = renderer; 33 | } 34 | 35 | @Override 36 | public GeoObjectRenderer getRenderer() { 37 | return this.renderer; 38 | } 39 | 40 | /** 41 | * Event listener interface for the {@link Object.CompileRenderLayers} GeoRenderEvent 42 | * 43 | * @param Object animatable class type 44 | * @param Associated object class type, or {@link Void} if none 45 | * @param RenderState class type 46 | */ 47 | @FunctionalInterface 48 | public interface Listener { 49 | void handle(CompileObjectRenderLayersEvent event); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /common/src/main/java/software/bernie/geckolib/network/packet/singleton/StatelessSingletonPlayAnimPacket.java: -------------------------------------------------------------------------------- 1 | package software.bernie.geckolib.network.packet.singleton; 2 | 3 | import net.minecraft.network.FriendlyByteBuf; 4 | import net.minecraft.network.codec.ByteBufCodecs; 5 | import net.minecraft.network.codec.StreamCodec; 6 | import net.minecraft.network.protocol.common.custom.CustomPacketPayload; 7 | import net.minecraft.world.entity.player.Player; 8 | import org.jspecify.annotations.Nullable; 9 | import software.bernie.geckolib.GeckoLibConstants; 10 | import software.bernie.geckolib.animatable.GeoAnimatable; 11 | import software.bernie.geckolib.animatable.stateless.StatelessGeoSingletonAnimatable; 12 | import software.bernie.geckolib.animation.RawAnimation; 13 | import software.bernie.geckolib.cache.SyncedSingletonAnimatableCache; 14 | import software.bernie.geckolib.network.packet.MultiloaderPacket; 15 | 16 | import java.util.function.Consumer; 17 | 18 | public record StatelessSingletonPlayAnimPacket(String syncableId, long instanceId, RawAnimation animation) implements MultiloaderPacket { 19 | public static final Type TYPE = new Type<>(GeckoLibConstants.id("stateless_singleton_play_anim")); 20 | public static final StreamCodec CODEC = StreamCodec.composite( 21 | ByteBufCodecs.STRING_UTF8, StatelessSingletonPlayAnimPacket::syncableId, 22 | ByteBufCodecs.VAR_LONG, StatelessSingletonPlayAnimPacket::instanceId, 23 | RawAnimation.STREAM_CODEC, StatelessSingletonPlayAnimPacket::animation, 24 | StatelessSingletonPlayAnimPacket::new); 25 | 26 | @Override 27 | public Type type() { 28 | return TYPE; 29 | } 30 | 31 | @Override 32 | public void receiveMessage(@Nullable Player sender, Consumer workQueue) { 33 | workQueue.accept(() -> { 34 | GeoAnimatable animatable = SyncedSingletonAnimatableCache.getSyncedAnimatable(this.syncableId); 35 | 36 | if (animatable instanceof StatelessGeoSingletonAnimatable statelessAnimatable) 37 | statelessAnimatable.handleClientAnimationPlay(animatable, this.instanceId, this.animation); 38 | }); 39 | } 40 | } 41 | --------------------------------------------------------------------------------