diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 79d7d565..85211da9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,161 +9,62 @@ on: required: true jobs: - build: + publish: runs-on: ubuntu-latest steps: - name: Checkout Branch - uses: actions/checkout@v3 - - - name: Get Artifact Id - uses: actions/github-script@v5 - env: - branch: ${{ github.head_ref || github.ref_name }} - id: artifact_id - with: - result-encoding: string - script: | - // use env branch replace / with _ - return process.env.branch.replace(/\//g, '_') + uses: actions/checkout@v4 - name: Setup Java uses: actions/setup-java@v4 with: distribution: 'adopt' - java-version: 21 + java-version: 25 - name: Grant Execute Permission run: chmod +x gradlew - name: Build - run: | - ./gradlew build - - - name: Upload To Artifacts - uses: actions/upload-artifact@v4 - with: - name: ${{ steps.artifact_id.outputs.result }} - path: | - ./dist/**/* - ./minecraft/fabric/build/libs - ./minecraft/neoforge/build/libs - ./gradle.properties - - deploy: - runs-on: ubuntu-latest - needs: - - build - steps: - - name: Checkout Branch - uses: actions/checkout@v3 - - - name: Setup Java - uses: actions/setup-java@v4 - with: - distribution: 'adopt' - java-version: 21 - - - name: Get Artifact Id - uses: actions/github-script@v5 - env: - branch: ${{ github.head_ref || github.ref_name }} - id: artifact_id - with: - result-encoding: string - script: | - // use env branch replace / with _ - return process.env.branch.replace(/\//g, '_') - - - name: Download Artifacts - uses: actions/download-artifact@v4 - with: - name: ${{ steps.artifact_id.outputs.result }} + run: ./gradlew build - name: Load Gradle Properties uses: christian-draeger/read-properties@1.1.1 id: gradle_properties with: path: './gradle.properties' - properties: 'java_version minecraft_version mod_version' + properties: 'minecraft_version mod_version' - - name: Check For Fabric Jar - uses: actions/github-script@v5 - id: fabric_release - with: - result-encoding: string - script: | - const fs = require("fs") - return fs.readdirSync("./minecraft/fabric/build/libs")[0] || false; - - - name: Check For Forge Jar - uses: actions/github-script@v5 - id: forge_release - with: - result-encoding: string - script: | - const fs = require("fs") - return fs.readdirSync("./minecraft/neoforge/build/libs")[0] || false; - - - name: Run Publish Fabric - if: ${{ steps.fabric_release.outputs.result != 'false' }} - id: publish_fabric + - name: Run Publish + id: publish_merged uses: Kir-Antipov/mc-publish@v3.3 with: modrinth-id: ha1mEyJS modrinth-token: ${{ secrets.MODRINTH_TOKEN }} - modrinth-featured: false + modrinth-featured: true modrinth-unfeature-mode: any - curseforge-id: 1283899 - curseforge-token: ${{ secrets.CURSEFORGE_TOKEN }} - - name: ${{ steps.gradle_properties.outputs.mod_version }}+${{ steps.gradle_properties.outputs.minecraft_version }}-Fabric - version: ${{ steps.gradle_properties.outputs.mod_version }} - - files: | - ./minecraft/fabric/build/libs/!(*-@(dev|sources|javadoc|all|dev-shadow)).jar - ./minecraft/fabric/build/libs/*-@(dev|sources|javadoc|all|dev-shadow).jar - version-type: release - - loaders: fabric - game-versions: | - ${{ steps.gradle_properties.outputs.minecraft_version }} - - changelog-file: CHANGELOG.md - - java: ${{ steps.gradle_properties.outputs.java_version }} - retry-attempts: 5 - retry-delay: 60000 - fail-mode: skip - - - name: Run Publish Forge - if: ${{ steps.forge_release.outputs.result != 'false' }} - id: publish_forge - uses: Kir-Antipov/mc-publish@v3.3 - with: - modrinth-id: ha1mEyJS - modrinth-token: ${{ secrets.MODRINTH_TOKEN }} - modrinth-featured: false - modrinth-unfeature-mode: any + github-tag: v${{ steps.gradle_properties.outputs.mod_version }}+${{ steps.gradle_properties.outputs.minecraft_version }} + github-token: ${{ secrets.GITHUB_TOKEN }} curseforge-id: 1283899 curseforge-token: ${{ secrets.CURSEFORGE_TOKEN }} - name: ${{ steps.gradle_properties.outputs.mod_version }}+${{ steps.gradle_properties.outputs.minecraft_version }}-NeoForge + name: ${{ steps.gradle_properties.outputs.mod_version }}+${{ steps.gradle_properties.outputs.minecraft_version }} version: ${{ steps.gradle_properties.outputs.mod_version }} files: | - ./minecraft/neoforge/build/libs/!(*-@(dev|sources|javadoc|all|dev-shadow)).jar - ./minecraft/neoforge/build/libs/*-@(dev|sources|javadoc|all|dev-shadow).jar + ./minecraft/build/libs/PlayerAnimationLibMerged-*.jar version-type: release - loaders: neoforge + loaders: | + fabric + neoforge game-versions: | ${{ steps.gradle_properties.outputs.minecraft_version }} changelog-file: CHANGELOG.md - java: ${{ steps.gradle_properties.outputs.java_version }} + java: 25 retry-attempts: 5 retry-delay: 60000 fail-mode: skip @@ -174,22 +75,11 @@ jobs: { echo 'P2D_LINKS<>() {}.getType(); public static final Gson GSON = new GsonBuilder() + .registerTypeAdapter(CustomModelBone.class, new CustomModelBone.Deserializer()) + .registerTypeAdapter(DecodedImage.class, new CustomModelBone.ImageDeserializer()) + .registerTypeAdapter(Vec3f.class, new Vec3f.Deserializer()) .registerTypeAdapter(Animation.Keyframes.class, new KeyFrameLoader()) .registerTypeAdapter(Animation.class, new AnimationLoader()) .registerTypeAdapter(ANIMATIONS_MAP_TYPE, new UniversalAnimLoader()) .disableHtmlEscaping() .create(); + + static { + PlayerAnimLib.LOGGER.info(WebPDiagnostics.summary()); + } } diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/Animation.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/Animation.java index 12411667..820e039f 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/Animation.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/Animation.java @@ -30,9 +30,7 @@ import com.zigythebird.playeranimcore.animation.keyframe.event.data.CustomInstructionKeyframeData; import com.zigythebird.playeranimcore.animation.keyframe.event.data.ParticleKeyframeData; import com.zigythebird.playeranimcore.animation.keyframe.event.data.SoundKeyframeData; -import com.zigythebird.playeranimcore.enums.AnimationStage; import com.zigythebird.playeranimcore.loading.UniversalAnimLoader; -import com.zigythebird.playeranimcore.math.Vec3f; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -45,7 +43,7 @@ *

* Modifications or extensions of a compiled Animation are not supported, and therefore an instance of Animation is considered final and immutable */ -public record Animation(ExtraAnimationData data, float length, LoopType loopType, Map boneAnimations, Keyframes keyFrames, Map bones, Map parents) implements Supplier { +public record Animation(ExtraAnimationData data, float length, LoopType loopType, Map boneAnimations, Keyframes keyFrames, Map bones, Map parents) implements Supplier { public record Keyframes(SoundKeyframeData[] sounds, ParticleKeyframeData[] particles, CustomInstructionKeyframeData[] customInstructions) { @Override public int hashCode() { @@ -54,7 +52,7 @@ public int hashCode() { } static Animation generateWaitAnimation(float length) { - return new Animation(new ExtraAnimationData(ExtraAnimationData.NAME_KEY, AnimationStage.WAIT.name()), length, LoopType.PLAY_ONCE, + return new Animation(new ExtraAnimationData(ExtraAnimationData.NAME_KEY, "internal.wait"), length, LoopType.PLAY_ONCE, Collections.emptyMap(), UniversalAnimLoader.NO_KEYFRAMES, new HashMap<>(), new HashMap<>()); } diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java index dba4b0be..34d00f81 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/AnimationController.java @@ -24,6 +24,7 @@ package com.zigythebird.playeranimcore.animation; +import com.google.gson.JsonArray; import com.zigythebird.playeranimcore.PlayerAnimLib; import com.zigythebird.playeranimcore.animation.keyframe.*; import com.zigythebird.playeranimcore.animation.keyframe.event.CustomKeyFrameEvents; @@ -39,9 +40,9 @@ import com.zigythebird.playeranimcore.animation.layered.modifier.SpeedModifier; import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonConfiguration; import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonMode; +import com.zigythebird.playeranimcore.bindings.PlatformModel; import com.zigythebird.playeranimcore.bones.*; import com.zigythebird.playeranimcore.easing.EasingType; -import com.zigythebird.playeranimcore.enums.AnimationStage; import com.zigythebird.playeranimcore.enums.PlayState; import com.zigythebird.playeranimcore.enums.State; import com.zigythebird.playeranimcore.enums.TransformType; @@ -54,6 +55,7 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.redlance.platformtools.webp.decoder.DecodedImage; import team.unnamed.mocha.MochaEngine; import team.unnamed.mocha.parser.ast.FloatExpression; @@ -69,14 +71,14 @@ * one to control attacks, one to control size, etc. */ public abstract class AnimationController implements IAnimation { - public static KeyframeLocation EMPTY_KEYFRAME_LOCATION = new KeyframeLocation<>(new Keyframe(0), 0); - public static KeyframeLocation EMPTY_SCALE_KEYFRAME_LOCATION = new KeyframeLocation<>(new Keyframe(0, Collections.singletonList(FloatExpression.ONE), Collections.singletonList(FloatExpression.ONE)), 0); + public static KeyframeLocation EMPTY_KEYFRAME_LOCATION = new KeyframeLocation(new Keyframe(0), 0); + public static KeyframeLocation EMPTY_SCALE_KEYFRAME_LOCATION = new KeyframeLocation(new Keyframe(0, Collections.singletonList(FloatExpression.ONE), Collections.singletonList(FloatExpression.ONE)), 0); protected final AnimationStateHandler stateHandler; protected final Map bonePositions; protected final Map bones = new Object2ObjectOpenHashMap<>(); protected final Map activeBones = new Object2ObjectOpenHashMap<>(); - protected final Map pivotBones = new Object2ObjectOpenHashMap<>(); + protected final Map pivotBones = new Object2ObjectOpenHashMap<>(); protected Queue animationQueue = new LinkedList<>(); protected final MochaEngine molangRuntime; @@ -364,13 +366,7 @@ protected void setAnimation(RawAnimation rawAnimation) { protected Queue getQueuedAnimations(RawAnimation rawAnimation) { LinkedList animations = new LinkedList<>(); for (RawAnimation.Stage stage : rawAnimation.getAnimationStages()) { - Animation animation; - if (stage.stage() == AnimationStage.WAIT) { // This is intentional. Do not change this or T̶s̶l̶a̶t̶ I will be unhappy!!! - animation = Animation.generateWaitAnimation(stage.additionalTicks()); - } else { - animation = stage.animation(); - } - + Animation animation = stage.animation(); if (animation != null) animations.add(new QueuedAnimation(animation, stage.loopType())); } return animations; @@ -415,9 +411,9 @@ public void triggerAnimation(Animation newAnimation) { public void replaceAnimationWithFade(@NotNull AbstractFadeModifier fadeModifier, @Nullable RawAnimation newAnimation, boolean fadeFromNothing) { if (fadeFromNothing || this.isActive()) { if (this.isActive()) { - Map snapshots = new HashMap<>(); + Map snapshots = new HashMap<>(); for (PlayerAnimBone bone : activeBones.values()) { - snapshots.put(bone.getName(), new AdvancedBoneSnapshot(bone)); + snapshots.put(bone.getName(), new ToggleablePlayerAnimBone(bone)); } fadeModifier.setTransitionAnimation(new AnimationSnapshot(snapshots)); } @@ -584,33 +580,19 @@ private void processCurrentAnimation(float adjustedTick, AnimationData animation KeyframeStack rotationKeyFrames = boneAnimation.rotationKeyFrames(); KeyframeStack positionKeyFrames = boneAnimation.positionKeyFrames(); KeyframeStack scaleKeyFrames = boneAnimation.scaleKeyFrames(); - List bendKeyFrames = boneAnimation.bendKeyFrames(); - - AnimationPoint rotXPoint = getAnimationPointAtTick(rotationKeyFrames.xKeyframes(), adjustedTick, TransformType.ROTATION, isAdvancedBone ? advancedBone::setRotXTransitionLength : null); - AnimationPoint rotYPoint = getAnimationPointAtTick(rotationKeyFrames.yKeyframes(), adjustedTick, TransformType.ROTATION, isAdvancedBone ? advancedBone::setRotYTransitionLength : null); - AnimationPoint rotZPoint = getAnimationPointAtTick(rotationKeyFrames.zKeyframes(), adjustedTick, TransformType.ROTATION, isAdvancedBone ? advancedBone::setRotZTransitionLength : null); - AnimationPoint posXPoint = getAnimationPointAtTick(positionKeyFrames.xKeyframes(), adjustedTick, TransformType.POSITION, isAdvancedBone ? advancedBone::setPositionXTransitionLength : null); - AnimationPoint posYPoint = getAnimationPointAtTick(positionKeyFrames.yKeyframes(), adjustedTick, TransformType.POSITION, isAdvancedBone ? advancedBone::setPositionYTransitionLength : null); - AnimationPoint posZPoint = getAnimationPointAtTick(positionKeyFrames.zKeyframes(), adjustedTick, TransformType.POSITION, isAdvancedBone ? advancedBone::setPositionZTransitionLength : null); - AnimationPoint scaleXPoint = getAnimationPointAtTick(scaleKeyFrames.xKeyframes(), adjustedTick, TransformType.SCALE, isAdvancedBone ? advancedBone::setScaleXTransitionLength : null); - AnimationPoint scaleYPoint = getAnimationPointAtTick(scaleKeyFrames.yKeyframes(), adjustedTick, TransformType.SCALE, isAdvancedBone ? advancedBone::setScaleYTransitionLength : null); - AnimationPoint scaleZPoint = getAnimationPointAtTick(scaleKeyFrames.zKeyframes(), adjustedTick, TransformType.SCALE, isAdvancedBone ? advancedBone::setScaleZTransitionLength : null); - AnimationPoint bendPoint = getAnimationPointAtTick(bendKeyFrames, adjustedTick, TransformType.BEND, isAdvancedBone ? advancedBone::setBendTransitionLength : null); - EasingType easingType = this.overrideEasingTypeFunction.apply(this); - - bone.setRotX(EasingType.lerpWithOverride(this.molangRuntime, rotXPoint, easingType)); - bone.setRotY(EasingType.lerpWithOverride(this.molangRuntime, rotYPoint, easingType)); - bone.setRotZ(EasingType.lerpWithOverride(this.molangRuntime, rotZPoint, easingType)); - - bone.setPosX(EasingType.lerpWithOverride(this.molangRuntime, posXPoint, easingType)); - bone.setPosY(EasingType.lerpWithOverride(this.molangRuntime, posYPoint, easingType)); - bone.setPosZ(EasingType.lerpWithOverride(this.molangRuntime, posZPoint, easingType)); - - bone.setScaleX(EasingType.lerpWithOverride(this.molangRuntime, scaleXPoint, easingType)); - bone.setScaleY(EasingType.lerpWithOverride(this.molangRuntime, scaleYPoint, easingType)); - bone.setScaleZ(EasingType.lerpWithOverride(this.molangRuntime, scaleZPoint, easingType)); - - bone.setBend(EasingType.lerpWithOverride(this.molangRuntime, bendPoint, easingType)); + EasingType easingOverride = this.overrideEasingTypeFunction.apply(this); + + bone.rotation.x = computeAnimValue(rotationKeyFrames.xKeyframes(), adjustedTick, TransformType.ROTATION, easingOverride, isAdvancedBone ? advancedBone::setRotXTransitionLength : null); + bone.rotation.y = computeAnimValue(rotationKeyFrames.yKeyframes(), adjustedTick, TransformType.ROTATION, easingOverride, isAdvancedBone ? advancedBone::setRotYTransitionLength : null); + bone.rotation.z = computeAnimValue(rotationKeyFrames.zKeyframes(), adjustedTick, TransformType.ROTATION, easingOverride, isAdvancedBone ? advancedBone::setRotZTransitionLength : null); + + bone.position.x = computeAnimValue(positionKeyFrames.xKeyframes(), adjustedTick, TransformType.POSITION, easingOverride, isAdvancedBone ? advancedBone::setPositionXTransitionLength : null); + bone.position.y = computeAnimValue(positionKeyFrames.yKeyframes(), adjustedTick, TransformType.POSITION, easingOverride, isAdvancedBone ? advancedBone::setPositionYTransitionLength : null); + bone.position.z = computeAnimValue(positionKeyFrames.zKeyframes(), adjustedTick, TransformType.POSITION, easingOverride, isAdvancedBone ? advancedBone::setPositionZTransitionLength : null); + + bone.scale.x = computeAnimValue(scaleKeyFrames.xKeyframes(), adjustedTick, TransformType.SCALE, easingOverride, isAdvancedBone ? advancedBone::setScaleXTransitionLength : null); + bone.scale.y = computeAnimValue(scaleKeyFrames.yKeyframes(), adjustedTick, TransformType.SCALE, easingOverride, isAdvancedBone ? advancedBone::setScaleYTransitionLength : null); + bone.scale.z = computeAnimValue(scaleKeyFrames.zKeyframes(), adjustedTick, TransformType.SCALE, easingOverride, isAdvancedBone ? advancedBone::setScaleZTransitionLength : null); } applyCustomPivotPoints(); @@ -760,31 +742,43 @@ else if (pivotBones.containsKey(entry.getKey())) } this.pivotBones.clear(); - for (Map.Entry entry : currentAnimation.animation().bones().entrySet()) { - this.pivotBones.put(entry.getKey(), new PivotBone(entry.getKey(), entry.getValue())); + for (Map.Entry entry : currentAnimation.animation().bones().entrySet()) { + this.pivotBones.put(entry.getKey(), new CustomBone(entry.getKey(), entry.getValue().pivot(), loadCustomModel( + entry.getValue().texture(), + entry.getValue().elements() + ))); } this.postAnimationSetupConsumer.accept(this.bones::get); } + protected abstract @Nullable PlatformModel loadCustomModel(@Nullable DecodedImage texture, @Nullable JsonArray elements); + + @Override + public void collectModels(Consumer consumer) { + for (CustomBone customBone : this.pivotBones.values()) { + if (customBone.getModel() == null) continue; + consumer.accept(customBone); + } + } + /** - * Convert a {@link KeyframeLocation} to an {@link AnimationPoint} + * Compute animation value for the given keyframes at the specified tick */ - private AnimationPoint getAnimationPointAtTick(List frames, float tick, TransformType type, Consumer transitionLengthSetter) { + private float computeAnimValue(List frames, float tick, TransformType type, @Nullable EasingType easingOverride, Consumer transitionLengthSetter) { Animation animation = this.currentAnimation.animation(); float endTick = animation.data().get(ExtraAnimationData.END_TICK_KEY).orElse(animation.length()-1); - KeyframeLocation location = getCurrentKeyFrameLocation(frames, tick, type, this.isAnimationPlayerAnimatorFormat() && this.currentAnimation.loopType().shouldPlayAgain(null, animation), animation.length(), this.currentAnimation.loopType().restartFromTick(null, animation)); + KeyframeLocation location = getCurrentKeyFrameLocation(frames, tick, type, this.isAnimationPlayerAnimatorFormat() && this.currentAnimation.loopType().shouldPlayAgain(null, animation), animation.length(), this.currentAnimation.loopType().restartFromTick(null, animation)); Keyframe currentFrame = location.keyframe(); float startValue = this.molangRuntime.eval(currentFrame.startValue()); float endValue = this.molangRuntime.eval(currentFrame.endValue()); if (type == TransformType.ROTATION || type == TransformType.BEND) { - if (!(MolangLoader.isConstant(currentFrame.startValue()))) { + if (!MolangLoader.isConstant(currentFrame.startValue())) { startValue = (float) Math.toRadians(startValue); } - - if (!(MolangLoader.isConstant(currentFrame.endValue()))) { + if (!MolangLoader.isConstant(currentFrame.endValue())) { endValue = (float) Math.toRadians(endValue); } } @@ -799,7 +793,9 @@ private AnimationPoint getAnimationPointAtTick(List frames, float tick } else transitionLengthSetter.accept(null); } - return new AnimationPoint(currentFrame.easingType(), currentFrame.easingArgs(), location.startTick(), currentFrame.length(), startValue, endValue); + + float lerpValue = currentFrame.length() > 0 ? location.startTick() / currentFrame.length() : 0; + return EasingType.lerpWithOverride(this.molangRuntime, startValue, endValue, currentFrame.length(), lerpValue, currentFrame.easingArgs(), currentFrame.easingType(), easingOverride); } /** @@ -809,9 +805,8 @@ private AnimationPoint getAnimationPointAtTick(List frames, float tick * @param ageInTicks The current tick time * @return A new {@code KeyFrameLocation} containing the current {@code KeyFrame} and the tick time used to find it */ - private KeyframeLocation getCurrentKeyFrameLocation(List frames, float ageInTicks, TransformType type, boolean isPlayerAnimatorLoop, float animTime, float returnToTick) { - if (frames.isEmpty()) - return type == TransformType.SCALE ? EMPTY_SCALE_KEYFRAME_LOCATION : EMPTY_KEYFRAME_LOCATION; + private KeyframeLocation getCurrentKeyFrameLocation(List frames, float ageInTicks, TransformType type, boolean isPlayerAnimatorLoop, float animTime, float returnToTick) { + if (frames.isEmpty()) return type == TransformType.SCALE ? EMPTY_SCALE_KEYFRAME_LOCATION : EMPTY_KEYFRAME_LOCATION; Keyframe firstFrame = returnToTick == 0 ? frames.getFirst() : Keyframe.getKeyframeAtTime(frames, returnToTick); float totalFrameTime = 0; @@ -822,16 +817,17 @@ private KeyframeLocation getCurrentKeyFrameLocation(List fra if (totalFrameTime > ageInTicks) { if (isPlayerAnimatorLoop && isLoopStarted() && frame == firstFrame) { float stopTickMinusLastKeyframe = animTime - Keyframe.getLastKeyframeTime(frames); - return new KeyframeLocation<>(new Keyframe(frame.length() + stopTickMinusLastKeyframe, frames.getLast().endValue(), frame.endValue(), frame.easingType(), frame.easingArgs()), ageInTicks + stopTickMinusLastKeyframe); + return new KeyframeLocation(new Keyframe(frame.length() + stopTickMinusLastKeyframe, frames.getLast().endValue(), frame.endValue(), frame.easingType(), frame.easingArgs()), ageInTicks + stopTickMinusLastKeyframe); } - return new KeyframeLocation<>(frame, (ageInTicks - (totalFrameTime - frame.length()))); + return new KeyframeLocation(frame, ageInTicks - (totalFrameTime - frame.length())); } } - if (isPlayerAnimatorLoop) - return new KeyframeLocation<>(new Keyframe(firstFrame.length() + animTime - totalFrameTime, frames.getLast().endValue(), firstFrame.endValue(), firstFrame.easingType(), firstFrame.easingArgs()), ageInTicks - totalFrameTime); + if (isPlayerAnimatorLoop) { + return new KeyframeLocation(new Keyframe(firstFrame.length() + animTime - totalFrameTime, frames.getLast().endValue(), firstFrame.endValue(), firstFrame.easingType(), firstFrame.easingArgs()), ageInTicks - totalFrameTime); + } - return new KeyframeLocation<>(frames.getLast(), ageInTicks); + return new KeyframeLocation(frames.getLast(), ageInTicks); } /** @@ -863,11 +859,12 @@ else if (hasEndTick() && extraData.get(ExtraAnimationData.END_TICK_KEY).g } @Override - public PlayerAnimBone get3DTransform(@NotNull PlayerAnimBone bone) { + public void get3DTransform(@NotNull PlayerAnimBone bone) { if (!modifiers.isEmpty()) { - return modifiers.getFirst().get3DTransform(bone); + modifiers.getFirst().get3DTransform(bone); + return; } - return get3DTransformRaw(bone); + get3DTransformRaw(bone); } @Override @@ -1082,8 +1079,8 @@ public void setupAnim(AnimationData state) { } @Override - public PlayerAnimBone get3DTransform(@NotNull PlayerAnimBone bone) { - return this.anim.get3DTransformRaw(bone); + public void get3DTransform(@NotNull PlayerAnimBone bone) { + this.anim.get3DTransformRaw(bone); } } diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/CustomModelBone.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/CustomModelBone.java new file mode 100644 index 00000000..1b6af052 --- /dev/null +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/CustomModelBone.java @@ -0,0 +1,35 @@ +package com.zigythebird.playeranimcore.animation; + +import com.google.gson.*; +import com.zigythebird.playeranimcore.math.Vec3f; +import org.jetbrains.annotations.Nullable; +import org.redlance.platformtools.webp.decoder.DecodedImage; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.Base64; + +public record CustomModelBone(Vec3f pivot, @Nullable DecodedImage texture, @Nullable JsonArray elements) { + public static class Deserializer implements JsonDeserializer { + @Override + public CustomModelBone deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext ctx) throws JsonParseException { + JsonObject obj = json.getAsJsonObject(); + return new CustomModelBone( + ctx.deserialize(obj.get("pivot"), Vec3f.class), + obj.has("texture") ? ctx.deserialize(obj.get("texture"), DecodedImage.class) : null, + obj.getAsJsonArray("elements") + ); + } + } + + public static class ImageDeserializer implements JsonDeserializer { + @Override + public DecodedImage deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext ctx) throws JsonParseException { + try { + return DecodedImage.fromPng(Base64.getDecoder().decode(json.getAsString())); + } catch (IOException e) { + throw new JsonParseException(e); + } + } + } +} diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/HumanoidAnimationController.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/HumanoidAnimationController.java index 4af219e0..2154e479 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/HumanoidAnimationController.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/HumanoidAnimationController.java @@ -24,11 +24,14 @@ package com.zigythebird.playeranimcore.animation; +import com.google.gson.JsonArray; +import com.zigythebird.playeranimcore.bindings.PlatformModel; import com.zigythebird.playeranimcore.bones.PlayerAnimBone; import com.zigythebird.playeranimcore.math.Vec3f; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.redlance.platformtools.webp.decoder.DecodedImage; import team.unnamed.mocha.MochaEngine; -import team.unnamed.mocha.runtime.standard.MochaMath; import java.util.ArrayList; import java.util.List; @@ -107,6 +110,7 @@ public void registerTopPlayerAnimBone(String name) { @Override public void process(AnimationData state) { super.process(state); + /* TODO Commented out until we decide what we want to do with bends this.torsoBend = bones.get("torso").getBend(); float absBend = Math.abs(this.torsoBend); if (absBend > 0.001 && (this.currentAnimation != null && this.currentAnimation.animation().data().getNullable(ExtraAnimationData.APPLY_BEND_TO_OTHER_BONES_KEY) == Boolean.TRUE)) { @@ -114,6 +118,7 @@ public void process(AnimationData state) { this.torsoBendYPosMultiplier = (float) -(1 - Math.cos(absBend)); this.torsoBendZPosMultiplier = (float) (1 - Math.sin(absBend)); } else this.torsoBendSign = 0; + */ } @Override @@ -122,10 +127,15 @@ public PlayerAnimBone get3DTransformRaw(@NotNull PlayerAnimBone bone) { String name = bone.getName(); if (this.torsoBendSign != 0 && this.top_bones.contains(name)) { float offset = getBonePosition(name).y() - 18; - bone.rotX += this.torsoBend; - bone.positionZ += (offset * this.torsoBendZPosMultiplier - offset) * this.torsoBendSign; - bone.positionY += offset * this.torsoBendYPosMultiplier; + bone.rotation.x += this.torsoBend; + bone.position.x += (offset * this.torsoBendZPosMultiplier - offset) * this.torsoBendSign; + bone.position.y += offset * this.torsoBendYPosMultiplier; } return bone; } + + @Override + protected @Nullable PlatformModel loadCustomModel(@Nullable DecodedImage texture, @Nullable JsonArray elements) { + return null; + } } diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/RawAnimation.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/RawAnimation.java index 3879df4e..0d789232 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/RawAnimation.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/RawAnimation.java @@ -9,10 +9,10 @@ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -24,17 +24,14 @@ package com.zigythebird.playeranimcore.animation; -import com.zigythebird.playeranimcore.enums.AnimationStage; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; /** - * A builder class for a raw/unbaked animation. These are constructed to pass to the - * {@link AnimationController} to build into full-fledged animations for usage - *

* Animations added to this builder are added in order of insertion - the animations will play in the order that you define them *

* RawAnimation instances should be cached statically where possible to reduce overheads and improve efficiency @@ -43,10 +40,17 @@ *

{@code RawAnimation.begin().thenPlay(openBox).thenLoop(stayOpen)}
*/ public final class RawAnimation { - private final List animationList = new ObjectArrayList<>(); + private final List animationList; // Private constructor to force usage of factory for logical operations - private RawAnimation() {} + private RawAnimation() { + this(new ObjectArrayList<>()); + } + + // Private constructor to force usage of factory for logical operations + private RawAnimation(List animationList) { + this.animationList = animationList; + } /** * Start a new RawAnimation instance. This is the start point for creating an animation chain @@ -84,7 +88,7 @@ public RawAnimation thenLoop(Animation animation) { * @param ticks The number of ticks to 'wait' for */ public RawAnimation thenWait(int ticks) { - this.animationList.add(new Stage(AnimationStage.WAIT, null, Animation.LoopType.PLAY_ONCE, ticks)); + this.animationList.add(new Stage(Animation.generateWaitAnimation(ticks), Animation.LoopType.PLAY_ONCE)); return this; } @@ -103,7 +107,7 @@ public RawAnimation thenPlayAndHold(Animation animation) { * Append an animation to the animation chain, playing the named animation playCount times, * then stopping or progressing to the next chained animation depending on the loop type set in the animation json * - * @param animation The animation to play X times + * @param animation The animation to play X times * @param playCount The number of times to repeat the animation before proceeding */ public RawAnimation thenPlayXTimes(Animation animation, int playCount) { @@ -146,6 +150,18 @@ public static RawAnimation copyOf(RawAnimation other) { return newInstance; } + @Override + public String toString() { + return "RawAnimation{" + this.animationList.stream().map(Stage::toString).collect(Collectors.joining(" -> ")) + "}"; + } + + /** + * Get the number of animation stages this RawAnimation contains + */ + public int getStageCount() { + return this.animationList.size(); + } + @Override public boolean equals(Object obj) { if (this == obj) @@ -167,15 +183,7 @@ public int hashCode() { *

* This is an entry object representing a single animation stage of the final compiled animation. */ - public record Stage(AnimationStage stage, @Nullable Animation animation, Animation.LoopType loopType, int additionalTicks) { - public Stage(AnimationStage stage, Animation animation, Animation.LoopType loopType) { - this(stage, animation, loopType, 0); - } - - public Stage(Animation animation, Animation.LoopType loopType) { - this(AnimationStage.ANIMATION, animation, loopType); - } - + public record Stage(@Nullable Animation animation, Animation.LoopType loopType) { @Override public boolean equals(Object obj) { if (this == obj) @@ -187,9 +195,14 @@ public boolean equals(Object obj) { return hashCode() == obj.hashCode(); } + @Override + public String toString() { + return animation == null ? "Invalid animation stage." : this.animation.toString(); + } + @Override public int hashCode() { - return Objects.hash(this.stage, this.animation, this.loopType); + return Objects.hash(this.animation, this.loopType); } } } diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/keyframe/AnimationPoint.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/keyframe/AnimationPoint.java deleted file mode 100644 index 75748b40..00000000 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/keyframe/AnimationPoint.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2024 GeckoLib - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.zigythebird.playeranimcore.animation.keyframe; - -import com.zigythebird.playeranimcore.easing.EasingType; -import org.jetbrains.annotations.Nullable; -import team.unnamed.mocha.parser.ast.Expression; - -import java.util.List; - -/** - * Animation state record that holds the state of an animation at a given point - * - * @param easingType The easing type - * @param easingArgs The easing arguments - * @param currentTick The lerped tick time (current tick + partial tick) of the point - * @param transitionLength The length of time (in ticks) that the point should take to transition - * @param animationStartValue The start value to provide to the animation handling system - * @param animationEndValue The end value to provide to the animation handling system - */ -public record AnimationPoint(EasingType easingType, @Nullable List> easingArgs, float currentTick, float transitionLength, float animationStartValue, float animationEndValue) { - public AnimationPoint(Keyframe keyframe, float currentTick, float transitionLength, float animationStartValue, float animationEndValue) { - this(keyframe == null ? EasingType.LINEAR : keyframe.easingType(), keyframe == null ? null : keyframe.easingArgs(), currentTick, transitionLength, animationStartValue, animationEndValue); - } - - @Override - public String toString() { - return "Tick: " + this.currentTick + - " | Transition Length: " + this.transitionLength + - " | Start Value: " + this.animationStartValue + - " | End Value: " + this.animationEndValue; - } -} diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/keyframe/KeyframeLocation.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/keyframe/KeyframeLocation.java index ea4ff529..aeb4a8e4 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/keyframe/KeyframeLocation.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/keyframe/KeyframeLocation.java @@ -30,4 +30,4 @@ * @param keyframe The {@code Keyframe} at the tick time * @param startTick The animation tick time at the start of this {@code Keyframe} */ -public record KeyframeLocation(T keyframe, float startTick) { } +public record KeyframeLocation(Keyframe keyframe, float startTick) {} diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/AnimationContainer.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/AnimationContainer.java index a8d80301..d5a235c8 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/AnimationContainer.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/AnimationContainer.java @@ -27,10 +27,13 @@ import com.zigythebird.playeranimcore.animation.AnimationData; import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonConfiguration; import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonMode; +import com.zigythebird.playeranimcore.bones.CustomBone; import com.zigythebird.playeranimcore.bones.PlayerAnimBone; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.function.Consumer; + /** * A container to make swapping animation object easier * It will clone the behaviour of the held animation @@ -69,9 +72,8 @@ public void tick(AnimationData state) { } @Override - public PlayerAnimBone get3DTransform(@NotNull PlayerAnimBone bone) { - if (anim != null) return anim.get3DTransform(bone); - return bone; + public void get3DTransform(@NotNull PlayerAnimBone bone) { + if (anim != null) anim.get3DTransform(bone); } @Override @@ -95,4 +97,9 @@ public String toString() { "anim=" + anim + '}'; } + + @Override + public void collectModels(Consumer consumer) { + if (this.anim != null) this.anim.collectModels(consumer); + } } diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/AnimationSnapshot.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/AnimationSnapshot.java index 24e53a12..afc51c9d 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/AnimationSnapshot.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/AnimationSnapshot.java @@ -1,23 +1,22 @@ package com.zigythebird.playeranimcore.animation.layered; -import com.zigythebird.playeranimcore.bones.AdvancedBoneSnapshot; import com.zigythebird.playeranimcore.bones.PlayerAnimBone; +import com.zigythebird.playeranimcore.bones.ToggleablePlayerAnimBone; import org.jetbrains.annotations.NotNull; import java.util.Map; -public record AnimationSnapshot(Map snapshots) implements IAnimation { +public record AnimationSnapshot(Map snapshots) implements IAnimation { @Override public boolean isActive() { return true; } @Override - public PlayerAnimBone get3DTransform(@NotNull PlayerAnimBone bone) { + public void get3DTransform(@NotNull PlayerAnimBone bone) { if (snapshots.containsKey(bone.getName())) { - return bone.copySnapshotSafe(snapshots.get(bone.getName())); + bone.copyOtherBoneIfNotDisabled(snapshots.get(bone.getName())); } - return bone; } @Override diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/AnimationStack.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/AnimationStack.java index 65466bbb..3045a3e7 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/AnimationStack.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/AnimationStack.java @@ -3,12 +3,14 @@ import com.zigythebird.playeranimcore.animation.AnimationData; import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonConfiguration; import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonMode; +import com.zigythebird.playeranimcore.bones.CustomBone; import com.zigythebird.playeranimcore.bones.PlayerAnimBone; import it.unimi.dsi.fastutil.Pair; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; +import java.util.function.Consumer; /** * Player animation stack, can contain multiple active or passive layers, will always be evaluated from the lowest index. @@ -37,16 +39,15 @@ public void tick(AnimationData state) { } @Override - public PlayerAnimBone get3DTransform(@NotNull PlayerAnimBone bone) { + public void get3DTransform(@NotNull PlayerAnimBone bone) { for (Pair layer : layers) { if (layer.right().isActive() /* Not sure if this is necessary, hard to implement rn && (!FirstPersonMode.isFirstPersonPass() || layer.right().getFirstPersonMode().isEnabled()) */) { - bone = layer.right().get3DTransform(bone); + layer.right().get3DTransform(bone); } } - return bone; } @Override @@ -132,4 +133,13 @@ public String toString() { "layers=" + layers + '}'; } + + @Override + public void collectModels(Consumer consumer) { + for (Pair layer : this.layers) { + if (layer.right().isActive()) { + layer.right().collectModels(consumer); + } + } + } } diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/IAnimation.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/IAnimation.java index 039619b3..88272fff 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/IAnimation.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/IAnimation.java @@ -27,9 +27,12 @@ import com.zigythebird.playeranimcore.animation.AnimationData; import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonConfiguration; import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonMode; +import com.zigythebird.playeranimcore.bones.CustomBone; import com.zigythebird.playeranimcore.bones.PlayerAnimBone; import org.jetbrains.annotations.NotNull; +import java.util.function.Consumer; + public interface IAnimation { FirstPersonConfiguration DEFAULT_FIRST_PERSON_CONFIG = new FirstPersonConfiguration(); @@ -58,7 +61,11 @@ default void setupAnim(AnimationData state) {} * @param bone the bone being currently animated. * KEEP IN MIND THAT THE BONE RETURNED ISN'T ALWAYS THE SAME AS THE INPUT BONE! */ - default PlayerAnimBone get3DTransform(@NotNull PlayerAnimBone bone) { + void get3DTransform(@NotNull PlayerAnimBone bone); + + default PlayerAnimBone get3DTransform(@NotNull String name) { + PlayerAnimBone bone = new PlayerAnimBone(name); + get3DTransform(bone); return bone; } @@ -84,4 +91,6 @@ default FirstPersonConfiguration getFirstPersonConfiguration() { default boolean canRemove() { return false; } + + default void collectModels(Consumer consumer) {} } diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/ModifierLayer.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/ModifierLayer.java index 7b9ef2f9..dc8f5814 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/ModifierLayer.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/ModifierLayer.java @@ -5,6 +5,7 @@ import com.zigythebird.playeranimcore.animation.layered.modifier.AbstractModifier; import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonConfiguration; import com.zigythebird.playeranimcore.api.firstPerson.FirstPersonMode; +import com.zigythebird.playeranimcore.bones.CustomBone; import com.zigythebird.playeranimcore.bones.PlayerAnimBone; import com.zigythebird.playeranimcore.easing.EasingType; import org.jetbrains.annotations.NotNull; @@ -14,6 +15,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.function.Consumer; import java.util.function.Predicate; @@ -41,6 +43,16 @@ public ModifierLayer() { return animation; } + protected @Nullable IAnimation getTopAnimation() { + if (!this.modifiers.isEmpty()) { + return this.modifiers.getFirst(); + } else if (this.animation != null) { + return this.animation; + } else { + return null; + } + } + @Override public void tick(AnimationData state) { for (int i = 0; i < modifiers.size(); i++) { @@ -48,9 +60,8 @@ public void tick(AnimationData state) { removeModifier(i--); } } - if (modifiers.size() > 0) { - modifiers.get(0).tick(state); - } else if (animation != null) animation.tick(state); + IAnimation top = getTopAnimation(); + if (top != null) top.tick(state); } public void addModifier(@NotNull AbstractModifier modifier, int idx) { @@ -141,40 +152,34 @@ protected void linkModifiers() { @Override public boolean isActive() { - if (!modifiers.isEmpty()) { - return modifiers.get(0).isActive(); - } else if (animation != null) return animation.isActive(); + IAnimation top = getTopAnimation(); + if (top != null) return top.isActive(); return false; } @Override - public PlayerAnimBone get3DTransform(@NotNull PlayerAnimBone bone) { - if (!modifiers.isEmpty()) { - return modifiers.get(0).get3DTransform(bone); - } else if (animation != null) return animation.get3DTransform(bone); - return bone; + public void get3DTransform(@NotNull PlayerAnimBone bone) { + IAnimation top = getTopAnimation(); + if (top != null) top.get3DTransform(bone); } @Override public void setupAnim(AnimationData state) { - if (!modifiers.isEmpty()) { - modifiers.get(0).setupAnim(state); - } else if (animation != null) animation.setupAnim(state); + IAnimation top = getTopAnimation(); + if (top != null) top.setupAnim(state); } @Override public @NotNull FirstPersonMode getFirstPersonMode() { - if (!modifiers.isEmpty()) { - return modifiers.get(0).getFirstPersonMode(); - } else if (animation != null) return animation.getFirstPersonMode(); + IAnimation top = getTopAnimation(); + if (top != null) return top.getFirstPersonMode(); return IAnimation.super.getFirstPersonMode(); } @Override public @NotNull FirstPersonConfiguration getFirstPersonConfiguration() { - if (!modifiers.isEmpty()) { - return modifiers.get(0).getFirstPersonConfiguration(); - } else if (animation != null) return animation.getFirstPersonConfiguration(); + IAnimation top = getTopAnimation(); + if (top != null) return top.getFirstPersonConfiguration(); return IAnimation.super.getFirstPersonConfiguration(); } @@ -185,4 +190,10 @@ public String toString() { ", animation=" + animation + '}'; } + + @Override + public void collectModels(Consumer consumer) { + IAnimation top = getTopAnimation(); + if (top != null) top.collectModels(consumer); + } } diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/PlayerAnimationFrame.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/PlayerAnimationFrame.java index 551c75a5..cf9d8d56 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/PlayerAnimationFrame.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/PlayerAnimationFrame.java @@ -92,12 +92,12 @@ public void enableAll() { } @Override - public PlayerAnimBone get3DTransform(@NotNull PlayerAnimBone bone) { + public void get3DTransform(@NotNull PlayerAnimBone bone) { PlayerBone part = parts.get(bone.getName()); - if (part != null) return part.applyToBone(bone); - return bone; + if (part != null) part.applyToBone(bone); } - + + //TODO Maybe replace this with smth better public static class PlayerBone { public Float offsetPosX = null; public Float offsetPosY = null; @@ -110,8 +110,6 @@ public static class PlayerBone { public Float scaleX = null; public Float scaleY = null; public Float scaleZ = null; - - public Float bend = null; public PlayerBone() { super(); @@ -133,8 +131,6 @@ public void setToInitialPose() { this.scaleX = null; this.scaleY = null; this.scaleZ = null; - - this.bend = null; } /** @@ -152,34 +148,29 @@ public void enableAll() { this.scaleX = 1F; this.scaleY = 1F; this.scaleZ = 1F; - - this.bend = 0F; } public PlayerAnimBone applyToBone(PlayerAnimBone bone) { if (offsetPosX != null) - bone.setPosX(offsetPosX); + bone.position.x = offsetPosX; if (offsetPosY != null) - bone.setPosY(offsetPosY); + bone.position.y = offsetPosY; if (offsetPosZ != null) - bone.setPosZ(offsetPosZ); + bone.position.z = offsetPosZ; if (rotX != null) - bone.setRotX(rotX); + bone.rotation.x = rotX; if (rotY != null) - bone.setRotY(rotY); + bone.rotation.y = rotY; if (rotZ != null) - bone.setRotZ(rotZ); + bone.rotation.z = rotZ; if (scaleX != null) - bone.setScaleX(scaleX); + bone.scale.x = scaleX; if (scaleY != null) - bone.setScaleY(scaleY); + bone.scale.y = scaleY; if (scaleZ != null) - bone.setScaleZ(scaleZ); - - if (bend != null) - bone.setBend(bend); + bone.scale.z = scaleZ; return bone; } diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/modifier/AbstractFadeModifier.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/modifier/AbstractFadeModifier.java index d6578b99..86fb015b 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/modifier/AbstractFadeModifier.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/modifier/AbstractFadeModifier.java @@ -84,9 +84,10 @@ public void tick(AnimationData state) { } @Override - public PlayerAnimBone get3DTransform(@NotNull PlayerAnimBone bone) { + public void get3DTransform(@NotNull PlayerAnimBone bone) { if (calculateProgress(tickDelta, bone.getName()) > 1) { - return super.get3DTransform(bone); + super.get3DTransform(bone); + return; } PlayerAnimBone copy2 = new PlayerAnimBone(bone.getName()); copy2.copyOtherBone(bone); @@ -95,7 +96,7 @@ public PlayerAnimBone get3DTransform(@NotNull PlayerAnimBone bone) { if (getFadeType() == FadeType.FADE_IN) { if (transitionAnimation != null && transitionAnimation.isActive()) transitionAnimation.get3DTransform(bone); } - return bone.scale(1 - a).add(copy2.scale(a)); + bone.scale(1 - a).add(copy2.scale(a)); } protected float calculateProgress(float f, String boneName) { diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/modifier/AdjustmentModifier.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/modifier/AdjustmentModifier.java index fcb166ae..08b7385c 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/modifier/AdjustmentModifier.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/modifier/AdjustmentModifier.java @@ -30,7 +30,6 @@ import com.zigythebird.playeranimcore.math.Vec3f; import org.jetbrains.annotations.NotNull; -import java.util.Objects; import java.util.Optional; import java.util.function.BiFunction; import java.util.function.Function; @@ -77,55 +76,11 @@ * */ public class AdjustmentModifier extends AbstractModifier { - public static final class PartModifier { - private final Vec3f rotation; - private final Vec3f scale; - private final Vec3f offset; - + //TODO Maybe we can replace this with something that uses Vector3f + public record PartModifier(Vec3f rotation, Vec3f scale, Vec3f offset) { public PartModifier(Vec3f rotation, Vec3f offset) { this(rotation, Vec3f.ZERO, offset); } - - public PartModifier(Vec3f rotation, Vec3f scale, Vec3f offset) { - this.rotation = rotation; - this.scale = scale; - this.offset = offset; - } - - public Vec3f rotation() { - return rotation; - } - - public Vec3f scale() { - return scale; - } - - public Vec3f offset() { - return offset; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null || obj.getClass() != this.getClass()) return false; - PartModifier that = (PartModifier) obj; - return Objects.equals(this.rotation, that.rotation) && - Objects.equals(this.scale, that.scale) && - Objects.equals(this.offset, that.offset); - } - - @Override - public int hashCode() { - return Objects.hash(rotation, scale, offset); - } - - @Override - public String toString() { - return "PartModifier[" + - "rotation=" + rotation + ", " + - "scale=" + scale + ", " + - "offset=" + offset + ']'; - } } /// Whether the adjustment should be increasingly applied @@ -207,9 +162,10 @@ protected float getFadeIn() { } @Override - public PlayerAnimBone get3DTransform(@NotNull PlayerAnimBone bone) { + public void get3DTransform(@NotNull PlayerAnimBone bone) { if (!enabled) { - return super.get3DTransform(bone); + super.get3DTransform(bone); + return; } Optional partModifier = source.apply(bone.getName(), data); @@ -218,18 +174,18 @@ public PlayerAnimBone get3DTransform(@NotNull PlayerAnimBone bone) { if (partModifier.isPresent()) { super.get3DTransform(bone); transformBone(bone, partModifier.get(), fade); - return bone; + return; } - return super.get3DTransform(bone); + super.get3DTransform(bone); } protected void transformBone(PlayerAnimBone bone, PartModifier partModifier, float fade) { Vec3f pos = partModifier.offset().mul(fade); Vec3f rot = partModifier.rotation().mul(fade); Vec3f scale = partModifier.scale().mul(fade); - bone.updatePosition(pos.x() + bone.getPosX(), pos.y() + bone.getPosY(), pos.z() + bone.getPosZ()); - bone.updateRotation(rot.x() + bone.getRotX(), rot.y() + bone.getRotY(), rot.z() + bone.getRotZ()); - bone.updateScale(scale.x() + bone.getScaleX(), scale.y() + bone.getScaleY(), scale.z() + bone.getScaleZ()); + bone.position.add(pos.x(), pos.y(), pos.z()); + bone.rotation.add(rot.x(), rot.y(), rot.z()); + bone.scale.add(scale.x(), scale.y(), scale.z()); } @Override diff --git a/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/modifier/MirrorModifier.java b/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/modifier/MirrorModifier.java index bfece8c9..4f18e9be 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/modifier/MirrorModifier.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/animation/layered/modifier/MirrorModifier.java @@ -38,8 +38,11 @@ public class MirrorModifier extends AbstractModifier { public boolean enabled = true; @Override - public PlayerAnimBone get3DTransform(@NotNull PlayerAnimBone bone) { - if (!enabled) return super.get3DTransform(bone); + public void get3DTransform(@NotNull PlayerAnimBone bone) { + if (!enabled) { + super.get3DTransform(bone); + return; + } String modelName = bone.getName(); if (mirrorMap.containsKey(modelName)) modelName = mirrorMap.get(modelName); @@ -47,10 +50,9 @@ public PlayerAnimBone get3DTransform(@NotNull PlayerAnimBone bone) { PlayerAnimBone newBone = new PlayerAnimBone(modelName); newBone.copyOtherBone(bone); - newBone = super.get3DTransform(newBone); + super.get3DTransform(newBone); transformBone(newBone); bone.copyOtherBone(newBone); - return bone; } @Override @@ -65,10 +67,10 @@ public PlayerAnimBone get3DTransform(@NotNull PlayerAnimBone bone) { } protected void transformBone(PlayerAnimBone bone) { - bone.positionX *= -1; - bone.rotY *= -1; - bone.rotZ *= -1; - bone.bend *= -1; + bone.position.x *= -1; + bone.rotation.y *= -1; + bone.rotation.z *= -1; + //bone.bend *= -1; Why was this a thing in the first place? } static { diff --git a/core/src/main/java/com/zigythebird/playeranimcore/bindings/PlatformModel.java b/core/src/main/java/com/zigythebird/playeranimcore/bindings/PlatformModel.java new file mode 100644 index 00000000..85edf661 --- /dev/null +++ b/core/src/main/java/com/zigythebird/playeranimcore/bindings/PlatformModel.java @@ -0,0 +1,5 @@ +package com.zigythebird.playeranimcore.bindings; + +public interface PlatformModel { + void invalidate(); +} diff --git a/core/src/main/java/com/zigythebird/playeranimcore/bones/AdvancedBoneSnapshot.java b/core/src/main/java/com/zigythebird/playeranimcore/bones/AdvancedBoneSnapshot.java deleted file mode 100644 index aec409f9..00000000 --- a/core/src/main/java/com/zigythebird/playeranimcore/bones/AdvancedBoneSnapshot.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.zigythebird.playeranimcore.bones; - -public class AdvancedBoneSnapshot extends BoneSnapshot { - public boolean scaleXEnabled; - public boolean scaleYEnabled; - public boolean scaleZEnabled; - - public boolean positionXEnabled; - public boolean positionYEnabled; - public boolean positionZEnabled; - - public boolean rotXEnabled; - public boolean rotYEnabled; - public boolean rotZEnabled; - - public boolean bendEnabled; - - public AdvancedBoneSnapshot(PlayerAnimBone bone) { - super(bone); - - if (bone instanceof IBoneEnabled boneEnabled) { - scaleXEnabled = boneEnabled.isScaleXEnabled(); - scaleYEnabled = boneEnabled.isScaleYEnabled(); - scaleZEnabled = boneEnabled.isScaleZEnabled(); - - positionXEnabled = boneEnabled.isPositionXEnabled(); - positionYEnabled = boneEnabled.isPositionYEnabled(); - positionZEnabled = boneEnabled.isPositionZEnabled(); - - rotXEnabled = boneEnabled.isRotXEnabled(); - rotYEnabled = boneEnabled.isRotYEnabled(); - rotZEnabled = boneEnabled.isRotZEnabled(); - - bendEnabled = boneEnabled.isBendEnabled(); - } - } -} diff --git a/core/src/main/java/com/zigythebird/playeranimcore/bones/AdvancedPlayerAnimBone.java b/core/src/main/java/com/zigythebird/playeranimcore/bones/AdvancedPlayerAnimBone.java index a0b1f8a6..6300fca2 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/bones/AdvancedPlayerAnimBone.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/bones/AdvancedPlayerAnimBone.java @@ -1,6 +1,6 @@ package com.zigythebird.playeranimcore.bones; -public class AdvancedPlayerAnimBone extends PlayerAnimBone implements IBoneEnabled { +public class AdvancedPlayerAnimBone extends ToggleablePlayerAnimBone { public Float scaleXTransitionLength = null; public Float scaleYTransitionLength = null; public Float scaleZTransitionLength = null; @@ -15,24 +15,14 @@ public class AdvancedPlayerAnimBone extends PlayerAnimBone implements IBoneEnabl public Float bendTransitionLength = null; - public boolean scaleXEnabled = true; - public boolean scaleYEnabled = true; - public boolean scaleZEnabled = true; - - public boolean positionXEnabled = true; - public boolean positionYEnabled = true; - public boolean positionZEnabled = true; - - public boolean rotXEnabled = true; - public boolean rotYEnabled = true; - public boolean rotZEnabled = true; - - public boolean bendEnabled = true; - public AdvancedPlayerAnimBone(String name) { super(name); } + public AdvancedPlayerAnimBone(PlayerAnimBone bone) { + super(bone); + } + public void setEnabled(boolean enabled) { scaleXEnabled = enabled; scaleYEnabled = enabled; @@ -88,72 +78,4 @@ public void setScaleYTransitionLength(Float scaleYTransitionLength) { public void setScaleXTransitionLength(Float scaleXTransitionLength) { this.scaleXTransitionLength = scaleXTransitionLength; } - - public void setPositionEnabled(boolean enabled) { - this.positionXEnabled = enabled; - this.positionYEnabled = enabled; - this.positionZEnabled = enabled; - } - - public void setRotEnabled(boolean enabled) { - this.rotXEnabled = enabled; - this.rotYEnabled = enabled; - this.rotZEnabled = enabled; - } - - public void setScaleEnabled(boolean enabled) { - this.scaleXEnabled = enabled; - this.scaleYEnabled = enabled; - this.scaleZEnabled = enabled; - } - - @Override - public boolean isScaleXEnabled() { - return scaleXEnabled; - } - - @Override - public boolean isScaleYEnabled() { - return scaleYEnabled; - } - - @Override - public boolean isScaleZEnabled() { - return scaleZEnabled; - } - - @Override - public boolean isPositionXEnabled() { - return positionXEnabled; - } - - @Override - public boolean isPositionYEnabled() { - return positionYEnabled; - } - - @Override - public boolean isPositionZEnabled() { - return positionZEnabled; - } - - @Override - public boolean isRotXEnabled() { - return rotXEnabled; - } - - @Override - public boolean isRotYEnabled() { - return rotYEnabled; - } - - @Override - public boolean isRotZEnabled() { - return rotZEnabled; - } - - @Override - public boolean isBendEnabled() { - return bendEnabled; - } } diff --git a/core/src/main/java/com/zigythebird/playeranimcore/bones/BoneSnapshot.java b/core/src/main/java/com/zigythebird/playeranimcore/bones/BoneSnapshot.java deleted file mode 100644 index a2ddf275..00000000 --- a/core/src/main/java/com/zigythebird/playeranimcore/bones/BoneSnapshot.java +++ /dev/null @@ -1,224 +0,0 @@ -package com.zigythebird.playeranimcore.bones; - -import com.zigythebird.playeranimcore.animation.AnimationController; -import com.zigythebird.playeranimcore.enums.TransformType; -import com.zigythebird.playeranimcore.math.Vec3f; -import it.unimi.dsi.fastutil.Pair; - -/** - * Transformations applied to the bone are monitored by the {@link AnimationController} - * in the course of animations, and stored here for monitoring. - */ -public class BoneSnapshot { - public final PlayerAnimBone bone; - - private float scaleX; - private float scaleY; - private float scaleZ; - - private float offsetPosX; - private float offsetPosY; - private float offsetPosZ; - - private float rotX; - private float rotY; - private float rotZ; - - private float bendAxis; - private float bend; - - public BoneSnapshot() { - this.bone = null; - setToInitialPose(); - } - - public BoneSnapshot(PlayerAnimBone bone) { - this.rotX = bone.getRotX(); - this.rotY = bone.getRotY(); - this.rotZ = bone.getRotZ(); - - this.offsetPosX = bone.getPosX(); - this.offsetPosY = bone.getPosY(); - this.offsetPosZ = bone.getPosZ(); - - this.scaleX = bone.getScaleX(); - this.scaleY = bone.getScaleY(); - this.scaleZ = bone.getScaleZ(); - - this.bend = bone.getBend(); - - this.bone = bone; - } - - public BoneSnapshot(BoneSnapshot bone) { - this.bone = bone.getBone(); - - this.rotX = bone.getRotX(); - this.rotY = bone.getRotY(); - this.rotZ = bone.getRotZ(); - - this.offsetPosX = bone.getOffsetX(); - this.offsetPosY = bone.getOffsetY(); - this.offsetPosZ = bone.getOffsetZ(); - - this.scaleX = bone.getScaleX(); - this.scaleY = bone.getScaleY(); - this.scaleZ = bone.getScaleZ(); - - this.bendAxis = bone.getBendAxis(); - this.bend = bone.getBend(); - } - - public BoneSnapshot(PlayerAnimBone bone, boolean isInitial) { - this.bone = bone; - if (!isInitial) { - this.rotX = bone.getRotX(); - this.rotY = bone.getRotY(); - this.rotZ = bone.getRotZ(); - - this.offsetPosX = bone.getPosX(); - this.offsetPosY = bone.getPosY(); - this.offsetPosZ = bone.getPosZ(); - - this.scaleX = bone.getScaleX(); - this.scaleY = bone.getScaleY(); - this.scaleZ = bone.getScaleZ(); - - this.bend = bone.getBend(); - } - else setToInitialPose(); - } - - public PlayerAnimBone getBone() {return this.bone;} - - public float getScaleX() { - return this.scaleX; - } - - public float getScaleY() { - return this.scaleY; - } - - public float getScaleZ() { - return this.scaleZ; - } - - public float getOffsetX() { - return this.offsetPosX; - } - - public float getOffsetY() { - return this.offsetPosY; - } - - public float getOffsetZ() { - return this.offsetPosZ; - } - - public float getRotX() { - return this.rotX; - } - - public float getRotY() { - return this.rotY; - } - - public float getRotZ() { - return this.rotZ; - } - - public float getBendAxis() { - return this.bendAxis; - } - - public float getBend() { - return this.bend; - } - - /** - * Update the scale state of this snapshot - */ - public void updateScale(float scaleX, float scaleY, float scaleZ) { - this.scaleX = scaleX; - this.scaleY = scaleY; - this.scaleZ = scaleZ; - } - - /** - * Update the offset state of this snapshot - */ - public void updateOffset(float offsetX, float offsetY, float offsetZ) { - this.offsetPosX = offsetX; - this.offsetPosY = offsetY; - this.offsetPosZ = offsetZ; - } - - /** - * Update the rotation state of this snapshot - */ - public void updateRotation(float rotX, float rotY, float rotZ) { - this.rotX = rotX; - this.rotY = rotY; - this.rotZ = rotZ; - } - - public void updateBend(float bendAxis, float bend) { - this.bendAxis = bendAxis; - this.bend = bend; - } - - public void updateBend(Pair bend) { - updateBend(bend.left(), bend.right()); - } - - public Vec3f getTransformFromType(TransformType type) { - switch (type) { - case POSITION -> { - return new Vec3f(offsetPosX, offsetPosY, offsetPosZ); - } - case ROTATION -> { - return new Vec3f(rotX, rotY, rotZ); - } - case SCALE -> { - return new Vec3f(scaleX, scaleY, scaleZ); - } - case BEND -> { - return new Vec3f(bendAxis, bend, 0); - } - } - return null; - } - - public void setToInitialPose() { - this.rotX = 0; - this.rotY = 0; - this.rotZ = 0; - - this.offsetPosX = 0; - this.offsetPosY = 0; - this.offsetPosZ = 0; - - this.scaleX = 1; - this.scaleY = 1; - this.scaleZ = 1; - - this.bendAxis = 0; - this.bend = 0; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - - if (obj == null || getClass() != obj.getClass()) - return false; - - return hashCode() == obj.hashCode(); - } - - @Override - public int hashCode() { - return this.bone.getName().hashCode(); - } -} diff --git a/core/src/main/java/com/zigythebird/playeranimcore/bones/CustomBone.java b/core/src/main/java/com/zigythebird/playeranimcore/bones/CustomBone.java new file mode 100644 index 00000000..aa892a09 --- /dev/null +++ b/core/src/main/java/com/zigythebird/playeranimcore/bones/CustomBone.java @@ -0,0 +1,26 @@ +package com.zigythebird.playeranimcore.bones; + +import com.zigythebird.playeranimcore.bindings.PlatformModel; +import com.zigythebird.playeranimcore.math.Vec3f; +import org.jetbrains.annotations.Nullable; + +public class CustomBone extends PlayerAnimBone { + private final Vec3f pivot; + + @Nullable + private final PlatformModel model; + + public CustomBone(String name, Vec3f pivot, @Nullable PlatformModel model) { + super(name); + this.pivot = pivot; + this.model = model; + } + + public Vec3f getPivot() { + return this.pivot; + } + + public @Nullable PlatformModel getModel() { + return this.model; + } +} diff --git a/core/src/main/java/com/zigythebird/playeranimcore/bones/IBoneEnabled.java b/core/src/main/java/com/zigythebird/playeranimcore/bones/IBoneEnabled.java deleted file mode 100644 index 92f4d3f2..00000000 --- a/core/src/main/java/com/zigythebird/playeranimcore/bones/IBoneEnabled.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.zigythebird.playeranimcore.bones; - -public interface IBoneEnabled { - boolean isScaleXEnabled(); - boolean isScaleYEnabled(); - boolean isScaleZEnabled(); - - boolean isPositionXEnabled(); - boolean isPositionYEnabled(); - boolean isPositionZEnabled(); - - boolean isRotXEnabled(); - boolean isRotYEnabled(); - boolean isRotZEnabled(); - - boolean isBendEnabled(); -} diff --git a/core/src/main/java/com/zigythebird/playeranimcore/bones/PivotBone.java b/core/src/main/java/com/zigythebird/playeranimcore/bones/PivotBone.java deleted file mode 100644 index 567b6949..00000000 --- a/core/src/main/java/com/zigythebird/playeranimcore/bones/PivotBone.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.zigythebird.playeranimcore.bones; - -import com.zigythebird.playeranimcore.math.Vec3f; - -public class PivotBone extends PlayerAnimBone { - private final Vec3f pivot; - - public PivotBone(String name, Vec3f pivot) { - super(name); - this.pivot = pivot; - } - - public Vec3f getPivot() { - return this.pivot; - } -} diff --git a/core/src/main/java/com/zigythebird/playeranimcore/bones/PlayerAnimBone.java b/core/src/main/java/com/zigythebird/playeranimcore/bones/PlayerAnimBone.java index 042e21c7..67285827 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/bones/PlayerAnimBone.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/bones/PlayerAnimBone.java @@ -8,8 +8,8 @@ import com.zigythebird.playeranimcore.easing.EasingType; import com.zigythebird.playeranimcore.enums.Axis; import com.zigythebird.playeranimcore.enums.TransformType; -import com.zigythebird.playeranimcore.math.Vec3f; import org.jetbrains.annotations.ApiStatus; +import org.joml.Vector3f; import java.util.List; @@ -17,360 +17,89 @@ * This is the object that is directly modified by animations to handle movement */ public class PlayerAnimBone { - private final String name; - - public float scaleX = 1; - public float scaleY = 1; - public float scaleZ = 1; - - public float positionX; - public float positionY; - public float positionZ; - - public float rotX; - public float rotY; - public float rotZ; - - public float bend; + public final String name; + public final Vector3f position; + public final Vector3f rotation; + public final Vector3f scale; public PlayerAnimBone(String name) { this.name = name; + this.position = new Vector3f(); + this.rotation = new Vector3f(); + this.scale = new Vector3f(1); } - public String getName() { - return this.name; - } - - public float getRotX() { - return this.rotX; - } - - public float getRotY() { - return this.rotY; - } - - public float getRotZ() { - return this.rotZ; - } - - public float getPosX() { - return this.positionX; - } - - public float getPosY() { - return this.positionY; - } - - public float getPosZ() { - return this.positionZ; - } - - public float getScaleX() { - return this.scaleX; - } - - public float getScaleY() { - return this.scaleY; - } - - public float getScaleZ() { - return this.scaleZ; - } - - public float getBend() { - return this.bend; - } - - public void setRotX(float value) { - this.rotX = value; - } - - public void setRotY(float value) { - this.rotY = value; - } - - public void setRotZ(float value) { - this.rotZ = value; - } - - public void updateRotation(float xRot, float yRot, float zRot) { - setRotX(xRot); - setRotY(yRot); - setRotZ(zRot); - } - - public void setPosX(float value) { - this.positionX = value; + public PlayerAnimBone(PlayerAnimBone bone) { + this.name = bone.getName(); + this.position = new Vector3f(bone.position); + this.rotation = new Vector3f(bone.rotation); + this.scale = new Vector3f(bone.scale); } - public void setPosY(float value) { - this.positionY = value; - } - - public void setPosZ(float value) { - this.positionZ = value; - } - - public void updatePosition(float posX, float posY, float posZ) { - setPosX(posX); - setPosY(posY); - setPosZ(posZ); - } - - public void setScaleX(float value) { - this.scaleX = value; - } - - public void setScaleY(float value) { - this.scaleY = value; - } - - public void setScaleZ(float value) { - this.scaleZ = value; - } - - public void updateScale(float scaleX, float scaleY, float scaleZ) { - setScaleX(scaleX); - setScaleY(scaleY); - setScaleZ(scaleZ); - } - - public void setBend(float value) { - this.bend = value; + public String getName() { + return this.name; } public void setToInitialPose() { - this.positionX = 0; - this.positionY = 0; - this.positionZ = 0; - - this.rotX = 0; - this.rotY = 0; - this.rotZ = 0; - - this.scaleX = 1; - this.scaleY = 1; - this.scaleZ = 1; - - this.bend = 0; - } - - public Vec3f getPositionVector() { - return new Vec3f(getPosX(), getPosY(), getPosZ()); - } - - public Vec3f getRotationVector() { - return new Vec3f(getRotX(), getRotY(), getRotZ()); - } - - public Vec3f getScaleVector() { - return new Vec3f(getScaleX(), getScaleY(), getScaleZ()); - } - - public void addRotationOffsetFromBone(PlayerAnimBone source) { - setRotX(getRotX() + source.getRotX()); - setRotY(getRotY() + source.getRotY()); - setRotZ(getRotZ() + source.getRotZ()); + this.position.set(0, 0, 0); + this.rotation.set(0, 0, 0); + this.scale.set(1, 1, 1); } public PlayerAnimBone scale(float value) { - this.positionX *= value; - this.positionY *= value; - this.positionZ *= value; - - this.rotX *= value; - this.rotY *= value; - this.rotZ *= value; - - this.scaleX *= value; - this.scaleY *= value; - this.scaleZ *= value; - - this.bend *= value; + this.position.mul(value); + this.rotation.mul(value); + this.scale.mul(value); return this; } public PlayerAnimBone add(PlayerAnimBone bone) { - this.positionX += bone.positionX; - this.positionY += bone.positionY; - this.positionZ += bone.positionZ; - - this.rotX += bone.rotX; - this.rotY += bone.rotY; - this.rotZ += bone.rotZ; - - this.scaleX += bone.scaleX; - this.scaleY += bone.scaleY; - this.scaleZ += bone.scaleZ; - - this.bend += bone.bend; + this.position.add(bone.position); + this.rotation.add(bone.rotation); + this.scale.add(bone.scale); return this; } public PlayerAnimBone applyOtherBone(PlayerAnimBone bone) { - this.positionX += bone.positionX; - this.positionY += bone.positionY; - this.positionZ += bone.positionZ; - - this.rotX += bone.rotX; - this.rotY += bone.rotY; - this.rotZ += bone.rotZ; - - this.scaleX *= bone.scaleX; - this.scaleY *= bone.scaleY; - this.scaleZ *= bone.scaleZ; - - this.bend += bone.bend; - - return this; - } - - public PlayerAnimBone addPos(float value) { - return addPos(value, value, value); - } - - public PlayerAnimBone mulPos(float value) { - return mulPos(value, value, value); - } - - public PlayerAnimBone divPos(float value) { - return divPos(value, value, value); - } - - public PlayerAnimBone addRot(float value) { - return addRot(value, value, value); - } - - public PlayerAnimBone mulRot(float value) { - return mulRot(value, value, value); - } - - public PlayerAnimBone divRot(float value) { - return divRot(value, value, value); - } - - public PlayerAnimBone addScale(float value) { - return addScale(value, value, value); - } - - public PlayerAnimBone mulScale(float value) { - return mulScale(value, value, value); - } - - public PlayerAnimBone divScale(float value) { - return divScale(value, value, value); - } - - public PlayerAnimBone addPos(float x, float y, float z) { - this.positionX += x; - this.positionY += y; - this.positionZ += z; - - return this; - } - - public PlayerAnimBone addRot(float x, float y, float z) { - this.rotX += x; - this.rotY += y; - this.rotZ += z; + this.position.add(bone.position); + this.rotation.add(bone.rotation); + this.scale.mul(bone.scale); return this; } - public PlayerAnimBone addScale(float x, float y, float z) { - this.scaleX += x; - this.scaleY += y; - this.scaleZ += z; - - return this; - } - - public PlayerAnimBone mulPos(float x, float y, float z) { - this.positionX *= x; - this.positionY *= y; - this.positionZ *= z; - return this; - } - - public PlayerAnimBone mulRot(float x, float y, float z) { - this.rotX *= x; - this.rotY *= y; - this.rotZ *= z; - return this; - } - - public PlayerAnimBone mulScale(float x, float y, float z) { - this.scaleX *= x; - this.scaleY *= y; - this.scaleZ *= z; - return this; - } - - public PlayerAnimBone divPos(float x, float y, float z) { - this.positionX /= x; - this.positionY /= y; - this.positionZ /= z; - return this; - } - - public PlayerAnimBone divRot(float x, float y, float z) { - this.rotX /= x; - this.rotY /= y; - this.rotZ /= z; - return this; - } - - public PlayerAnimBone divScale(float x, float y, float z) { - this.scaleX /= x; - this.scaleY /= y; - this.scaleZ /= z; - return this; - } - public PlayerAnimBone copyOtherBone(PlayerAnimBone bone) { - this.positionX = bone.positionX; - this.positionY = bone.positionY; - this.positionZ = bone.positionZ; - - this.rotX = bone.rotX; - this.rotY = bone.rotY; - this.rotZ = bone.rotZ; + this.position.set(bone.position); + this.rotation.set(bone.rotation); + this.scale.set(bone.scale); - this.scaleX = bone.scaleX; - this.scaleY = bone.scaleY; - this.scaleZ = bone.scaleZ; - - this.bend = bone.bend; return this; } public PlayerAnimBone copyOtherBoneIfNotDisabled(PlayerAnimBone bone) { - if (bone instanceof IBoneEnabled advancedBone) { - if (advancedBone.isPositionXEnabled()) - this.positionX = bone.positionX; - if (advancedBone.isPositionYEnabled()) - this.positionY = bone.positionY; - if (advancedBone.isPositionZEnabled()) - this.positionZ = bone.positionZ; - - if (advancedBone.isRotXEnabled()) - this.rotX = bone.rotX; - if (advancedBone.isRotYEnabled()) - this.rotY = bone.rotY; - if (advancedBone.isRotZEnabled()) - this.rotZ = bone.rotZ; - - if (advancedBone.isScaleXEnabled()) - this.scaleX = bone.scaleX; - if (advancedBone.isScaleYEnabled()) - this.scaleY = bone.scaleY; - if (advancedBone.isScaleZEnabled()) - this.scaleZ = bone.scaleZ; - - if (advancedBone.isBendEnabled()) - this.bend = bone.bend; + if (bone instanceof ToggleablePlayerAnimBone toggleableBone) { + if (toggleableBone.isPositionXEnabled()) + this.position.x = bone.position.x; + if (toggleableBone.isPositionYEnabled()) + this.position.y = bone.position.y; + if (toggleableBone.isPositionZEnabled()) + this.position.z = bone.position.z; + + if (toggleableBone.isRotXEnabled()) + this.rotation.x = bone.rotation.x; + if (toggleableBone.isRotYEnabled()) + this.rotation.y = bone.rotation.y; + if (toggleableBone.isRotZEnabled()) + this.rotation.z = bone.rotation.z; + + if (toggleableBone.isScaleXEnabled()) + this.scale.x = bone.scale.x; + if (toggleableBone.isScaleYEnabled()) + this.scale.y = bone.scale.y; + if (toggleableBone.isScaleZEnabled()) + this.scale.z = bone.scale.z; return this; } @@ -378,34 +107,29 @@ public PlayerAnimBone copyOtherBoneIfNotDisabled(PlayerAnimBone bone) { } @ApiStatus.Internal - public PlayerAnimBone beginOrEndTickLerp(AdvancedPlayerAnimBone bone, float animTime, Animation animation) { + public void beginOrEndTickLerp(AdvancedPlayerAnimBone bone, float animTime, Animation animation) { if (bone.positionXEnabled) - this.positionX = beginOrEndTickLerp(positionX, bone.positionX, bone.positionXTransitionLength, animTime, animation, TransformType.POSITION, Axis.X); + this.position.x = beginOrEndTickLerp(position.x, bone.position.x, bone.positionXTransitionLength, animTime, animation, TransformType.POSITION, Axis.X); if (bone.positionYEnabled) - this.positionY = beginOrEndTickLerp(positionY, bone.positionY, bone.positionYTransitionLength, animTime, animation, TransformType.POSITION, Axis.Y); + this.position.y = beginOrEndTickLerp(position.y, bone.position.y, bone.positionYTransitionLength, animTime, animation, TransformType.POSITION, Axis.Y); if (bone.positionZEnabled) - this.positionZ = beginOrEndTickLerp(positionZ, bone.positionZ, bone.positionZTransitionLength, animTime, animation, TransformType.POSITION, Axis.Z); + this.position.z = beginOrEndTickLerp(position.z, bone.position.z, bone.positionZTransitionLength, animTime, animation, TransformType.POSITION, Axis.Z); if (bone.rotXEnabled) - this.rotX = beginOrEndTickLerp(rotX, bone.rotX, bone.rotXTransitionLength, animTime, animation, TransformType.ROTATION, Axis.X); + this.rotation.z = beginOrEndTickLerp(rotation.x, bone.rotation.x, bone.rotXTransitionLength, animTime, animation, TransformType.ROTATION, Axis.X); if (bone.rotYEnabled) - this.rotY = beginOrEndTickLerp(rotY, bone.rotY, bone.rotYTransitionLength, animTime, animation, TransformType.ROTATION, Axis.Y); + this.rotation.y = beginOrEndTickLerp(rotation.y, bone.rotation.y, bone.rotYTransitionLength, animTime, animation, TransformType.ROTATION, Axis.Y); if (bone.rotZEnabled) - this.rotZ = beginOrEndTickLerp(rotZ, bone.rotZ, bone.rotZTransitionLength, animTime, animation, TransformType.ROTATION, Axis.Z); + this.rotation.z = beginOrEndTickLerp(rotation.z, bone.rotation.z, bone.rotZTransitionLength, animTime, animation, TransformType.ROTATION, Axis.Z); if (bone.scaleXEnabled) - this.scaleX = beginOrEndTickLerp(scaleX, bone.scaleX, bone.scaleXTransitionLength, animTime, animation, TransformType.SCALE, Axis.X); + this.scale.x = beginOrEndTickLerp(scale.x, bone.scale.x, bone.scaleXTransitionLength, animTime, animation, TransformType.SCALE, Axis.X); if (bone.scaleYEnabled) - this.scaleY = beginOrEndTickLerp(scaleY, bone.scaleY, bone.scaleYTransitionLength, animTime, animation, TransformType.SCALE, Axis.Y); + this.scale.y = beginOrEndTickLerp(scale.y, bone.scale.y, bone.scaleYTransitionLength, animTime, animation, TransformType.SCALE, Axis.Y); if (bone.scaleZEnabled) - this.scaleZ = beginOrEndTickLerp(scaleZ, bone.scaleZ, bone.scaleZTransitionLength, animTime, animation, TransformType.SCALE, Axis.Z); - - if (bone.bendEnabled) - this.bend = beginOrEndTickLerp(bend, bone.bend, bone.bendTransitionLength, animTime, animation, TransformType.BEND, Axis.Y); - - return this; + this.scale.z = beginOrEndTickLerp(scale.z, bone.scale.z, bone.scaleZTransitionLength, animTime, animation, TransformType.SCALE, Axis.Z); } - + private float beginOrEndTickLerp(float startValue, float endValue, Float transitionLength, float animTime, Animation animation, TransformType type, Axis axis) { EasingType easingType = EasingType.EASE_IN_OUT_SINE; if (animation != null) { @@ -439,54 +163,7 @@ private float beginOrEndTickLerp(float startValue, float endValue, Float transit return easingType.apply(startValue, endValue, animTime / transitionLength); } - public void copySnapshot(BoneSnapshot snapshot) { - this.positionX = snapshot.getOffsetX(); - this.positionY = snapshot.getOffsetY(); - this.positionZ = snapshot.getOffsetZ(); - - this.rotX = snapshot.getRotX(); - this.rotY = snapshot.getRotY(); - this.rotZ = snapshot.getRotZ(); - - this.scaleX = snapshot.getScaleX(); - this.scaleY = snapshot.getScaleY(); - this.scaleZ = snapshot.getScaleZ(); - - this.bend = snapshot.getBend(); - } - - public PlayerAnimBone copySnapshotSafe(AdvancedBoneSnapshot snapshot) { - if (snapshot.positionXEnabled) - this.positionX = snapshot.getOffsetX(); - if (snapshot.positionYEnabled) - this.positionY = snapshot.getOffsetY(); - if (snapshot.positionZEnabled) - this.positionZ = snapshot.getOffsetZ(); - - if (snapshot.rotXEnabled) - this.rotX = snapshot.getRotX(); - if (snapshot.rotYEnabled) - this.rotY = snapshot.getRotY(); - if (snapshot.rotZEnabled) - this.rotZ = snapshot.getRotZ(); - - if (snapshot.scaleXEnabled) - this.scaleX = snapshot.getScaleX(); - if (snapshot.scaleYEnabled) - this.scaleY = snapshot.getScaleY(); - if (snapshot.scaleZEnabled) - this.scaleZ = snapshot.getScaleZ(); - - if (snapshot.bendEnabled) - this.bend = snapshot.getBend(); - - return this; - } - - public BoneSnapshot saveSnapshot() { - return new BoneSnapshot(this); - } - + @Override public boolean equals(Object obj) { if (this == obj) return true; @@ -497,6 +174,7 @@ public boolean equals(Object obj) { return hashCode() == obj.hashCode(); } + @Override public int hashCode() { return getName().hashCode(); } diff --git a/core/src/main/java/com/zigythebird/playeranimcore/bones/ToggleablePlayerAnimBone.java b/core/src/main/java/com/zigythebird/playeranimcore/bones/ToggleablePlayerAnimBone.java new file mode 100644 index 00000000..e10b03bc --- /dev/null +++ b/core/src/main/java/com/zigythebird/playeranimcore/bones/ToggleablePlayerAnimBone.java @@ -0,0 +1,99 @@ +package com.zigythebird.playeranimcore.bones; + +public class ToggleablePlayerAnimBone extends PlayerAnimBone { + public boolean scaleXEnabled = true; + public boolean scaleYEnabled = true; + public boolean scaleZEnabled = true; + + public boolean positionXEnabled = true; + public boolean positionYEnabled = true; + public boolean positionZEnabled = true; + + public boolean rotXEnabled = true; + public boolean rotYEnabled = true; + public boolean rotZEnabled = true; + + public boolean bendEnabled = true; + + public ToggleablePlayerAnimBone(String name) { + super(name); + } + + public ToggleablePlayerAnimBone(PlayerAnimBone bone) { + super(bone); + + if (bone instanceof ToggleablePlayerAnimBone boneEnabled) { + scaleXEnabled = boneEnabled.isScaleXEnabled(); + scaleYEnabled = boneEnabled.isScaleYEnabled(); + scaleZEnabled = boneEnabled.isScaleZEnabled(); + + positionXEnabled = boneEnabled.isPositionXEnabled(); + positionYEnabled = boneEnabled.isPositionYEnabled(); + positionZEnabled = boneEnabled.isPositionZEnabled(); + + rotXEnabled = boneEnabled.isRotXEnabled(); + rotYEnabled = boneEnabled.isRotYEnabled(); + rotZEnabled = boneEnabled.isRotZEnabled(); + + bendEnabled = boneEnabled.isBendEnabled(); + } + } + + public void setPositionEnabled(boolean enabled) { + this.positionXEnabled = enabled; + this.positionYEnabled = enabled; + this.positionZEnabled = enabled; + } + + public void setRotEnabled(boolean enabled) { + this.rotXEnabled = enabled; + this.rotYEnabled = enabled; + this.rotZEnabled = enabled; + } + + public void setScaleEnabled(boolean enabled) { + this.scaleXEnabled = enabled; + this.scaleYEnabled = enabled; + this.scaleZEnabled = enabled; + } + + public boolean isScaleXEnabled() { + return scaleXEnabled; + } + + public boolean isScaleYEnabled() { + return scaleYEnabled; + } + + public boolean isScaleZEnabled() { + return scaleZEnabled; + } + + public boolean isPositionXEnabled() { + return positionXEnabled; + } + + public boolean isPositionYEnabled() { + return positionYEnabled; + } + + public boolean isPositionZEnabled() { + return positionZEnabled; + } + + public boolean isRotXEnabled() { + return rotXEnabled; + } + + public boolean isRotYEnabled() { + return rotYEnabled; + } + + public boolean isRotZEnabled() { + return rotZEnabled; + } + + public boolean isBendEnabled() { + return bendEnabled; + } +} diff --git a/core/src/main/java/com/zigythebird/playeranimcore/easing/BezierEasing.java b/core/src/main/java/com/zigythebird/playeranimcore/easing/BezierEasing.java index c013bb6f..53baed14 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/easing/BezierEasing.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/easing/BezierEasing.java @@ -1,6 +1,5 @@ package com.zigythebird.playeranimcore.easing; -import com.zigythebird.playeranimcore.animation.keyframe.AnimationPoint; import it.unimi.dsi.fastutil.floats.Float2FloatFunction; import org.jetbrains.annotations.Nullable; import org.joml.Vector2f; @@ -20,10 +19,12 @@ public Float2FloatFunction buildTransformer(@Nullable Float value) { abstract boolean isEasingBefore(); @Override - public float apply(MochaEngine env, AnimationPoint animationPoint, @Nullable Float easingValue, float lerpValue) { - List> easingArgs = animationPoint.easingArgs(); - if (easingArgs.isEmpty()) - return MochaMath.lerp(animationPoint.animationStartValue(), animationPoint.animationEndValue(), buildTransformer(easingValue).apply(lerpValue)); + public float apply(MochaEngine env, float startValue, float endValue, float transitionLength, float lerpValue, @Nullable List> easingArgs) { + if (lerpValue >= 1) return endValue; + if (Float.isNaN(lerpValue)) return startValue; + + if (easingArgs == null || easingArgs.isEmpty()) + return MochaMath.lerp(startValue, endValue, buildTransformer(null).apply(lerpValue)); float rightValue = isEasingBefore() ? 0 : env.eval(easingArgs.getFirst()); float rightTime = isEasingBefore() ? 0.1f : env.eval(easingArgs.get(1)); @@ -38,16 +39,16 @@ public float apply(MochaEngine env, AnimationPoint animationPoint, @Nullable leftValue = (float) Math.toRadians(leftValue); rightValue = (float) Math.toRadians(rightValue); - float gapTime = animationPoint.transitionLength()/20; + float gapTime = transitionLength / 20; float time_handle_before = Math.clamp(rightTime, 0, gapTime); float time_handle_after = Math.clamp(leftTime, -gapTime, 0); CubicBezierCurve curve = new CubicBezierCurve( - new Vector2f(0, animationPoint.animationStartValue()), - new Vector2f(time_handle_before, animationPoint.animationStartValue() + rightValue), - new Vector2f(time_handle_after + gapTime, animationPoint.animationEndValue() + leftValue), - new Vector2f(gapTime, animationPoint.animationEndValue())); + new Vector2f(0, startValue), + new Vector2f(time_handle_before, startValue + rightValue), + new Vector2f(time_handle_after + gapTime, endValue + leftValue), + new Vector2f(gapTime, endValue)); float time = gapTime * lerpValue; List points = curve.getPoints(200); diff --git a/core/src/main/java/com/zigythebird/playeranimcore/easing/CatmullRomEasing.java b/core/src/main/java/com/zigythebird/playeranimcore/easing/CatmullRomEasing.java index 12e5ba72..5fb5b1f5 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/easing/CatmullRomEasing.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/easing/CatmullRomEasing.java @@ -1,6 +1,5 @@ package com.zigythebird.playeranimcore.easing; -import com.zigythebird.playeranimcore.animation.keyframe.AnimationPoint; import it.unimi.dsi.fastutil.floats.Float2FloatFunction; import org.jetbrains.annotations.Nullable; import team.unnamed.mocha.MochaEngine; @@ -34,15 +33,13 @@ public Float2FloatFunction buildTransformer(Float value) { } @Override - public float apply(MochaEngine env, AnimationPoint animationPoint, @Nullable Float easingValue, float lerpValue) { - if (animationPoint.currentTick() >= animationPoint.transitionLength()) - return animationPoint.animationEndValue(); + public float apply(MochaEngine env, float startValue, float endValue, float transitionLength, float lerpValue, @Nullable List> easingArgs) { + if (lerpValue >= 1) return endValue; + if (Float.isNaN(lerpValue)) return startValue; - List> easingArgs = animationPoint.easingArgs(); + if (easingArgs == null || easingArgs.size() < 2) + return MochaMath.lerp(startValue, endValue, buildTransformer(null).apply(lerpValue)); - if (easingArgs.size() < 2) - return MochaMath.lerp(animationPoint.animationStartValue(), animationPoint.animationEndValue(), buildTransformer(easingValue).apply(lerpValue)); - - return getPointOnSpline(lerpValue, env.eval(easingArgs.get(0)), animationPoint.animationStartValue(), animationPoint.animationEndValue(), env.eval(easingArgs.get(1))); + return getPointOnSpline(lerpValue, env.eval(easingArgs.get(0)), startValue, endValue, env.eval(easingArgs.get(1))); } } diff --git a/core/src/main/java/com/zigythebird/playeranimcore/easing/EasingType.java b/core/src/main/java/com/zigythebird/playeranimcore/easing/EasingType.java index 0998ad52..ba422400 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/easing/EasingType.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/easing/EasingType.java @@ -2,14 +2,15 @@ import com.google.gson.JsonElement; import com.google.gson.JsonPrimitive; -import com.zigythebird.playeranimcore.animation.keyframe.AnimationPoint; import com.zigythebird.playeranimcore.animation.keyframe.Keyframe; import com.zigythebird.playeranimcore.math.MathHelper; import it.unimi.dsi.fastutil.floats.Float2FloatFunction; import org.jetbrains.annotations.Nullable; import team.unnamed.mocha.MochaEngine; +import team.unnamed.mocha.parser.ast.Expression; import team.unnamed.mocha.runtime.standard.MochaMath; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -98,23 +99,13 @@ public Float2FloatFunction buildTransformer(@Nullable Float value) { return this.transformer.buildTransformer(value); } - public static float lerpWithOverride(MochaEngine env, AnimationPoint animationPoint, @Nullable EasingType override) { - EasingType easingType = override; - - if (override == null) - easingType = animationPoint.easingType(); - - return easingType.apply(env, animationPoint); - } - - @Override - public float apply(MochaEngine env, AnimationPoint animationPoint) { - return this.transformer.apply(env, animationPoint); + public float apply(MochaEngine env, float startValue, float endValue, float transitionLength, float lerpValue, @Nullable List> easingArgs) { + return this.transformer.apply(env, startValue, endValue, transitionLength, lerpValue, easingArgs); } - @Override - public float apply(MochaEngine env, AnimationPoint animationPoint, @Nullable Float easingValue, float lerpValue) { - return this.transformer.apply(env, animationPoint, easingValue, lerpValue); + public static float lerpWithOverride(MochaEngine env, float startValue, float endValue, float transitionLength, float lerpValue, @Nullable List> easingArgs, EasingType easingType, @Nullable EasingType override) { + EasingType easing = override != null ? override : easingType; + return easing.apply(env, startValue, endValue, transitionLength, lerpValue, easingArgs); } @Override diff --git a/core/src/main/java/com/zigythebird/playeranimcore/easing/EasingTypeTransformer.java b/core/src/main/java/com/zigythebird/playeranimcore/easing/EasingTypeTransformer.java index 9dbeb659..29390b60 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/easing/EasingTypeTransformer.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/easing/EasingTypeTransformer.java @@ -1,32 +1,27 @@ package com.zigythebird.playeranimcore.easing; -import com.zigythebird.playeranimcore.animation.keyframe.AnimationPoint; import it.unimi.dsi.fastutil.floats.Float2FloatFunction; import org.jetbrains.annotations.Nullable; import team.unnamed.mocha.MochaEngine; +import team.unnamed.mocha.parser.ast.Expression; import team.unnamed.mocha.runtime.standard.MochaMath; import team.unnamed.mocha.runtime.value.ObjectValue; +import java.util.List; + @FunctionalInterface public interface EasingTypeTransformer extends ObjectValue.FloatFunction3 { Float2FloatFunction buildTransformer(@Nullable Float value); - default float apply(MochaEngine env, AnimationPoint animationPoint) { - Float easingVariable = null; - - if (animationPoint.easingArgs() != null && !animationPoint.easingArgs().isEmpty()) - easingVariable = env.eval(animationPoint.easingArgs().getFirst()); + default float apply(MochaEngine env, float startValue, float endValue, float transitionLength, float lerpValue, @Nullable List> easingArgs) { + if (lerpValue >= 1) return endValue; + if (Float.isNaN(lerpValue)) return startValue; - return apply(env, animationPoint, easingVariable, animationPoint.currentTick() / animationPoint.transitionLength()); - } - - default float apply(MochaEngine env, AnimationPoint animationPoint, @Nullable Float easingValue, float lerpValue) { - if (lerpValue >= 1) - return animationPoint.animationEndValue(); - if (Float.isNaN(lerpValue)) - return animationPoint.animationStartValue(); - - return apply(animationPoint.animationStartValue(), animationPoint.animationEndValue(), easingValue, lerpValue); + Float easingVariable = null; + if (easingArgs != null && !easingArgs.isEmpty()) { + easingVariable = env.eval(easingArgs.getFirst()); + } + return apply(startValue, endValue, easingVariable, lerpValue); } @Override diff --git a/core/src/main/java/com/zigythebird/playeranimcore/enums/AnimationStage.java b/core/src/main/java/com/zigythebird/playeranimcore/enums/AnimationStage.java deleted file mode 100644 index 96283aff..00000000 --- a/core/src/main/java/com/zigythebird/playeranimcore/enums/AnimationStage.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.zigythebird.playeranimcore.enums; - -public enum AnimationStage { - WAIT, - ANIMATION -} diff --git a/core/src/main/java/com/zigythebird/playeranimcore/loading/AnimationLoader.java b/core/src/main/java/com/zigythebird/playeranimcore/loading/AnimationLoader.java index 9aaa8fbd..09480da1 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/loading/AnimationLoader.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/loading/AnimationLoader.java @@ -27,6 +27,7 @@ import com.google.gson.*; import com.zigythebird.playeranimcore.PlayerAnimLib; import com.zigythebird.playeranimcore.animation.Animation; +import com.zigythebird.playeranimcore.animation.CustomModelBone; import com.zigythebird.playeranimcore.animation.ExtraAnimationData; import com.zigythebird.playeranimcore.animation.keyframe.BoneAnimation; import com.zigythebird.playeranimcore.animation.keyframe.Keyframe; @@ -34,7 +35,6 @@ import com.zigythebird.playeranimcore.easing.EasingType; import com.zigythebird.playeranimcore.enums.Axis; import com.zigythebird.playeranimcore.enums.TransformType; -import com.zigythebird.playeranimcore.math.Vec3f; import com.zigythebird.playeranimcore.molang.MolangLoader; import com.zigythebird.playeranimcore.util.JsonUtil; import it.unimi.dsi.fastutil.floats.FloatObjectPair; @@ -63,7 +63,7 @@ public Animation deserialize(JsonElement json, Type typeOfT, JsonDeserialization Animation.Keyframes keyframes = context.deserialize(animationObj, Animation.Keyframes.class); Map parents = UniversalAnimLoader.getParents(JsonUtil.getAsJsonObject(animationObj, "parents", new JsonObject())); - Map bones = UniversalAnimLoader.getModel(JsonUtil.getAsJsonObject(animationObj, "model", new JsonObject())); + Map bones = UniversalAnimLoader.getModel(JsonUtil.getAsJsonObject(animationObj, "model", new JsonObject()), context); // Extra data ExtraAnimationData extraData = new ExtraAnimationData(); diff --git a/core/src/main/java/com/zigythebird/playeranimcore/loading/UniversalAnimLoader.java b/core/src/main/java/com/zigythebird/playeranimcore/loading/UniversalAnimLoader.java index 7f5b8c8c..64d7f01a 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/loading/UniversalAnimLoader.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/loading/UniversalAnimLoader.java @@ -3,11 +3,11 @@ import com.google.gson.*; import com.zigythebird.playeranimcore.PlayerAnimLib; import com.zigythebird.playeranimcore.animation.Animation; +import com.zigythebird.playeranimcore.animation.CustomModelBone; import com.zigythebird.playeranimcore.animation.ExtraAnimationData; import com.zigythebird.playeranimcore.animation.keyframe.event.data.CustomInstructionKeyframeData; import com.zigythebird.playeranimcore.animation.keyframe.event.data.ParticleKeyframeData; import com.zigythebird.playeranimcore.animation.keyframe.event.data.SoundKeyframeData; -import com.zigythebird.playeranimcore.math.Vec3f; import com.zigythebird.playeranimcore.util.JsonUtil; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; @@ -39,13 +39,17 @@ public static Map loadAnimations(InputStream resource) throws public static Map<@NotNull String, Animation> loadAnimations(JsonObject json) { if (json.has("animations")) { Map animationMap = PlayerAnimLib.GSON.fromJson(json.get("animations"), PlayerAnimLib.ANIMATIONS_MAP_TYPE); - if (json.has("parents") && json.has("model")) { - Map parents = UniversalAnimLoader.getParents(JsonUtil.getAsJsonObject(json, "parents", new JsonObject())); - Map bones = UniversalAnimLoader.getModel(JsonUtil.getAsJsonObject(json, "model", new JsonObject())); + if (json.has("model")) { + Map bones = UniversalAnimLoader.getModel(JsonUtil.getAsJsonObject(json, "model", new JsonObject()), PlayerAnimLib.GSON::fromJson); for (Animation animation : animationMap.values()) { if (animation.bones().isEmpty()) { animation.bones().putAll(bones); } + } + } + if (json.has("parents")) { + Map parents = UniversalAnimLoader.getParents(JsonUtil.getAsJsonObject(json, "parents", new JsonObject())); + for (Animation animation : animationMap.values()) { if (animation.parents().isEmpty()) { animation.parents().putAll(parents); } @@ -86,13 +90,10 @@ public static Map getParents(JsonObject parentsObj) { return parents; } - public static Map getModel(JsonObject modelObj) { - Map bones = new HashMap<>(modelObj.size()); + public static Map getModel(JsonObject modelObj, JsonDeserializationContext ctx) { + Map bones = new HashMap<>(modelObj.size()); for (Map.Entry entry : modelObj.entrySet()) { - JsonObject object = entry.getValue().getAsJsonObject(); - JsonArray pivot = object.get("pivot").getAsJsonArray(); - Vec3f bone = new Vec3f(pivot.get(0).getAsFloat(), pivot.get(1).getAsFloat(), pivot.get(2).getAsFloat()); - bones.put(entry.getKey(), bone); + bones.put(entry.getKey(), ctx.deserialize(entry.getValue(), CustomModelBone.class)); } return bones; } diff --git a/core/src/main/java/com/zigythebird/playeranimcore/math/Vec3f.java b/core/src/main/java/com/zigythebird/playeranimcore/math/Vec3f.java index 6775e6ae..26ba2a44 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/math/Vec3f.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/math/Vec3f.java @@ -1,5 +1,9 @@ package com.zigythebird.playeranimcore.math; +import com.google.gson.*; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Type; import java.util.Objects; public record Vec3f(float x, float y, float z) { @@ -16,6 +20,10 @@ public Vec3f mul(float scalar) { return new Vec3f(this.x * scalar, this.y * scalar, this.z * scalar); } + public Vec3f div(float scalar) { + return new Vec3f(this.x / scalar, this.y / scalar, this.z / scalar); + } + /** * Add two vectors * @@ -29,12 +37,12 @@ public Vec3f add(Vec3f other) { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof Vec3f vec)) return false; - return Objects.equals(x, vec.x) && Objects.equals(y, vec.y) && Objects.equals(z, vec.z); + if (!(o instanceof Vec3f(float x1, float y1, float z1))) return false; + return Objects.equals(x, x1) && Objects.equals(y, y1) && Objects.equals(z, z1); } @Override - public String toString() { + public @NotNull String toString() { return "Vec3f[" + this.x + "; " + this.y + "; " + this.z + "]"; } @@ -42,4 +50,12 @@ public String toString() { public int hashCode() { return Objects.hash(x, y, z); } + + public static class Deserializer implements JsonDeserializer { + @Override + public Vec3f deserialize(JsonElement json, Type type, JsonDeserializationContext ctx) throws JsonParseException { + JsonArray array = json.getAsJsonArray(); + return new Vec3f(array.get(0).getAsFloat(), array.get(1).getAsFloat(), array.get(2).getAsFloat()); + } + } } diff --git a/core/src/main/java/com/zigythebird/playeranimcore/network/AnimationBinary.java b/core/src/main/java/com/zigythebird/playeranimcore/network/AnimationBinary.java index 0ca46ca8..631724f6 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/network/AnimationBinary.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/network/AnimationBinary.java @@ -1,6 +1,7 @@ package com.zigythebird.playeranimcore.network; import com.zigythebird.playeranimcore.animation.Animation; +import com.zigythebird.playeranimcore.animation.CustomModelBone; import com.zigythebird.playeranimcore.animation.ExtraAnimationData; import com.zigythebird.playeranimcore.animation.keyframe.BoneAnimation; import com.zigythebird.playeranimcore.animation.keyframe.Keyframe; @@ -11,9 +12,7 @@ import com.zigythebird.playeranimcore.easing.EasingType; import com.zigythebird.playeranimcore.enums.AnimationFormat; import com.zigythebird.playeranimcore.enums.TransformType; -import com.zigythebird.playeranimcore.loading.AnimationLoader; import com.zigythebird.playeranimcore.loading.PlayerAnimatorLoader; -import com.zigythebird.playeranimcore.math.Vec3f; import io.netty.buffer.ByteBuf; import team.unnamed.mocha.parser.ast.Expression; import team.unnamed.mocha.parser.ast.FloatExpression; @@ -36,14 +35,20 @@ public final class AnimationBinary { * Version 3: No change client side, but the server won't send some animations to versions lower than 3 due to the possibility of a crash. * Version 4: Fixed some issues with the body bone. * Version 5: Fixed the Y position axis on items being negated. + * Version 6: Compact binary format - bit-packed header, presence flags for bone axes, compact keyframe encoding. */ - public static final int CURRENT_VERSION = 5; + public static final int CURRENT_VERSION = 6; public static void write(ByteBuf buf, Animation animation) { AnimationBinary.write(buf, CURRENT_VERSION, animation); } public static void write(ByteBuf buf, int version, Animation animation) { + if (version >= 6) { + AnimationBinaryV6.write(buf, version, animation); + return; + } + Map data = animation.data().data(); boolean applyBendToOtherBones = (boolean) data.getOrDefault(ExtraAnimationData.APPLY_BEND_TO_OTHER_BONES_KEY, false); if (version < 3 && applyBendToOtherBones && animation.boneAnimations().containsKey("torso") @@ -75,30 +80,8 @@ public static void write(ByteBuf buf, int version, Animation animation) { writeBoneAnimation(buf, entry.getValue(), version < 4 && entry.getKey().equals("body"), version < 5 && LegacyAnimationBinary.ITEM_BONE.test(entry.getKey())); } - // Sounds - VarIntUtils.writeVarInt(buf, animation.keyFrames().sounds().length); - for (SoundKeyframeData soundKeyframe : animation.keyFrames().sounds()) { - buf.writeFloat(soundKeyframe.getStartTick()); - ProtocolUtils.writeString(buf, soundKeyframe.getSound()); - } - - // Particles - VarIntUtils.writeVarInt(buf, animation.keyFrames().particles().length); - for (ParticleKeyframeData particleKeyframe : animation.keyFrames().particles()) { - buf.writeFloat(particleKeyframe.getStartTick()); - ProtocolUtils.writeString(buf, particleKeyframe.getEffect()); - ProtocolUtils.writeString(buf, particleKeyframe.getLocator()); - ProtocolUtils.writeString(buf, particleKeyframe.script()); - } - - // Instructions - VarIntUtils.writeVarInt(buf, animation.keyFrames().customInstructions().length); - for (CustomInstructionKeyframeData instructionKeyframe : animation.keyFrames().customInstructions()) { - buf.writeFloat(instructionKeyframe.getStartTick()); - ProtocolUtils.writeString(buf, instructionKeyframe.getInstructions()); - } - - NetworkUtils.writeMap(buf, animation.bones(), ProtocolUtils::writeString, NetworkUtils::writeVec3f); + writeEventKeyframes(buf, animation.keyFrames()); + NetworkUtils.writeMap(buf, animation.bones(), ProtocolUtils::writeString, (byteBuf, bone) -> NetworkUtils.writeCustomBone(byteBuf, bone, version)); NetworkUtils.writeMap(buf, animation.parents(), ProtocolUtils::writeString, ProtocolUtils::writeString); } @@ -122,11 +105,40 @@ public static void writeKeyframe(Keyframe keyframe, ByteBuf buf) { ProtocolUtils.writeList(buf, keyframe.easingArgs(), ExprBytesUtils::writeExpressions); } + static void writeEventKeyframes(ByteBuf buf, Animation.Keyframes keyFrames) { + // Sounds + VarIntUtils.writeVarInt(buf, keyFrames.sounds().length); + for (SoundKeyframeData soundKeyframe : keyFrames.sounds()) { + buf.writeFloat(soundKeyframe.getStartTick()); + ProtocolUtils.writeString(buf, soundKeyframe.getSound()); + } + + // Particles + VarIntUtils.writeVarInt(buf, keyFrames.particles().length); + for (ParticleKeyframeData particleKeyframe : keyFrames.particles()) { + buf.writeFloat(particleKeyframe.getStartTick()); + ProtocolUtils.writeString(buf, particleKeyframe.getEffect()); + ProtocolUtils.writeString(buf, particleKeyframe.getLocator()); + ProtocolUtils.writeString(buf, particleKeyframe.script()); + } + + // Instructions + VarIntUtils.writeVarInt(buf, keyFrames.customInstructions().length); + for (CustomInstructionKeyframeData instructionKeyframe : keyFrames.customInstructions()) { + buf.writeFloat(instructionKeyframe.getStartTick()); + ProtocolUtils.writeString(buf, instructionKeyframe.getInstructions()); + } + } + public static Animation read(ByteBuf buf) { return AnimationBinary.read(buf, CURRENT_VERSION); } public static Animation read(ByteBuf buf, int version) { + if (version >= 6) { + return AnimationBinaryV6.read(buf, version); + } + float length = buf.readFloat(); Animation.LoopType loopType = Animation.LoopType.PLAY_ONCE; if (buf.readBoolean()) { @@ -168,37 +180,8 @@ public static Animation read(ByteBuf buf, int version) { boneAnimations.get("left_item").positionKeyFrames().yKeyframes().replaceAll(AnimationBinary::negateKeyframeExpressions); } - // Sounds - int soundCount = VarIntUtils.readVarInt(buf); - SoundKeyframeData[] sounds = new SoundKeyframeData[soundCount]; - for (int i = 0; i < soundCount; i++) { - float startTick = buf.readFloat(); - String sound = ProtocolUtils.readString(buf); - sounds[i] = new SoundKeyframeData(startTick, sound); - } - - // Particles - int particleCount = VarIntUtils.readVarInt(buf); - ParticleKeyframeData[] particles = new ParticleKeyframeData[particleCount]; - for (int i = 0; i < particleCount; i++) { - float startTick = buf.readFloat(); - String effect = ProtocolUtils.readString(buf); - String locator = ProtocolUtils.readString(buf); - String script = ProtocolUtils.readString(buf); - particles[i] = new ParticleKeyframeData(startTick, effect, locator, script); - } - - // Instructions - int customInstructionCount = VarIntUtils.readVarInt(buf); - CustomInstructionKeyframeData[] customInstructions = new CustomInstructionKeyframeData[customInstructionCount]; - for (int i = 0; i < customInstructionCount; i++) { - float startTick = buf.readFloat(); - String instructions = ProtocolUtils.readString(buf); - customInstructions[i] = new CustomInstructionKeyframeData(startTick, instructions); - } - Animation.Keyframes keyFrames = new Animation.Keyframes(sounds, particles, customInstructions); - - Map pivotBones = NetworkUtils.readMap(buf, ProtocolUtils::readString, NetworkUtils::readVec3f); + Animation.Keyframes keyFrames = readEventKeyframes(buf); + Map pivotBones = NetworkUtils.readMap(buf, ProtocolUtils::readString, byteBuf -> NetworkUtils.readCustomBone(byteBuf, version)); Map parents = NetworkUtils.readMap(buf, ProtocolUtils::readString, ProtocolUtils::readString); return new Animation(data, length, loopType, boneAnimations, keyFrames, pivotBones, parents); @@ -239,6 +222,39 @@ public static List readKeyframeList(ByteBuf buf, boolean shouldStartFr return list; } + static Animation.Keyframes readEventKeyframes(ByteBuf buf) { + // Sounds + int soundCount = VarIntUtils.readVarInt(buf); + SoundKeyframeData[] sounds = new SoundKeyframeData[soundCount]; + for (int i = 0; i < soundCount; i++) { + float startTick = buf.readFloat(); + String sound = ProtocolUtils.readString(buf); + sounds[i] = new SoundKeyframeData(startTick, sound); + } + + // Particles + int particleCount = VarIntUtils.readVarInt(buf); + ParticleKeyframeData[] particles = new ParticleKeyframeData[particleCount]; + for (int i = 0; i < particleCount; i++) { + float startTick = buf.readFloat(); + String effect = ProtocolUtils.readString(buf); + String locator = ProtocolUtils.readString(buf); + String script = ProtocolUtils.readString(buf); + particles[i] = new ParticleKeyframeData(startTick, effect, locator, script); + } + + // Instructions + int customInstructionCount = VarIntUtils.readVarInt(buf); + CustomInstructionKeyframeData[] customInstructions = new CustomInstructionKeyframeData[customInstructionCount]; + for (int i = 0; i < customInstructionCount; i++) { + float startTick = buf.readFloat(); + String instructions = ProtocolUtils.readString(buf); + customInstructions[i] = new CustomInstructionKeyframeData(startTick, instructions); + } + + return new Animation.Keyframes(sounds, particles, customInstructions); + } + private static List negateKeyframes(List keyframes) { keyframes = new ArrayList<>(keyframes); keyframes.replaceAll(AnimationBinary::negateKeyframeExpressions); diff --git a/core/src/main/java/com/zigythebird/playeranimcore/network/AnimationBinaryV6.java b/core/src/main/java/com/zigythebird/playeranimcore/network/AnimationBinaryV6.java new file mode 100644 index 00000000..4de15612 --- /dev/null +++ b/core/src/main/java/com/zigythebird/playeranimcore/network/AnimationBinaryV6.java @@ -0,0 +1,226 @@ +package com.zigythebird.playeranimcore.network; + +import com.zigythebird.playeranimcore.animation.Animation; +import com.zigythebird.playeranimcore.animation.CustomModelBone; +import com.zigythebird.playeranimcore.animation.ExtraAnimationData; +import com.zigythebird.playeranimcore.animation.keyframe.BoneAnimation; +import com.zigythebird.playeranimcore.animation.keyframe.Keyframe; +import com.zigythebird.playeranimcore.animation.keyframe.KeyframeStack; +import com.zigythebird.playeranimcore.easing.EasingType; +import com.zigythebird.playeranimcore.enums.AnimationFormat; +import com.zigythebird.playeranimcore.loading.PlayerAnimatorLoader; +import io.netty.buffer.ByteBuf; +import team.unnamed.mocha.parser.ast.Expression; +import team.unnamed.mocha.parser.ast.FloatExpression; +import team.unnamed.mocha.runtime.IsConstantExpression; +import team.unnamed.mocha.util.ExprBytesUtils; +import team.unnamed.mocha.util.network.ProtocolUtils; +import team.unnamed.mocha.util.network.VarIntUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static com.zigythebird.playeranimcore.molang.MolangLoader.MOCHA_ENGINE; + +final class AnimationBinaryV6 { + + static void write(ByteBuf buf, int version, Animation animation) { + Map data = animation.data().data(); + writeHeader(buf, animation, data); + + VarIntUtils.writeVarInt(buf, animation.boneAnimations().size()); + for (Map.Entry entry : animation.boneAnimations().entrySet()) { + ProtocolUtils.writeString(buf, entry.getKey()); + writeBoneAnimation(buf, entry.getValue(), version); + } + + AnimationBinary.writeEventKeyframes(buf, animation.keyFrames()); + NetworkUtils.writeMap(buf, animation.bones(), ProtocolUtils::writeString, (byteBuf, bone) -> NetworkUtils.writeCustomBone(byteBuf, bone, version)); + NetworkUtils.writeMap(buf, animation.parents(), ProtocolUtils::writeString, ProtocolUtils::writeString); + } + + static Animation read(ByteBuf buf, int version) { + ExtraAnimationData data = new ExtraAnimationData(); + + int flags = VarIntUtils.readVarInt(buf); + boolean shouldPlayAgain = HeaderFlag.SHOULD_PLAY_AGAIN.test(flags); + boolean isHoldOnLastFrame = HeaderFlag.HOLD_ON_LAST_FRAME.test(flags); + AnimationFormat format = HeaderFlag.PLAYER_ANIMATOR.test(flags) ? AnimationFormat.PLAYER_ANIMATOR : AnimationFormat.GECKOLIB; + + data.put(ExtraAnimationData.FORMAT_KEY, format); + if (HeaderFlag.APPLY_BEND.test(flags)) data.put(ExtraAnimationData.APPLY_BEND_TO_OTHER_BONES_KEY, true); + if (!HeaderFlag.EASE_BEFORE.test(flags)) data.put(ExtraAnimationData.EASING_BEFORE_KEY, false); + + float length = buf.readFloat(); + + Animation.LoopType loopType; + if (shouldPlayAgain) { + if (isHoldOnLastFrame) { + loopType = Animation.LoopType.HOLD_ON_LAST_FRAME; + } else { + loopType = Animation.LoopType.returnToTickLoop(buf.readFloat()); + } + } else { + loopType = Animation.LoopType.PLAY_ONCE; + } + + if (HeaderFlag.HAS_BEGIN_TICK.test(flags)) data.put(ExtraAnimationData.BEGIN_TICK_KEY, buf.readFloat()); + if (HeaderFlag.HAS_END_TICK.test(flags)) data.put(ExtraAnimationData.END_TICK_KEY, buf.readFloat()); + + data.put(ExtraAnimationData.UUID_KEY, NetworkUtils.readUuid(buf)); + + boolean isPlayerAnimator = format == AnimationFormat.PLAYER_ANIMATOR; + Map boneAnimations = NetworkUtils.readMap(buf, ProtocolUtils::readString, + buf1 -> readBoneAnimation(buf1, isPlayerAnimator, version)); + + Animation.Keyframes keyFrames = AnimationBinary.readEventKeyframes(buf); + Map pivotBones = NetworkUtils.readMap(buf, ProtocolUtils::readString, byteBuf -> NetworkUtils.readCustomBone(byteBuf, version)); + Map parents = NetworkUtils.readMap(buf, ProtocolUtils::readString, ProtocolUtils::readString); + + return new Animation(data, length, loopType, boneAnimations, keyFrames, pivotBones, parents); + } + + private static void writeHeader(ByteBuf buf, Animation animation, Map data) { + boolean shouldPlayAgain = animation.loopType().shouldPlayAgain(null, animation); + boolean isHoldOnLastFrame = animation.loopType() == Animation.LoopType.HOLD_ON_LAST_FRAME; + AnimationFormat format = (AnimationFormat) data.getOrDefault(ExtraAnimationData.FORMAT_KEY, AnimationFormat.GECKOLIB); + boolean applyBend = (boolean) data.getOrDefault(ExtraAnimationData.APPLY_BEND_TO_OTHER_BONES_KEY, false); + boolean easeBefore = (boolean) data.getOrDefault(ExtraAnimationData.EASING_BEFORE_KEY, true); + float beginTick = (float) data.getOrDefault(ExtraAnimationData.BEGIN_TICK_KEY, Float.NaN); + float endTick = (float) data.getOrDefault(ExtraAnimationData.END_TICK_KEY, Float.NaN); + + int flags = 0; + flags = HeaderFlag.SHOULD_PLAY_AGAIN.set(flags, shouldPlayAgain); + flags = HeaderFlag.HOLD_ON_LAST_FRAME.set(flags, isHoldOnLastFrame); + flags = HeaderFlag.PLAYER_ANIMATOR.set(flags, format == AnimationFormat.PLAYER_ANIMATOR); + flags = HeaderFlag.APPLY_BEND.set(flags, applyBend); + flags = HeaderFlag.EASE_BEFORE.set(flags, easeBefore); + flags = HeaderFlag.HAS_BEGIN_TICK.set(flags, !Float.isNaN(beginTick)); + flags = HeaderFlag.HAS_END_TICK.set(flags, !Float.isNaN(endTick)); + + VarIntUtils.writeVarInt(buf, flags); + buf.writeFloat(animation.length()); + if (shouldPlayAgain && !isHoldOnLastFrame) { + buf.writeFloat(animation.loopType().restartFromTick(null, animation)); + } + if (HeaderFlag.HAS_BEGIN_TICK.test(flags)) buf.writeFloat(beginTick); + if (HeaderFlag.HAS_END_TICK.test(flags)) buf.writeFloat(endTick); + NetworkUtils.writeUuid(buf, animation.uuid()); + } + + private static void writeBoneAnimation(ByteBuf buf, BoneAnimation bone, int version) { + int presenceFlags = 0; + for (BoneChannel ch : BoneChannel.VALUES) { + if (!ch.getKeyframes(bone).isEmpty()) { + presenceFlags |= ch.mask; + } + } + VarIntUtils.writeVarInt(buf, presenceFlags); + for (BoneChannel ch : BoneChannel.VALUES) { + if ((presenceFlags & ch.mask) != 0) { + writeKeyframeList(buf, ch.getKeyframes(bone), version); + } + } + } + + @SuppressWarnings("unchecked") + private static BoneAnimation readBoneAnimation(ByteBuf buf, boolean shouldStartFromDefault, int version) { + int presenceFlags = VarIntUtils.readVarInt(buf); + List[] lists = new List[BoneChannel.VALUES.length]; + for (BoneChannel ch : BoneChannel.VALUES) { + lists[ch.ordinal()] = (presenceFlags & ch.mask) != 0 + ? readKeyframeList(buf, shouldStartFromDefault, ch.isScale, version) + : new ArrayList<>(0); + } + return new BoneAnimation( + new KeyframeStack(lists[0], lists[1], lists[2]), + new KeyframeStack(lists[3], lists[4], lists[5]), + new KeyframeStack(lists[6], lists[7], lists[8]), + lists[9] + ); + } + + private static void writeKeyframeList(ByteBuf buf, List keyframes, int version) { + VarIntUtils.writeVarInt(buf, keyframes.size()); + for (Keyframe keyframe : keyframes) { + writeKeyframe(keyframe, buf, version); + } + } + + private static void writeKeyframe(Keyframe keyframe, ByteBuf buf, int version) { + List endValue = keyframe.endValue(); + boolean isConstant = endValue.size() == 1 && IsConstantExpression.test(endValue.getFirst()); + boolean hasEasingArgs = false; + for (List inner : keyframe.easingArgs()) { + if (!inner.isEmpty()) { + hasEasingArgs = true; + break; + } + } + + int flags = 0; + if (isConstant) flags |= KeyframeFlag.IS_CONSTANT.mask; + if (hasEasingArgs) flags |= KeyframeFlag.HAS_EASING_ARGS.mask; + if (keyframe.length() == 0.0f) flags |= KeyframeFlag.LENGTH_ZERO.mask; + else if (keyframe.length() == 1.0f) flags |= KeyframeFlag.LENGTH_ONE.mask; + VarIntUtils.writeVarInt(buf, KeyframeFlag.pack(keyframe.easingType().id, flags, version)); + + if (isConstant) { + buf.writeFloat(MOCHA_ENGINE.eval(endValue)); + } else { + ExprBytesUtils.writeExpressions(endValue, buf); + } + + if ((flags & (KeyframeFlag.LENGTH_ZERO.mask | KeyframeFlag.LENGTH_ONE.mask)) == 0) { + buf.writeFloat(keyframe.length()); + } + + if (hasEasingArgs) { + ProtocolUtils.writeList(buf, keyframe.easingArgs(), ExprBytesUtils::writeExpressions); + } + } + + private static List readKeyframeList(ByteBuf buf, boolean shouldStartFromDefault, boolean isScale, int version) { + int count = VarIntUtils.readVarInt(buf); + List list = new ArrayList<>(count); + + for (int i = 0; i < count; i++) { + int combined = VarIntUtils.readVarInt(buf); + int easingId = KeyframeFlag.unpackEasing(combined, version); + int flags = KeyframeFlag.unpackFlags(combined, version); + boolean isConstant = (flags & KeyframeFlag.IS_CONSTANT.mask) != 0; + boolean hasEasingArgs = (flags & KeyframeFlag.HAS_EASING_ARGS.mask) != 0; + + List endValue; + if (isConstant) { + endValue = List.of(FloatExpression.of(buf.readFloat())); + } else { + endValue = ExprBytesUtils.readExpressions(buf); + } + + float length; + if ((flags & KeyframeFlag.LENGTH_ZERO.mask) != 0) length = 0.0f; + else if ((flags & KeyframeFlag.LENGTH_ONE.mask) != 0) length = 1.0f; + else length = buf.readFloat(); + + List startValue = list.isEmpty() + ? (shouldStartFromDefault ? (isScale ? PlayerAnimatorLoader.ONE : PlayerAnimatorLoader.ZERO) : endValue) + : list.getLast().endValue(); + EasingType easingType = EasingType.fromId((byte) easingId); + List> easingArgs; + if (hasEasingArgs) { + easingArgs = ProtocolUtils.readList(buf, ExprBytesUtils::readExpressions); + } else if (shouldStartFromDefault && i > 0) { + easingArgs = Collections.singletonList(new ArrayList<>(0)); + } else { + easingArgs = new ArrayList<>(0); + } + + list.add(new Keyframe(length, startValue, endValue, easingType, easingArgs)); + } + + return list; + } +} diff --git a/core/src/main/java/com/zigythebird/playeranimcore/network/BoneChannel.java b/core/src/main/java/com/zigythebird/playeranimcore/network/BoneChannel.java new file mode 100644 index 00000000..f22faf58 --- /dev/null +++ b/core/src/main/java/com/zigythebird/playeranimcore/network/BoneChannel.java @@ -0,0 +1,40 @@ +package com.zigythebird.playeranimcore.network; + +import com.zigythebird.playeranimcore.animation.keyframe.BoneAnimation; +import com.zigythebird.playeranimcore.animation.keyframe.Keyframe; +import com.zigythebird.playeranimcore.animation.keyframe.KeyframeStack; +import com.zigythebird.playeranimcore.enums.Axis; + +import java.util.List; +import java.util.function.Function; + +enum BoneChannel { + ROTATION_X(BoneAnimation::rotationKeyFrames, Axis.X, false), + ROTATION_Y(BoneAnimation::rotationKeyFrames, Axis.Y, false), + ROTATION_Z(BoneAnimation::rotationKeyFrames, Axis.Z, false), + POSITION_X(BoneAnimation::positionKeyFrames, Axis.X, false), + POSITION_Y(BoneAnimation::positionKeyFrames, Axis.Y, false), + POSITION_Z(BoneAnimation::positionKeyFrames, Axis.Z, false), + SCALE_X(BoneAnimation::scaleKeyFrames, Axis.X, true), + SCALE_Y(BoneAnimation::scaleKeyFrames, Axis.Y, true), + SCALE_Z(BoneAnimation::scaleKeyFrames, Axis.Z, true), + BEND(null, null, false); + + static final BoneChannel[] VALUES = values(); + + final int mask = 1 << ordinal(); + final Function stackAccessor; + final Axis axis; + final boolean isScale; + + BoneChannel(Function stackAccessor, Axis axis, boolean isScale) { + this.stackAccessor = stackAccessor; + this.axis = axis; + this.isScale = isScale; + } + + List getKeyframes(BoneAnimation bone) { + if (this == BEND) return bone.bendKeyFrames(); + return stackAccessor.apply(bone).getKeyFramesForAxis(axis); + } +} diff --git a/core/src/main/java/com/zigythebird/playeranimcore/network/CustomModelUtils.java b/core/src/main/java/com/zigythebird/playeranimcore/network/CustomModelUtils.java new file mode 100644 index 00000000..4d738cfb --- /dev/null +++ b/core/src/main/java/com/zigythebird/playeranimcore/network/CustomModelUtils.java @@ -0,0 +1,232 @@ +package com.zigythebird.playeranimcore.network; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import io.netty.buffer.ByteBuf; +import team.unnamed.mocha.util.network.ProtocolUtils; +import team.unnamed.mocha.util.network.VarIntUtils; + +class CustomModelUtils { + private static final String[] DIRECTION_NAMES = {"down", "up", "north", "south", "west", "east"}; + private static final String[] AXIS_NAMES = {"x", "y", "z"}; + + /** + * ── BlockElement ── + * elementFlags (varint): + * bit 0: hasFrom (almost always set → low bit) + * bit 1: hasTo (almost always set → low bit) + * bit 2: hasRotation + * bit 3: noShade (bit set = shade is false, default true → 0) + * bits 4-7: lightEmission (0-15) + */ + static void writeBlockElement(ByteBuf buf, JsonObject element, int version) { + boolean hasFrom = element.has("from"); + boolean hasTo = element.has("to"); + boolean hasRotation = element.has("rotation"); + boolean noShade = element.has("shade") && !element.get("shade").getAsBoolean(); + int lightEmission = element.has("light_emission") ? element.get("light_emission").getAsInt() : 0; + + int flags = 0; + if (hasFrom) flags |= 1; + if (hasTo) flags |= 2; + if (hasRotation) flags |= 4; + if (noShade) flags |= 8; + flags |= (lightEmission & 0xF) << 4; + VarIntUtils.writeVarInt(buf, flags); + + if (hasFrom) writeJsonVec3f(buf, element.getAsJsonArray("from")); + if (hasTo) writeJsonVec3f(buf, element.getAsJsonArray("to")); + + JsonObject faces = element.has("faces") ? element.getAsJsonObject("faces") : null; + int facesBitmask = 0; + if (faces != null) { + for (int d = 0; d < 6; d++) { + if (faces.has(DIRECTION_NAMES[d])) facesBitmask |= (1 << d); + } + } + VarIntUtils.writeVarInt(buf, facesBitmask); + + for (int d = 0; d < 6; d++) { + if ((facesBitmask & (1 << d)) == 0) continue; + writeBlockElementFace(buf, faces.getAsJsonObject(DIRECTION_NAMES[d]), version); + } + + if (hasRotation) { + writeBlockElementRotation(buf, element.getAsJsonObject("rotation"), version); + } + } + + static JsonObject readBlockElement(ByteBuf buf, int version) { + JsonObject element = new JsonObject(); + + int flags = VarIntUtils.readVarInt(buf); + boolean hasFrom = (flags & 1) != 0; + boolean hasTo = (flags & 2) != 0; + boolean hasRotation = (flags & 4) != 0; + boolean noShade = (flags & 8) != 0; + int lightEmission = (flags >> 4) & 0xF; + + if (hasFrom) element.add("from", readJsonVec3f(buf)); + if (hasTo) element.add("to", readJsonVec3f(buf)); + if (noShade) element.addProperty("shade", false); + if (lightEmission != 0) element.addProperty("light_emission", lightEmission); + + int facesBitmask = VarIntUtils.readVarInt(buf); + if (facesBitmask != 0) { + JsonObject faces = new JsonObject(); + for (int d = 0; d < 6; d++) { + if ((facesBitmask & (1 << d)) == 0) continue; + faces.add(DIRECTION_NAMES[d], readBlockElementFace(buf, version)); + } + element.add("faces", faces); + } + + if (hasRotation) { + element.add("rotation", readBlockElementRotation(buf, version)); + } + + return element; + } + + /** + * ── BlockElementFace ── + * faceFlags (varint): + * bit 0: hasTexture + * bit 1: hasUVs + * bit 2: hasTintIndex + * bits 3-5: cullForDirection (0-5=dir, 7=none) + * bit 6: hasRotation + */ + private static void writeBlockElementFace(ByteBuf buf, JsonObject face, int version) { + boolean hasTexture = face.has("texture"); + boolean hasUVs = face.has("uv"); + int tintIndex = face.has("tintindex") ? face.get("tintindex").getAsInt() : -1; + boolean hasTint = tintIndex != -1; + + int cullDir = 7; + if (face.has("cullface")) { + String cullName = face.get("cullface").getAsString(); + for (int i = 0; i < 6; i++) { + if (DIRECTION_NAMES[i].equals(cullName)) { cullDir = i; break; } + } + } + boolean hasRotation = face.has("rotation"); + + int faceFlags = (hasTexture ? 1 : 0) | (hasUVs ? (1 << 1) : 0) | (hasTint ? (1 << 2) : 0) + | ((cullDir & 0x7) << 3) | (hasRotation ? (1 << 6) : 0); + VarIntUtils.writeVarInt(buf, faceFlags); + + if (hasTexture) ProtocolUtils.writeString(buf, face.get("texture").getAsString()); + if (hasTint) VarIntUtils.writeVarInt(buf, tintIndex); + + if (hasUVs) { + JsonArray uv = face.getAsJsonArray("uv"); + buf.writeFloat(uv.get(0).getAsFloat()); + buf.writeFloat(uv.get(1).getAsFloat()); + buf.writeFloat(uv.get(2).getAsFloat()); + buf.writeFloat(uv.get(3).getAsFloat()); + } + + if (hasRotation) VarIntUtils.writeVarInt(buf, face.get("rotation").getAsInt()); + } + + private static JsonObject readBlockElementFace(ByteBuf buf, int version) { + int faceFlags = VarIntUtils.readVarInt(buf); + boolean hasTexture = (faceFlags & 1) != 0; + boolean hasUVs = (faceFlags & (1 << 1)) != 0; + boolean hasTint = (faceFlags & (1 << 2)) != 0; + int cullDir = (faceFlags >> 3) & 0x7; + boolean hasRotation = (faceFlags & (1 << 6)) != 0; + + JsonObject face = new JsonObject(); + + if (hasTexture) face.addProperty("texture", ProtocolUtils.readString(buf)); + if (cullDir < 6) face.addProperty("cullface", DIRECTION_NAMES[cullDir]); + if (hasTint) face.addProperty("tintindex", VarIntUtils.readVarInt(buf)); + + if (hasUVs) { + JsonArray uv = new JsonArray(4); + uv.add(buf.readFloat()); + uv.add(buf.readFloat()); + uv.add(buf.readFloat()); + uv.add(buf.readFloat()); + face.add("uv", uv); + } + + if (hasRotation) face.addProperty("rotation", VarIntUtils.readVarInt(buf)); + + return face; + } + + /** + * ── BlockElementRotation ── + * rotFlags (varint): bit0=isEuler, bit1=rescale + */ + private static void writeBlockElementRotation(ByteBuf buf, JsonObject rotation, int version) { + writeJsonVec3f(buf, rotation.getAsJsonArray("origin")); + + // MC logic: euler when axis/angle are absent + boolean isEuler = !rotation.has("axis") && !rotation.has("angle"); + boolean rescale = rotation.has("rescale") && rotation.get("rescale").getAsBoolean(); + + int rotFlags = 0; + if (isEuler) rotFlags |= 1; + if (rescale) rotFlags |= 2; + VarIntUtils.writeVarInt(buf, rotFlags); + + if (isEuler) { + buf.writeFloat(rotation.has("x") ? rotation.get("x").getAsFloat() : 0f); + buf.writeFloat(rotation.has("y") ? rotation.get("y").getAsFloat() : 0f); + buf.writeFloat(rotation.has("z") ? rotation.get("z").getAsFloat() : 0f); + } else { + String axisName = rotation.get("axis").getAsString(); + int axis = 0; + for (int i = 0; i < 3; i++) { + if (AXIS_NAMES[i].equals(axisName)) { axis = i; break; } + } + VarIntUtils.writeVarInt(buf, axis); + buf.writeFloat(rotation.get("angle").getAsFloat()); + } + } + + private static JsonObject readBlockElementRotation(ByteBuf buf, int version) { + JsonObject rotation = new JsonObject(); + rotation.add("origin", readJsonVec3f(buf)); + + int rotFlags = VarIntUtils.readVarInt(buf); + boolean isEuler = (rotFlags & 1) != 0; + boolean rescale = (rotFlags & 2) != 0; + + if (isEuler) { + float x = buf.readFloat(); + float y = buf.readFloat(); + float z = buf.readFloat(); + rotation.addProperty("x", x); + rotation.addProperty("y", y); + rotation.addProperty("z", z); + } else { + int axis = VarIntUtils.readVarInt(buf); + float angle = buf.readFloat(); + rotation.addProperty("axis", AXIS_NAMES[axis]); + rotation.addProperty("angle", angle); + } + + if (rescale) rotation.addProperty("rescale", true); + + return rotation; + } + + private static void writeJsonVec3f(ByteBuf buf, JsonArray arr) { + buf.writeFloat(arr.get(0).getAsFloat()); + buf.writeFloat(arr.get(1).getAsFloat()); + buf.writeFloat(arr.get(2).getAsFloat()); + } + + private static JsonArray readJsonVec3f(ByteBuf buf) { + JsonArray arr = new JsonArray(3); + arr.add(buf.readFloat()); + arr.add(buf.readFloat()); + arr.add(buf.readFloat()); + return arr; + } +} diff --git a/core/src/main/java/com/zigythebird/playeranimcore/network/HeaderFlag.java b/core/src/main/java/com/zigythebird/playeranimcore/network/HeaderFlag.java new file mode 100644 index 00000000..c60c8851 --- /dev/null +++ b/core/src/main/java/com/zigythebird/playeranimcore/network/HeaderFlag.java @@ -0,0 +1,21 @@ +package com.zigythebird.playeranimcore.network; + +enum HeaderFlag { + SHOULD_PLAY_AGAIN, + HOLD_ON_LAST_FRAME, + PLAYER_ANIMATOR, + APPLY_BEND, + EASE_BEFORE, + HAS_BEGIN_TICK, + HAS_END_TICK; + + final int mask = 1 << ordinal(); + + boolean test(int flags) { + return (flags & mask) != 0; + } + + int set(int flags, boolean condition) { + return condition ? flags | mask : flags; + } +} diff --git a/core/src/main/java/com/zigythebird/playeranimcore/network/KeyframeFlag.java b/core/src/main/java/com/zigythebird/playeranimcore/network/KeyframeFlag.java new file mode 100644 index 00000000..35f01a14 --- /dev/null +++ b/core/src/main/java/com/zigythebird/playeranimcore/network/KeyframeFlag.java @@ -0,0 +1,44 @@ +package com.zigythebird.playeranimcore.network; + +enum KeyframeFlag { + IS_CONSTANT(6), + HAS_EASING_ARGS(6), + LENGTH_ZERO(6), + LENGTH_ONE(6); + + final int sinceVersion; + final int mask = 1 << ordinal(); + + KeyframeFlag(int sinceVersion) { + this.sinceVersion = sinceVersion; + } + + static int flagBitsForVersion(int version) { + int bits = 0; + for (KeyframeFlag flag : values()) { + if (flag.sinceVersion <= version) bits = flag.ordinal() + 1; + } + return bits; + } + + static int pack(int easingId, int flags, int version) { + return (easingId << flagBitsForVersion(version)) | flags; + } + + static int unpackEasing(int combined, int version) { + return combined >>> flagBitsForVersion(version); + } + + static int unpackFlags(int combined, int version) { + return combined & ((1 << flagBitsForVersion(version)) - 1); + } + + static { + int lastVersion = 0; + for (KeyframeFlag flag : values()) { + if (flag.sinceVersion < lastVersion) + throw new AssertionError("KeyframeFlag." + flag.name() + " sinceVersion " + flag.sinceVersion + " is less than previous " + lastVersion + ". Flags must be ordered by version."); + lastVersion = flag.sinceVersion; + } + } +} diff --git a/core/src/main/java/com/zigythebird/playeranimcore/network/LegacyAnimationBinary.java b/core/src/main/java/com/zigythebird/playeranimcore/network/LegacyAnimationBinary.java index 7cea525b..29cb7d40 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/network/LegacyAnimationBinary.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/network/LegacyAnimationBinary.java @@ -256,6 +256,9 @@ public static Animation read(ByteBuf buf, int version) throws IOException { boneAnimations.put("right_leg", readPart(buf, "right_leg", new BoneAnimation(), version, keyframeSize, easeBefore)); boneAnimations.put("left_leg", readPart(buf, "left_leg", new BoneAnimation(), version, keyframeSize, easeBefore)); } + // Remove empty phantom bones (v1 always creates 6 bones even if they have no data) + boneAnimations.values().removeIf(bone -> !bone.hasKeyframes()); + BoneAnimation body = boneAnimations.get("body"); if (body != null && !body.bendKeyFrames().isEmpty()) { BoneAnimation torso = boneAnimations.computeIfAbsent("torso", name -> new BoneAnimation()); diff --git a/core/src/main/java/com/zigythebird/playeranimcore/network/NetworkUtils.java b/core/src/main/java/com/zigythebird/playeranimcore/network/NetworkUtils.java index 33f8e970..7755fea8 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/network/NetworkUtils.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/network/NetworkUtils.java @@ -1,9 +1,17 @@ package com.zigythebird.playeranimcore.network; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.zigythebird.playeranimcore.animation.CustomModelBone; import com.zigythebird.playeranimcore.math.Vec3f; import io.netty.buffer.ByteBuf; +import org.redlance.platformtools.webp.decoder.DecodedImage; +import org.redlance.platformtools.webp.decoder.PlatformWebPDecoder; +import org.redlance.platformtools.webp.encoder.PlatformWebPEncoder; import team.unnamed.mocha.util.network.VarIntUtils; +import java.io.IOException; +import java.io.UncheckedIOException; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -30,6 +38,87 @@ public static void writeMap(ByteBuf buf, Map map, BiConsumer= 6) { + int boneFlags = VarIntUtils.readVarInt(buf); + + if ((boneFlags & 1) != 0) { + boolean isWebP = (boneFlags & 2) != 0; + + int len = VarIntUtils.readVarInt(buf); + byte[] rawTexture = new byte[len]; + buf.readBytes(rawTexture); + + try { + if (isWebP) { + texture = PlatformWebPDecoder.INSTANCE.decode(rawTexture); + } else { + texture = DecodedImage.fromPng(rawTexture); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + if ((boneFlags & 4) != 0) { + int count = VarIntUtils.readVarInt(buf); + elements = new JsonArray(count); + for (int i = 0; i < count; i++) { + elements.add(CustomModelUtils.readBlockElement(buf, version)); + } + } + } + + return new CustomModelBone(pivot, texture, elements); + } + + public static void writeCustomBone(ByteBuf buf, CustomModelBone bone, int version) { + writeVec3f(buf, bone.pivot()); + + if (version >= 6) { + boolean isWebPEncoderAvailable = PlatformWebPEncoder.INSTANCE.isAvailable(); + + int boneFlags = 0; + if (bone.texture() != null) { + boneFlags |= 1; + if (isWebPEncoderAvailable) boneFlags |= 2; + } + if (bone.elements() != null) boneFlags |= 4; + VarIntUtils.writeVarInt(buf, boneFlags); + + if (bone.texture() != null) { + byte[] imageData; + try { + if (isWebPEncoderAvailable) { + imageData = PlatformWebPEncoder.INSTANCE.encodeLossless(bone.texture()); + } else { + imageData = bone.texture().toPng(); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + VarIntUtils.writeVarInt(buf, imageData.length); + buf.writeBytes(imageData); + } + + if (bone.elements() != null) { + VarIntUtils.writeVarInt(buf, bone.elements().size()); + for (JsonElement el : bone.elements()) { + CustomModelUtils.writeBlockElement(buf, el.getAsJsonObject(), version); + } + } + } + } + public static Vec3f readVec3f(ByteBuf buf) { float x = buf.readFloat(); float y = buf.readFloat(); diff --git a/core/src/main/java/com/zigythebird/playeranimcore/util/MatrixUtil.java b/core/src/main/java/com/zigythebird/playeranimcore/util/MatrixUtil.java index 561cf152..e17ab1db 100644 --- a/core/src/main/java/com/zigythebird/playeranimcore/util/MatrixUtil.java +++ b/core/src/main/java/com/zigythebird/playeranimcore/util/MatrixUtil.java @@ -1,6 +1,6 @@ package com.zigythebird.playeranimcore.util; -import com.zigythebird.playeranimcore.bones.PivotBone; +import com.zigythebird.playeranimcore.bones.CustomBone; import com.zigythebird.playeranimcore.bones.PlayerAnimBone; import com.zigythebird.playeranimcore.math.Vec3f; import org.joml.Matrix4f; @@ -14,16 +14,16 @@ */ public class MatrixUtil { public static void translateMatrixForBone(Matrix4f matrix, PlayerAnimBone bone) { - matrix.translate(-bone.getPosX(), bone.getPosY(), -bone.getPosZ()); + matrix.translate(-bone.position.x, bone.position.y, -bone.position.z); } public static void rotateMatrixAroundBone(Matrix4f matrix, PlayerAnimBone bone) { - if (bone.getRotZ() != 0 || bone.getRotY() != 0 || bone.getRotX() != 0) - matrix.rotateZ(bone.getRotZ()).rotateY(bone.getRotY()).rotateX(bone.getRotX()); + if (bone.rotation.z != 0 || bone.rotation.y != 0 || bone.rotation.x != 0) + matrix.rotateZYX(bone.rotation); } public static void scaleMatrixForBone(Matrix4f matrix, PlayerAnimBone bone) { - matrix.scale(bone.getScaleX(), bone.getScaleY(), bone.getScaleZ()); + matrix.scale(bone.scale.x, bone.scale.y, bone.scale.z); } public static void translateToPivotPoint(Matrix4f matrix, Vec3f pivot) { @@ -46,21 +46,16 @@ public static void applyParentsToChild(PlayerAnimBone child, Iterable Stream loadServices(Class serviceClass) { + ModuleLayer layer = serviceClass.getModule().getLayer(); // NeoForge compat? + + ServiceLoader loader = layer == null ? ServiceLoader.load(serviceClass, + serviceClass.getClassLoader() + ) : ServiceLoader.load(layer, serviceClass); + + return loader.stream() + .map(ServiceLoader.Provider::get) + .filter(ActiveService::isActive); + } + + public static T loadService(Class serviceClass) { + return ServiceUtil.loadServices(serviceClass).findAny().orElseThrow(); + } + + public interface ActiveService { + boolean isActive(); + } +} diff --git a/core/src/test/java/com/zigythebird/playeranimcore/network/CustomModelBinaryTest.java b/core/src/test/java/com/zigythebird/playeranimcore/network/CustomModelBinaryTest.java new file mode 100644 index 00000000..460531c7 --- /dev/null +++ b/core/src/test/java/com/zigythebird/playeranimcore/network/CustomModelBinaryTest.java @@ -0,0 +1,365 @@ +package com.zigythebird.playeranimcore.network; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.zigythebird.playeranimcore.animation.Animation; +import com.zigythebird.playeranimcore.animation.CustomModelBone; +import com.zigythebird.playeranimcore.loading.UniversalAnimLoader; +import com.zigythebird.playeranimcore.math.Vec3f; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +public class CustomModelBinaryTest { + + private static JsonArray vec3(float x, float y, float z) { + JsonArray arr = new JsonArray(3); + arr.add(x); + arr.add(y); + arr.add(z); + return arr; + } + + private static JsonArray uv(float minU, float minV, float maxU, float maxV) { + JsonArray arr = new JsonArray(4); + arr.add(minU); + arr.add(minV); + arr.add(maxU); + arr.add(maxV); + return arr; + } + + private static JsonObject makeFace(String texture, String cullface, float[] uvs, int tintIndex, int rotation) { + JsonObject face = new JsonObject(); + if (texture != null) face.addProperty("texture", texture); + if (cullface != null) face.addProperty("cullface", cullface); + if (uvs != null) face.add("uv", uv(uvs[0], uvs[1], uvs[2], uvs[3])); + if (tintIndex != -1) face.addProperty("tintindex", tintIndex); + if (rotation != 0) face.addProperty("rotation", rotation); + return face; + } + + private static void assertRoundTrip(CustomModelBone bone, int version) { + ByteBuf buf = Unpooled.buffer(); + NetworkUtils.writeCustomBone(buf, bone, version); + CustomModelBone read = NetworkUtils.readCustomBone(buf, version); + + Assertions.assertEquals(bone.pivot(), read.pivot(), "pivot mismatch"); + Assertions.assertArrayEquals(bone.texture(), read.texture(), "texture mismatch"); + + if (bone.elements() == null) { + Assertions.assertNull(read.elements(), "expected null elements"); + } else { + Assertions.assertNotNull(read.elements(), "expected non-null elements"); + Assertions.assertEquals(bone.elements().size(), read.elements().size(), "elements count mismatch"); + for (int i = 0; i < bone.elements().size(); i++) { + Assertions.assertEquals( + bone.elements().get(i), + read.elements().get(i), + "element " + i + " mismatch" + ); + } + } + + Assertions.assertFalse(buf.isReadable(), "buffer has leftover bytes"); + buf.release(); + } + + // ── Tests ── + + @Test + @DisplayName("Bone with only pivot (version < 6)") + void pivotOnlyOldVersion() { + CustomModelBone bone = new CustomModelBone(new Vec3f(1, 2, 3), null, null); + assertRoundTrip(bone, 5); + } + + @Test + @DisplayName("Bone with only pivot (version 6)") + void pivotOnly() { + CustomModelBone bone = new CustomModelBone(new Vec3f(1, 2, 3), null, null); + assertRoundTrip(bone, 6); + } + + @Test + @DisplayName("Bone with texture bytes") + void boneWithTexture() { + byte[] tex = {0x00, 0x01, 0x02, (byte) 0xFF}; + CustomModelBone bone = new CustomModelBone(new Vec3f(0, 0, 0), tex, null); + assertRoundTrip(bone, 6); + } + + @Test + @DisplayName("Full element: from, to, 6 faces with all fields") + void fullElement() { + JsonObject element = new JsonObject(); + element.add("from", vec3(0, 0, 0)); + element.add("to", vec3(16, 16, 16)); + + JsonObject faces = new JsonObject(); + String[] dirs = {"down", "up", "north", "south", "west", "east"}; + for (String dir : dirs) { + faces.add(dir, makeFace("#all", dir, new float[]{0, 0, 16, 16}, -1, 0)); + } + element.add("faces", faces); + + JsonArray elements = new JsonArray(); + elements.add(element); + + CustomModelBone bone = new CustomModelBone(new Vec3f(8, 8, 8), null, elements); + assertRoundTrip(bone, 6); + } + + @Test + @DisplayName("Element with shade=false and light_emission") + void shadeAndLightEmission() { + JsonObject element = new JsonObject(); + element.add("from", vec3(0, 0, 0)); + element.add("to", vec3(8, 8, 8)); + element.addProperty("shade", false); + element.addProperty("light_emission", 15); + + JsonObject faces = new JsonObject(); + faces.add("up", makeFace("#top", null, null, -1, 0)); + element.add("faces", faces); + + JsonArray elements = new JsonArray(); + elements.add(element); + + CustomModelBone bone = new CustomModelBone(new Vec3f(0, 0, 0), null, elements); + assertRoundTrip(bone, 6); + } + + @Test + @DisplayName("Face with tintindex, rotation, UV") + void faceAllFields() { + JsonObject element = new JsonObject(); + element.add("from", vec3(0, 0, 0)); + element.add("to", vec3(16, 16, 16)); + + JsonObject faces = new JsonObject(); + faces.add("north", makeFace("#side", "north", new float[]{0, 0, 16, 16}, 0, 270)); + element.add("faces", faces); + + JsonArray elements = new JsonArray(); + elements.add(element); + + CustomModelBone bone = new CustomModelBone(new Vec3f(8, 8, 8), null, elements); + assertRoundTrip(bone, 6); + } + + @Test + @DisplayName("Face without texture (minimal)") + void faceNoTexture() { + JsonObject element = new JsonObject(); + element.add("from", vec3(0, 0, 0)); + element.add("to", vec3(16, 16, 16)); + + JsonObject faces = new JsonObject(); + JsonObject face = new JsonObject(); + face.add("uv", uv(0, 0, 16, 16)); + faces.add("up", face); + element.add("faces", faces); + + JsonArray elements = new JsonArray(); + elements.add(element); + + CustomModelBone bone = new CustomModelBone(new Vec3f(0, 0, 0), null, elements); + assertRoundTrip(bone, 6); + } + + @Test + @DisplayName("Single-axis rotation with rescale") + void singleAxisRotation() { + JsonObject element = new JsonObject(); + element.add("from", vec3(0, 0, 0)); + element.add("to", vec3(16, 16, 16)); + + JsonObject rot = new JsonObject(); + rot.add("origin", vec3(8, 8, 8)); + rot.addProperty("axis", "y"); + rot.addProperty("angle", 22.5f); + rot.addProperty("rescale", true); + element.add("rotation", rot); + + JsonObject faces = new JsonObject(); + faces.add("north", makeFace("#side", null, null, -1, 0)); + element.add("faces", faces); + + JsonArray elements = new JsonArray(); + elements.add(element); + + CustomModelBone bone = new CustomModelBone(new Vec3f(8, 8, 8), null, elements); + assertRoundTrip(bone, 6); + } + + @Test + @DisplayName("Euler XYZ rotation") + void eulerRotation() { + JsonObject element = new JsonObject(); + element.add("from", vec3(0, 0, 0)); + element.add("to", vec3(16, 16, 16)); + + JsonObject rot = new JsonObject(); + rot.add("origin", vec3(8, 8, 8)); + rot.addProperty("x", 45f); + rot.addProperty("y", 0f); + rot.addProperty("z", -30f); + element.add("rotation", rot); + + JsonObject faces = new JsonObject(); + faces.add("up", makeFace("#top", null, null, -1, 0)); + element.add("faces", faces); + + JsonArray elements = new JsonArray(); + elements.add(element); + + CustomModelBone bone = new CustomModelBone(new Vec3f(0, 0, 0), null, elements); + assertRoundTrip(bone, 6); + } + + @Test + @DisplayName("Element without from/to (minimal)") + void elementMinimal() { + JsonObject element = new JsonObject(); + // no from, no to, no faces, no rotation + + JsonArray elements = new JsonArray(); + elements.add(element); + + CustomModelBone bone = new CustomModelBone(new Vec3f(0, 0, 0), null, elements); + assertRoundTrip(bone, 6); + } + + @Test + @DisplayName("Multiple elements") + void multipleElements() { + JsonArray elements = new JsonArray(); + + for (int i = 0; i < 3; i++) { + JsonObject element = new JsonObject(); + element.add("from", vec3(i, i, i)); + element.add("to", vec3(i + 8, i + 8, i + 8)); + + JsonObject faces = new JsonObject(); + faces.add("north", makeFace("#tex" + i, "north", new float[]{0, 0, 16, 16}, -1, 0)); + element.add("faces", faces); + + elements.add(element); + } + + CustomModelBone bone = new CustomModelBone(new Vec3f(8, 8, 8), new byte[]{1, 2, 3}, elements); + assertRoundTrip(bone, 6); + } + + @Test + @DisplayName("All directions for cullface") + void allCullfaceDirections() { + String[] dirs = {"down", "up", "north", "south", "west", "east"}; + + for (String dir : dirs) { + JsonObject element = new JsonObject(); + element.add("from", vec3(0, 0, 0)); + element.add("to", vec3(16, 16, 16)); + + JsonObject faces = new JsonObject(); + faces.add(dir, makeFace("#tex", dir, null, -1, 0)); + element.add("faces", faces); + + JsonArray elements = new JsonArray(); + elements.add(element); + + CustomModelBone bone = new CustomModelBone(new Vec3f(0, 0, 0), null, elements); + assertRoundTrip(bone, 6); + } + } + + @Test + @DisplayName("All axis for single-axis rotation") + void allAxes() { + String[] axes = {"x", "y", "z"}; + + for (String axis : axes) { + JsonObject element = new JsonObject(); + element.add("from", vec3(0, 0, 0)); + element.add("to", vec3(16, 16, 16)); + + JsonObject rot = new JsonObject(); + rot.add("origin", vec3(8, 8, 8)); + rot.addProperty("axis", axis); + rot.addProperty("angle", 45f); + element.add("rotation", rot); + + JsonObject faces = new JsonObject(); + faces.add("up", makeFace("#top", null, null, -1, 0)); + element.add("faces", faces); + + JsonArray elements = new JsonArray(); + elements.add(element); + + CustomModelBone bone = new CustomModelBone(new Vec3f(0, 0, 0), null, elements); + assertRoundTrip(bone, 6); + } + } + + @Test + @DisplayName("Real parsed bone from cmm_bone_test.json") + void realParsedBone() throws IOException { + try (InputStream is = CustomModelBinaryTest.class.getResourceAsStream("/cmm_bone_test.json")) { + Assertions.assertNotNull(is, "cmm_bone_test.json not found"); + Map animations = UniversalAnimLoader.loadAnimations(is); + + Assertions.assertFalse(animations.isEmpty(), "no animations loaded"); + + Animation animation = animations.values().iterator().next(); + Assertions.assertFalse(animation.bones().isEmpty(), "no bones in animation"); + + for (Map.Entry entry : animation.bones().entrySet()) { + CustomModelBone bone = entry.getValue(); + + Assertions.assertNotNull(bone.pivot(), "pivot is null for bone " + entry.getKey()); + Assertions.assertNotNull(bone.texture(), "texture is null for bone " + entry.getKey()); + Assertions.assertNotNull(bone.elements(), "elements is null for bone " + entry.getKey()); + Assertions.assertFalse(bone.elements().isEmpty(), "elements empty for bone " + entry.getKey()); + + assertRoundTrip(bone, 6); + } + } + } + + @Test + @DisplayName("Buffer fully consumed after read") + void bufferFullyConsumed() { + JsonObject element = new JsonObject(); + element.add("from", vec3(1, 2, 3)); + element.add("to", vec3(4, 5, 6)); + element.addProperty("shade", false); + element.addProperty("light_emission", 7); + + JsonObject rot = new JsonObject(); + rot.add("origin", vec3(0, 0, 0)); + rot.addProperty("x", 10f); + rot.addProperty("y", 20f); + rot.addProperty("z", 30f); + rot.addProperty("rescale", true); + element.add("rotation", rot); + + JsonObject faces = new JsonObject(); + faces.add("down", makeFace("#bottom", "down", new float[]{0, 0, 16, 16}, 2, 90)); + faces.add("up", makeFace("#top", "up", new float[]{0, 0, 16, 16}, 0, 180)); + faces.add("north", makeFace("#side", "north", new float[]{0, 0, 16, 16}, -1, 0)); + element.add("faces", faces); + + JsonArray elements = new JsonArray(); + elements.add(element); + + CustomModelBone bone = new CustomModelBone(new Vec3f(4, 5, 6), new byte[]{10, 20, 30}, elements); + assertRoundTrip(bone, 6); + } +} diff --git a/core/src/test/java/io/github/kosmx/emotes/testing/common/AnimationBinaryTest.java b/core/src/test/java/io/github/kosmx/emotes/testing/common/AnimationBinaryTest.java index f3055c72..b6508e1d 100644 --- a/core/src/test/java/io/github/kosmx/emotes/testing/common/AnimationBinaryTest.java +++ b/core/src/test/java/io/github/kosmx/emotes/testing/common/AnimationBinaryTest.java @@ -1,6 +1,7 @@ package io.github.kosmx.emotes.testing.common; import com.zigythebird.playeranimcore.animation.Animation; +import com.zigythebird.playeranimcore.animation.keyframe.BoneAnimation; import com.zigythebird.playeranimcore.network.AnimationBinary; import com.zigythebird.playeranimcore.network.LegacyAnimationBinary; import io.netty.buffer.ByteBuf; @@ -10,11 +11,14 @@ import org.junit.jupiter.api.Test; import java.io.IOException; +import java.util.List; /** * Test network data sending and receiving */ public class AnimationBinaryTest { + private static final List V1_BONES = List.of("head", "body", "right_arm", "left_arm", "right_leg", "left_leg"); + @Test @DisplayName("New binary format") public void newBinaryTest() throws IOException { @@ -38,13 +42,24 @@ public void legacyBinaryTest() throws IOException { int len = LegacyAnimationBinary.calculateSize(animation, version); ByteBuf byteBuf = Unpooled.buffer(len); LegacyAnimationBinary.write(animation, byteBuf, version); - Assertions.assertEquals(len, byteBuf.writerIndex(), "Incorrect size calculator!"); + Assertions.assertEquals(len, byteBuf.writerIndex(), "Incorrect size calculator at version " + version); Assertions.assertTrue(byteBuf.readableBytes() > 0, "animation reads incorrectly at version " + version); Animation readed = LegacyAnimationBinary.read(byteBuf, version); - // Assertions.assertEquals(animation.boneAnimations(), readed.boneAnimations(), "animation reads incorrectly at version " + version); - Assertions.assertNotNull(readed, "animation reads incorrectly at version " + version); // TODO Not working correctly (zigy, please fix) + + if (version < 2) { + // V1 only supports 6 hardcoded bones — compare only those + for (String bone : V1_BONES) { + BoneAnimation orig = animation.boneAnimations().get(bone); + BoneAnimation read = readed.boneAnimations().get(bone); + if (orig != null) { + Assertions.assertEquals(orig, read, "bone '" + bone + "' reads incorrectly at version " + version); + } + } + } else { + Assertions.assertEquals(animation.boneAnimations(), readed.boneAnimations(), "animation reads incorrectly at version " + version); + } byteBuf.release(); } } diff --git a/core/src/test/java/io/github/kosmx/emotes/testing/common/BinarySizeTest.java b/core/src/test/java/io/github/kosmx/emotes/testing/common/BinarySizeTest.java index d15cc955..43f60c98 100644 --- a/core/src/test/java/io/github/kosmx/emotes/testing/common/BinarySizeTest.java +++ b/core/src/test/java/io/github/kosmx/emotes/testing/common/BinarySizeTest.java @@ -25,10 +25,12 @@ public void newBinarySizeTest() throws IOException { for (int version = 1; version <= AnimationBinary.CURRENT_VERSION; version++) { ByteBuf byteBuf = Unpooled.buffer(); + long start = System.nanoTime(); AnimationBinary.write(byteBuf, version, animation); + long elapsed = System.nanoTime() - start; int size = byteBuf.readableBytes(); - System.out.println("[NEW] in version " + version + " size " + size); + System.out.println("[NEW] in version " + version + " size " + size + " time " + (elapsed / 1_000_000.0) + "ms"); Assertions.assertTrue(size < MAX_PACKET_SIZE, "size exceeds"); } } @@ -40,10 +42,12 @@ public void legacyBinarySizeTest() throws IOException { for (int version = 1; version <= LegacyAnimationBinary.getCurrentVersion(); version++) { ByteBuf byteBuf = Unpooled.buffer(LegacyAnimationBinary.calculateSize(animation, version)); + long start = System.nanoTime(); LegacyAnimationBinary.write(animation, byteBuf, version); + long elapsed = System.nanoTime() - start; int size = byteBuf.readableBytes(); - System.out.println("[LEGACY] in version " + version + " size " + size); + System.out.println("[LEGACY] in version " + version + " size " + size + " time " + (elapsed / 1_000_000.0) + "ms"); Assertions.assertTrue(size < MAX_PACKET_SIZE, "size exceeds"); byteBuf.release(); } diff --git a/core/src/test/resources/cmm_bone_test.json b/core/src/test/resources/cmm_bone_test.json new file mode 100644 index 00000000..621dd819 --- /dev/null +++ b/core/src/test/resources/cmm_bone_test.json @@ -0,0 +1,25 @@ +{ + "format_version": "1.8.0", + "model": { + "cmm": { + "pivot": [ 0, 12, 0 ], + "texture": "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAfUlEQVR4Xo1QiRHAIAhzUAZgC7foAg5KjSkq1OsVr1qS8Jby18TE1PivBi/R1a4JwmtRIp1uHUYOHeIlnxEOQoyz5ZBB40MOxNNPAsL6vKEIBIxBHx5/ECzqIHBwFQg9+BT7XeOguUTYw56DL5p9LZvrxpggE00DzJOZD7sBRaHjpRD91mQAAAAASUVORK5CYII=", + "elements": [ + { + "from": [ 0, 0.25, 0 ], + "to": [ 16, 0.25, 16 ], + "faces": { + "down": { "uv": [ 0, 16, 16, 0 ], "texture": "#texture", "tintindex": 0 }, + "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#texture", "tintindex": 0 } + } + } + ] + } + }, + "animations": { + "cmm_bone_test": { + "loop": false, + "bones": {} + } + } +} diff --git a/gradle.properties b/gradle.properties index 7028a9de..f703cfd2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,17 +3,15 @@ org.gradle.jvmargs=-Xmx2G org.gradle.parallel=true # Mod properties -mod_version = 1.1.6 +mod_version = 1.1.6+dev maven_group = com.zigythebird.playeranim archives_base_name = PlayerAnimationLib # Minecraft properties -minecraft_version = 1.21.11 -parchment_version = 2025.12.20 +minecraft_version = 26.1-snapshot-11 # Dependencies -fabric_loader_version = 0.18.3 -fabric_api_version = 0.140.2+1.21.11 -neoforge_version = 21.11.13-beta -molang_version = 4.1.5 -javassist_version = 3.30.2-GA +fabric_loader_version = 0.18.4 +fabric_api_version = 0.143.11+26.1 +neoforge_version = 26.1.0.0-alpha.0+snapshot-11.20260304.010323 +molang_version = 5.0.0 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index f8e1ee31..61285a65 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 23449a2b..dbc3ce4a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/minecraft/build.gradle b/minecraft/build.gradle index 1896e1fa..966051bc 100644 --- a/minecraft/build.gradle +++ b/minecraft/build.gradle @@ -1,38 +1,196 @@ +import org.apache.commons.lang3.StringUtils + plugins { - id "architectury-plugin" + id "xyz.wagyourtail.unimined" + id "com.gradleup.shadow" } -architectury { - minecraft = rootProject.minecraft_version +sourceSets { + fabric + neoforge } -subprojects { - apply plugin: "architectury-plugin" - apply plugin: "dev.architectury.loom" +unimined.minecraft(sourceSets.main) { + version rootProject.minecraft_version - loom { - silentMojangMappingsLicense() + fabric { + loader rootProject.fabric_loader_version + accessWidener file("src/main/resources/player_animation_library.classtweaker") } - jar { - if (!rootProject.version.toString().contains("dev") && !project.gradle.startParameter.taskNames.contains("runClient")) - processResources.exclude('assets/player_animation_library/player_animations/*') + defaultRemapJar = false +} + +unimined.minecraft(sourceSets.fabric) { + combineWith(sourceSets.main) + + fabric { + loader project.fabric_loader_version + accessWidener file("src/main/resources/player_animation_library.classtweaker") } + defaultRemapJar = true +} - dependencies { - minecraft "com.mojang:minecraft:${rootProject.minecraft_version}" - mappings loom.layered() { - officialMojangMappings() - parchment("org.parchmentmc.data:parchment-${rootProject.minecraft_version}:${rootProject.parchment_version}@zip") - } - implementation project(":core") +unimined.minecraft(sourceSets.neoforge) { + combineWith(sourceSets.main) + + neoForge { + loader("net.neoforged:neoforge:$rootProject.neoforge_version:universal") + mixinConfig("player_animation_library.mixins.json") + + // accessTransformer aw2at(file("src/main/resources/player_animation_library.classtweaker")) + } + defaultRemapJar = true +} + +configurations { + shadow + + fabricCompileClasspath.extendsFrom compileClasspath + neoforgeCompileClasspath.extendsFrom compileClasspath + fabricRuntimeClasspath.extendsFrom runtimeClasspath + neoforgeRuntimeClasspath.extendsFrom runtimeClasspath + + platformInclude + fabricInclude.extendsFrom platformInclude + neoforgeInclude.extendsFrom platformInclude +} + +dependencies { + // Core + api(project(":core")) + shadow(project(path: ":core")) { transitive = false } + + // Common + platformInclude("com.zigythebird:mochafloats:$rootProject.molang_version") { + transitive = false + } + + // Fabric + fabricImplementation fabricApi.fabricModule("fabric-command-api-v2", rootProject.fabric_api_version) + fabricImplementation fabricApi.fabricModule("fabric-resource-loader-v1", rootProject.fabric_api_version) + + // Neoforge +} + +jar { + if (!rootProject.version.toString().contains("dev") && !project.gradle.startParameter.taskNames.contains("runClient")) { + processResources.exclude('assets/player_animation_library/player_animations/*') + } + archiveClassifier.set "dev" +} + +[tasks.processResources, tasks.processFabricResources, tasks.processNeoforgeResources].each { + it.inputs.property "version", project.version + + it.filesMatching(["META-INF/neoforge.mods.toml", "fabric.mod.json"]) { + expand version: project.version + } +} + +shadowJar { + configurations = [project.configurations.shadow] + + from(tasks.named("remapFabricJar").map { zipTree(it.archiveFile) }) + from(tasks.named("remapNeoforgeJar").map { zipTree(it.archiveFile) }) + + archiveBaseName.set("${rootProject.archives_base_name}Merged") + archiveClassifier.set null + + // Services + filesMatching('META-INF/services/**') { + duplicatesStrategy = DuplicatesStrategy.INCLUDE + } + mergeServiceFiles() + + // Fix fabric jij + exclude 'META-INF/jarjar/*.jar' + filesMatching('META-INF/jarjar/metadata.json') { + filter { it.replace('META-INF/jarjar/', 'META-INF/jars/') } + } +} + +shadow { + addShadowVariantIntoJavaComponent = false +} + +[sourceSets.fabric, sourceSets.neoforge].each { ss -> + tasks.register("${ss.name}SourcesJar", Jar) { + from sourceSets.main.allSource + from ss.allSource + + archiveBaseName.set("${rootProject.archives_base_name}${StringUtils.capitalize(ss.name)}") + archiveClassifier.set "sources" } +} + +publishing { + publications { + mavenMain(MavenPublication) { + artifactId = "PlayerAnimationLibCommon" + + artifact(jar) { + classifier = null + } + artifact sourcesJar + + pom.withXml { + def deps = asNode().appendNode("dependencies") + + configurations.api.dependencies.each { + def d = deps.appendNode("dependency") + + d.appendNode("groupId", it.group) + d.appendNode('artifactId', it instanceof ProjectDependency ? project(it.path).base.archivesName.get() : it.name) + d.appendNode("version", it.version) + d.appendNode("scope", "compile") + } + } + } + mavenFabric(MavenPublication) { + artifactId = "PlayerAnimationLibFabric" + + artifact(tasks.named("remapFabricJar")) { + classifier = null + } + artifact fabricSourcesJar + + pom.withXml { + def deps = asNode().appendNode("dependencies") + + // Adds fabric api to deps + configurations.fabricImplementation.dependencies.each { + def d = deps.appendNode("dependency") + + d.appendNode("groupId", it.group) + d.appendNode('artifactId', it instanceof ProjectDependency ? project(it.path).base.archivesName.get() : it.name) + d.appendNode("version", it.version) + d.appendNode("scope", "compile") + } + + def d = deps.appendNode("dependency") + d.appendNode("groupId", project.group) + d.appendNode("artifactId", "PlayerAnimationLibCommon") + d.appendNode("version", project.version) + d.appendNode("scope", "compile") + } + } + mavenNeo(MavenPublication) { + artifactId = "PlayerAnimationLibNeo" - processResources { - inputs.property "version", project.version + artifact(tasks.named("remapNeoforgeJar")) { + classifier = null + } + artifact neoforgeSourcesJar - filesMatching(["META-INF/neoforge.mods.toml", "fabric.mod.json"]) { - expand version: project.version + pom.withXml { + def deps = asNode().appendNode("dependencies") + def d = deps.appendNode("dependency") + d.appendNode("groupId", project.group) + d.appendNode("artifactId", "PlayerAnimationLibCommon") + d.appendNode("version", project.version) + d.appendNode("scope", "compile") + } } } } diff --git a/minecraft/common/build.gradle b/minecraft/common/build.gradle deleted file mode 100644 index f72ddb67..00000000 --- a/minecraft/common/build.gradle +++ /dev/null @@ -1,22 +0,0 @@ -loom { - accessWidenerPath = file("src/main/resources/player_animation_library.accesswidener") -} - -dependencies { - modCompileOnly "net.fabricmc:fabric-loader:$rootProject.fabric_loader_version" - implementation project(path: ":core") -} - -jar { - from rootProject.file("LICENSE") -} - -publishing { - publications { - mavenCommon(MavenPublication) { - artifactId = "PlayerAnimationLibCommon" - from components.java - } - } -} - diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/PlayerAnimLibPlatform.java b/minecraft/common/src/main/java/com/zigythebird/playeranim/PlayerAnimLibPlatform.java deleted file mode 100644 index 032826dc..00000000 --- a/minecraft/common/src/main/java/com/zigythebird/playeranim/PlayerAnimLibPlatform.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.zigythebird.playeranim; - -@Deprecated(forRemoval = true) -public class PlayerAnimLibPlatform { - @Deprecated(forRemoval = true) - public static boolean isModLoaded(String id) { - return PlayerAnimLibService.INSTANCE.isModLoaded(id); - } -} diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/PlayerAnimLibService.java b/minecraft/common/src/main/java/com/zigythebird/playeranim/PlayerAnimLibService.java deleted file mode 100644 index 2374bca3..00000000 --- a/minecraft/common/src/main/java/com/zigythebird/playeranim/PlayerAnimLibService.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.zigythebird.playeranim; - -import java.util.ServiceLoader; -import java.util.stream.Stream; - -public interface PlayerAnimLibService { - PlayerAnimLibService INSTANCE = loadServices(PlayerAnimLibService.class).findAny().orElseThrow(); - - boolean isModLoaded(String id); - - static Stream loadServices(Class serviceClass) { - ModuleLayer layer = serviceClass.getModule().getLayer(); // NeoForge compat? - ServiceLoader loader = layer == null ? ServiceLoader.load(serviceClass, - serviceClass.getClassLoader() - ) : ServiceLoader.load(layer, serviceClass); - return loader.stream().map(ServiceLoader.Provider::get); - } -} diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/accessors/ICapeLayer.java b/minecraft/common/src/main/java/com/zigythebird/playeranim/accessors/ICapeLayer.java deleted file mode 100644 index 0eb40c85..00000000 --- a/minecraft/common/src/main/java/com/zigythebird/playeranim/accessors/ICapeLayer.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.zigythebird.playeranim.accessors; - -import com.zigythebird.playeranim.animation.AvatarAnimManager; - -@Deprecated(forRemoval = true) -public interface ICapeLayer { - default void applyBend(AvatarAnimManager manager, float bend) {} - default void resetBend() {} -} diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/LivingEntityRendererMixin.java b/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/LivingEntityRendererMixin.java deleted file mode 100644 index 327727ec..00000000 --- a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/LivingEntityRendererMixin.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2022 KosmX - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.zigythebird.playeranim.mixin; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.zigythebird.playeranim.accessors.IAvatarAnimationState; -import com.zigythebird.playeranim.util.RenderUtil; -import com.zigythebird.playeranimcore.bones.PlayerAnimBone; -import net.minecraft.client.renderer.SubmitNodeCollector; -import net.minecraft.client.renderer.entity.LivingEntityRenderer; -import net.minecraft.client.renderer.entity.state.LivingEntityRenderState; -import net.minecraft.client.renderer.state.CameraRenderState; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(LivingEntityRenderer.class) -public class LivingEntityRendererMixin { - @Inject(method = "submit(Lnet/minecraft/client/renderer/entity/state/LivingEntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/state/CameraRenderState;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/LivingEntityRenderer;scale(Lnet/minecraft/client/renderer/entity/state/LivingEntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;)V")) - private void doTranslations(S livingEntityRenderState, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, CameraRenderState cameraRenderState, CallbackInfo ci) { - if (livingEntityRenderState instanceof IAvatarAnimationState avatarRenderState) { - var animationPlayer = avatarRenderState.playerAnimLib$getAnimManager(); - if (animationPlayer != null && animationPlayer.isActive()) { - avatarRenderState.playerAnimLib$getAnimManager().handleAnimations(animationPlayer.getTickDelta(), false, avatarRenderState.playerAnimLib$isFirstPersonPass()); - poseStack.scale(-1.0F, -1.0F, 1.0F); - - //These are additive properties - PlayerAnimBone body = animationPlayer.get3DTransform(new PlayerAnimBone("body")); - - poseStack.translate(-body.getPosX()/16, body.getPosY()/16 + 0.75, body.getPosZ()/16); - body.rotX *= -1; - body.rotY *= -1; - RenderUtil.rotateMatrixAroundBone(poseStack, body); - poseStack.scale(body.getScaleX(), body.getScaleY(), body.getScaleZ()); - - poseStack.translate(0, -0.75, 0); - - poseStack.scale(-1.0F, -1.0F, 1.0F); - } - } - } -} diff --git a/minecraft/common/src/main/resources/architectury.common.json b/minecraft/common/src/main/resources/architectury.common.json deleted file mode 100644 index ab4f3715..00000000 --- a/minecraft/common/src/main/resources/architectury.common.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "injected_interfaces": { - "net/minecraft/class_11890": [ - "com/zigythebird/playeranim/accessors/IAnimatedAvatar" - ], - "net/minecraft/class_10055": [ - "com/zigythebird/playeranim/accessors/IAvatarAnimationState" - ] - }, - "accessWidener": "player_animation_library.accesswidener" -} \ No newline at end of file diff --git a/minecraft/common/src/main/resources/architectury.common.marker b/minecraft/common/src/main/resources/architectury.common.marker deleted file mode 100644 index e69de29b..00000000 diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/.gitignore b/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/.gitignore deleted file mode 100644 index 22e953a7..00000000 --- a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/.gitignore +++ /dev/null @@ -1 +0,0 @@ -dont_include \ No newline at end of file diff --git a/minecraft/common/src/main/resources/player_animation_library.accesswidener b/minecraft/common/src/main/resources/player_animation_library.accesswidener deleted file mode 100644 index 50690074..00000000 --- a/minecraft/common/src/main/resources/player_animation_library.accesswidener +++ /dev/null @@ -1,6 +0,0 @@ -accessWidener v2 named - -extendable class net/minecraft/client/model/geom/ModelPart -accessible field net/minecraft/client/renderer/LevelRenderer levelRenderState Lnet/minecraft/client/renderer/state/LevelRenderState; -accessible field net/minecraft/client/renderer/entity/layers/RenderLayer renderer Lnet/minecraft/client/renderer/entity/RenderLayerParent; -accessible field net/minecraft/client/renderer/entity/LivingEntityRenderer layers Ljava/util/List; \ No newline at end of file diff --git a/minecraft/fabric/build.gradle b/minecraft/fabric/build.gradle deleted file mode 100644 index d6efe654..00000000 --- a/minecraft/fabric/build.gradle +++ /dev/null @@ -1,74 +0,0 @@ -plugins { - id "com.gradleup.shadow" -} - -loom { - accessWidenerPath = project(":minecraft:common").loom.accessWidenerPath -} - -architectury { - platformSetupLoomIde() - fabric() -} - -configurations { - shadowCommon - compileClasspath.extendsFrom shadowCommon - runtimeClasspath.extendsFrom shadowCommon - developmentFabric.extendsFrom shadowCommon -} - -dependencies { - modImplementation "net.fabricmc:fabric-loader:$rootProject.fabric_loader_version" - - // Fabric API - modApi fabricApi.module("fabric-command-api-v2", rootProject.fabric_api_version) - modApi fabricApi.module("fabric-resource-loader-v1", rootProject.fabric_api_version) - - implementation api(include("com.zigythebird:mochafloats:$rootProject.molang_version")) { - transitive = false - } - modRuntimeOnly include("org.javassist:javassist:$rootProject.javassist_version") - - shadowCommon(project(path: ":minecraft:common", configuration: "namedElements")) { transitive = false } - shadowCommon(project(path: ":core")) { transitive = false } -} - -shadowJar { - configurations = [project.configurations.shadowCommon] - archiveClassifier = 'dev-shadow' - mergeServiceFiles() - - exclude "architectury.common.marker" -} - -remapJar { - injectAccessWidener = true - - inputFile.set shadowJar.archiveFile - dependsOn shadowJar - archiveClassifier.set null -} - -jar { - archiveClassifier.set "dev" -} - -sourcesJar { - def commonSources = project(":minecraft:common").sourcesJar - dependsOn commonSources - from commonSources.archiveFile.map { zipTree(it) } -} - -shadow { - addShadowVariantIntoJavaComponent = false -} - -publishing { - publications { - mavenFabric(MavenPublication) { - artifactId = "PlayerAnimationLibFabric" - from components.java - } - } -} diff --git a/minecraft/neoforge/build.gradle b/minecraft/neoforge/build.gradle deleted file mode 100644 index 7e067092..00000000 --- a/minecraft/neoforge/build.gradle +++ /dev/null @@ -1,73 +0,0 @@ -plugins { - id "com.gradleup.shadow" -} - -loom { - accessWidenerPath = project(":minecraft:common").loom.accessWidenerPath -} - -architectury { - platformSetupLoomIde() - neoForge() -} - -configurations { - shadowCommon - compileClasspath.extendsFrom shadowCommon - runtimeClasspath.extendsFrom shadowCommon - developmentNeoForge.extendsFrom shadowCommon -} - -dependencies { - neoForge "net.neoforged:neoforge:$rootProject.neoforge_version" - - implementation forgeRuntimeLibrary(api(include("com.zigythebird:mochafloats:$rootProject.molang_version"))) { - transitive = false - } - modRuntimeOnly forgeRuntimeLibrary(include("org.javassist:javassist:$rootProject.javassist_version")) - - shadowCommon(project(path: ":minecraft:common", configuration: "namedElements")) { transitive = false } - shadowCommon(project(path: ":core")) { transitive = false } -} - -shadowJar { - exclude "fabric.mod.json" - exclude "architectury.common.json" - exclude "architectury.common.marker" - - configurations = [project.configurations.shadowCommon] - archiveClassifier.set "dev-shadow" - - mergeServiceFiles() -} - -remapJar { - atAccessWideners.add(loom.accessWidenerPath.get().asFile.name) - - inputFile.set shadowJar.archiveFile - dependsOn shadowJar - archiveClassifier.set null -} - -jar { - archiveClassifier.set "dev" -} - -sourcesJar { - def commonSources = project(":minecraft:common").sourcesJar - dependsOn commonSources - from commonSources.archiveFile.map { zipTree(it) } -} - -shadow { - addShadowVariantIntoJavaComponent = false -} - -publishing { - publications { - mavenNeoForge(MavenPublication) { - artifactId = "PlayerAnimationLibNeo" - from components.java - } - } -} diff --git a/minecraft/neoforge/gradle.properties b/minecraft/neoforge/gradle.properties deleted file mode 100644 index 2e6ed767..00000000 --- a/minecraft/neoforge/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -loom.platform = neoforge diff --git a/minecraft/neoforge/src/main/resources/icon.png b/minecraft/neoforge/src/main/resources/icon.png deleted file mode 100644 index 7d97c057..00000000 Binary files a/minecraft/neoforge/src/main/resources/icon.png and /dev/null differ diff --git a/minecraft/fabric/src/main/java/com/zigythebird/playeranim/fabric/PlayerAnimLibModFabric.java b/minecraft/src/fabric/java/com/zigythebird/playeranim/fabric/PlayerAnimLibModFabric.java similarity index 94% rename from minecraft/fabric/src/main/java/com/zigythebird/playeranim/fabric/PlayerAnimLibModFabric.java rename to minecraft/src/fabric/java/com/zigythebird/playeranim/fabric/PlayerAnimLibModFabric.java index 44752d95..2141c695 100644 --- a/minecraft/fabric/src/main/java/com/zigythebird/playeranim/fabric/PlayerAnimLibModFabric.java +++ b/minecraft/src/fabric/java/com/zigythebird/playeranim/fabric/PlayerAnimLibModFabric.java @@ -12,7 +12,7 @@ public final class PlayerAnimLibModFabric extends PlayerAnimLibMod implements ClientModInitializer { @Override public void onInitializeClient() { - ResourceLoader.get(PackType.CLIENT_RESOURCES).registerReloader(PlayerAnimResources.KEY, new PlayerAnimResources()); + ResourceLoader.get(PackType.CLIENT_RESOURCES).registerReloadListener(PlayerAnimResources.KEY, new PlayerAnimResources()); if (FabricLoader.getInstance().isDevelopmentEnvironment() || FabricLoader.getInstance().getModContainer(PlayerAnimLibMod.MOD_ID).get().getMetadata().getVersion().getFriendlyString().contains("dev")) ClientCommandRegistrationCallback.EVENT.register(PlayerAnimCommands::register); diff --git a/minecraft/fabric/src/main/java/com/zigythebird/playeranim/fabric/PlayerAnimLibServiceImpl.java b/minecraft/src/fabric/java/com/zigythebird/playeranim/fabric/PlayerAnimLibServiceImpl.java similarity index 60% rename from minecraft/fabric/src/main/java/com/zigythebird/playeranim/fabric/PlayerAnimLibServiceImpl.java rename to minecraft/src/fabric/java/com/zigythebird/playeranim/fabric/PlayerAnimLibServiceImpl.java index b07d88a7..c33e8938 100644 --- a/minecraft/fabric/src/main/java/com/zigythebird/playeranim/fabric/PlayerAnimLibServiceImpl.java +++ b/minecraft/src/fabric/java/com/zigythebird/playeranim/fabric/PlayerAnimLibServiceImpl.java @@ -4,6 +4,16 @@ import net.fabricmc.loader.api.FabricLoader; public final class PlayerAnimLibServiceImpl implements PlayerAnimLibService { + @Override + public boolean isActive() { + try { + Class.forName("net.fabricmc.loader.api.FabricLoader"); + return true; + } catch (Exception th) { + return false; + } + } + @Override public boolean isModLoaded(String id) { return FabricLoader.getInstance().isModLoaded(id); diff --git a/minecraft/fabric/src/main/resources/META-INF/services/com.zigythebird.playeranim.PlayerAnimLibService b/minecraft/src/fabric/resources/META-INF/services/com.zigythebird.playeranim.PlayerAnimLibService similarity index 100% rename from minecraft/fabric/src/main/resources/META-INF/services/com.zigythebird.playeranim.PlayerAnimLibService rename to minecraft/src/fabric/resources/META-INF/services/com.zigythebird.playeranim.PlayerAnimLibService diff --git a/minecraft/fabric/src/main/resources/fabric.mod.json b/minecraft/src/fabric/resources/fabric.mod.json similarity index 93% rename from minecraft/fabric/src/main/resources/fabric.mod.json rename to minecraft/src/fabric/resources/fabric.mod.json index fece4e0b..72b20875 100644 --- a/minecraft/fabric/src/main/resources/fabric.mod.json +++ b/minecraft/src/fabric/resources/fabric.mod.json @@ -25,8 +25,8 @@ "player_animation_library.mixins.json" ], "depends": { - "fabricloader": ">=0.18.3", - "minecraft": ">=1.21.11", + "fabricloader": ">=0.18.4", + "minecraft": ">=26.1-alpha.6", "fabric-resource-loader-v1": "*", "fabric-command-api-v2": "*" }, diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/PlayerAnimLibMod.java b/minecraft/src/main/java/com/zigythebird/playeranim/PlayerAnimLibMod.java similarity index 83% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/PlayerAnimLibMod.java rename to minecraft/src/main/java/com/zigythebird/playeranim/PlayerAnimLibMod.java index 7adaf238..ec4ce1d3 100644 --- a/minecraft/common/src/main/java/com/zigythebird/playeranim/PlayerAnimLibMod.java +++ b/minecraft/src/main/java/com/zigythebird/playeranim/PlayerAnimLibMod.java @@ -19,11 +19,9 @@ public static Identifier id(String name) { protected void init() { PlayerAnimationFactory.ANIMATION_DATA_FACTORY.registerFactory(ANIMATION_LAYER_ID, 1000, - player -> new PlayerAnimationController(player, - (controller, state, animSetter) -> PlayState.STOP - ) + player -> new PlayerAnimationController(player, (_, _, _) -> PlayState.STOP) ); - MolangEvent.MOLANG_EVENT.register((controller, engine, queryBinding) -> + MolangEvent.MOLANG_EVENT.register((_, _, queryBinding) -> MolangQueries.setDefaultQueryValues(queryBinding) ); CustomKeyFrameEvents.SOUND_KEYFRAME_EVENT.register(new AutoPlayingSoundKeyframeHandler()); diff --git a/minecraft/src/main/java/com/zigythebird/playeranim/PlayerAnimLibService.java b/minecraft/src/main/java/com/zigythebird/playeranim/PlayerAnimLibService.java new file mode 100644 index 00000000..6fd5acd7 --- /dev/null +++ b/minecraft/src/main/java/com/zigythebird/playeranim/PlayerAnimLibService.java @@ -0,0 +1,9 @@ +package com.zigythebird.playeranim; + +import com.zigythebird.playeranimcore.util.ServiceUtil; + +public interface PlayerAnimLibService extends ServiceUtil.ActiveService { + PlayerAnimLibService INSTANCE = ServiceUtil.loadService(PlayerAnimLibService.class); + + boolean isModLoaded(String id); +} diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/accessors/IAnimatedAvatar.java b/minecraft/src/main/java/com/zigythebird/playeranim/accessors/IAnimatedAvatar.java similarity index 100% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/accessors/IAnimatedAvatar.java rename to minecraft/src/main/java/com/zigythebird/playeranim/accessors/IAnimatedAvatar.java diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/accessors/IAvatarAnimationState.java b/minecraft/src/main/java/com/zigythebird/playeranim/accessors/IAvatarAnimationState.java similarity index 100% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/accessors/IAvatarAnimationState.java rename to minecraft/src/main/java/com/zigythebird/playeranim/accessors/IAvatarAnimationState.java diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/accessors/IBoneUpdater.java b/minecraft/src/main/java/com/zigythebird/playeranim/accessors/IBoneUpdater.java similarity index 100% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/accessors/IBoneUpdater.java rename to minecraft/src/main/java/com/zigythebird/playeranim/accessors/IBoneUpdater.java diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/animation/AvatarAnimManager.java b/minecraft/src/main/java/com/zigythebird/playeranim/animation/AvatarAnimManager.java similarity index 98% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/animation/AvatarAnimManager.java rename to minecraft/src/main/java/com/zigythebird/playeranim/animation/AvatarAnimManager.java index 9ae7d31f..a8f2dd2f 100644 --- a/minecraft/common/src/main/java/com/zigythebird/playeranim/animation/AvatarAnimManager.java +++ b/minecraft/src/main/java/com/zigythebird/playeranim/animation/AvatarAnimManager.java @@ -77,7 +77,7 @@ public void setTickDelta(float tickDelta) { public void updatePart(ModelPart part, PlayerAnimBone bone) { PartPose initialPose = part.getInitialPose(); - bone = this.get3DTransform(bone); + this.get3DTransform(bone); RenderUtil.translatePartToBone(part, bone, initialPose); } diff --git a/minecraft/src/main/java/com/zigythebird/playeranim/animation/MinecraftModel.java b/minecraft/src/main/java/com/zigythebird/playeranim/animation/MinecraftModel.java new file mode 100644 index 00000000..be510a2c --- /dev/null +++ b/minecraft/src/main/java/com/zigythebird/playeranim/animation/MinecraftModel.java @@ -0,0 +1,134 @@ +package com.zigythebird.playeranim.animation; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.mojang.blaze3d.platform.NativeImage; +import com.mojang.blaze3d.systems.RenderSystem; +import com.zigythebird.playeranim.PlayerAnimLibMod; +import com.zigythebird.playeranimcore.bindings.PlatformModel; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.dispatch.BlockModelRotation; +import net.minecraft.client.renderer.block.dispatch.BlockStateModelPart; +import net.minecraft.client.renderer.block.model.*; +import net.minecraft.client.renderer.rendertype.RenderType; +import net.minecraft.client.renderer.rendertype.RenderTypes; +import net.minecraft.client.renderer.texture.DynamicTexture; +import net.minecraft.client.renderer.texture.SpriteContents; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.metadata.animation.FrameSize; +import net.minecraft.client.resources.model.*; +import net.minecraft.client.resources.model.cuboid.CuboidModel; +import net.minecraft.client.resources.model.cuboid.CuboidModelElement; +import net.minecraft.client.resources.model.cuboid.UnbakedCuboidGeometry; +import net.minecraft.client.resources.model.geometry.BakedQuad; +import net.minecraft.client.resources.model.geometry.QuadCollection; +import net.minecraft.client.resources.model.sprite.Material; +import net.minecraft.client.resources.model.sprite.MaterialBaker; +import net.minecraft.client.resources.model.sprite.TextureSlots; +import net.minecraft.resources.Identifier; +import org.joml.Vector3fc; +import org.jspecify.annotations.NonNull; +import org.redlance.platformtools.webp.decoder.DecodedImage; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +public class MinecraftModel implements PlatformModel, MaterialBaker, ModelBaker, ModelBaker.Interner, ModelDebugName { + private static final AtomicInteger TEXTURE_COUNTER = new AtomicInteger(0); + + private final TextureAtlasSprite sprite; + private final RenderType renderType; + private final QuadCollection geometry; + + public MinecraftModel(@NonNull DecodedImage texture, @NonNull JsonArray elements) throws IOException { + this.sprite = loadAtlasSprite(texture.toPng()); + this.renderType = RenderTypes.entityTranslucent(this.sprite.atlasLocation()); + + List blockElements = new ArrayList<>(); + for (JsonElement element : elements) { + blockElements.add(CuboidModel.GSON.fromJson(element, CuboidModelElement.class)); + } + this.geometry = UnbakedCuboidGeometry.bake(blockElements, TextureSlots.EMPTY, this, BlockModelRotation.IDENTITY, this); + } + + @NonNull + public QuadCollection getGeometry() { + return this.geometry; + } + + @NonNull + public RenderType getRenderType() { + return this.renderType; + } + + @Override + public void invalidate() { + if (this.sprite != null) this.sprite.close(); + } + + @Override + public @NonNull String debugName() { + return "playeranim:custom_bone"; + } + + @Override + public Material.@NonNull Baked get(Material material, @NonNull ModelDebugName name) { + return new Material.Baked(this.sprite, material.forceTranslucent()); + } + + @Override + public Material.@NonNull Baked reportMissingReference(@NonNull String reference, @NonNull ModelDebugName name) { + return new Material.Baked(this.sprite, false); + } + + @Override + public @NonNull ResolvedModel getModel(@NonNull Identifier location) { + throw new UnsupportedOperationException(); + } + + @Override + public @NonNull BlockStateModelPart missingBlockModelPart() { + throw new UnsupportedOperationException(); + } + + @Override + public @NonNull MaterialBaker materials() { + return this; + } + + @Override + public @NonNull Interner interner() { + return this; + } + + @Override + public @NonNull Vector3fc vector(@NonNull Vector3fc vector) { + return vector; + } + + @Override + public BakedQuad.@NonNull SpriteInfo spriteInfo(BakedQuad.@NonNull SpriteInfo sprite) { + return sprite; + } + + @Override + public T compute(SharedOperationKey key) { + return key.compute(this); + } + + private static TextureAtlasSprite loadAtlasSprite(byte[] texture) throws IOException { + RenderSystem.assertOnRenderThread(); + NativeImage image = NativeImage.read(texture); + + Identifier texId = PlayerAnimLibMod.id("dynamic/texture_" + TEXTURE_COUNTER.getAndIncrement()); + DynamicTexture dynTex = new DynamicTexture(texId::toString, image); + Minecraft.getInstance().getTextureManager().register(texId, dynTex); + + int w = image.getWidth(); + int h = image.getHeight(); + SpriteContents contents = new SpriteContents(texId, new FrameSize(w, h), image); + return new TextureAtlasSprite(texId, contents, w, h, 0, 0, 0); + } +} diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/animation/PlayerAnimResources.java b/minecraft/src/main/java/com/zigythebird/playeranim/animation/PlayerAnimResources.java similarity index 100% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/animation/PlayerAnimResources.java rename to minecraft/src/main/java/com/zigythebird/playeranim/animation/PlayerAnimResources.java diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/animation/PlayerAnimationController.java b/minecraft/src/main/java/com/zigythebird/playeranim/animation/PlayerAnimationController.java similarity index 78% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/animation/PlayerAnimationController.java rename to minecraft/src/main/java/com/zigythebird/playeranim/animation/PlayerAnimationController.java index b87abf00..c08cee8e 100644 --- a/minecraft/common/src/main/java/com/zigythebird/playeranim/animation/PlayerAnimationController.java +++ b/minecraft/src/main/java/com/zigythebird/playeranim/animation/PlayerAnimationController.java @@ -1,12 +1,16 @@ package com.zigythebird.playeranim.animation; +import com.google.gson.JsonArray; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import com.zigythebird.playeranim.PlayerAnimLibMod; import com.zigythebird.playeranim.util.RenderUtil; +import com.zigythebird.playeranimcore.PlayerAnimLib; import com.zigythebird.playeranimcore.animation.AnimationController; import com.zigythebird.playeranimcore.animation.HumanoidAnimationController; import com.zigythebird.playeranimcore.animation.layered.modifier.AbstractFadeModifier; +import com.zigythebird.playeranimcore.bindings.PlatformModel; +import com.zigythebird.playeranimcore.bones.PlayerAnimBone; import com.zigythebird.playeranimcore.math.Vec3f; import com.zigythebird.playeranimcore.molang.MolangLoader; import net.minecraft.resources.Identifier; @@ -15,6 +19,7 @@ import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.redlance.platformtools.webp.decoder.DecodedImage; import team.unnamed.mocha.MochaEngine; import java.util.function.Function; @@ -53,7 +58,7 @@ public boolean triggerAnimation(Identifier newAnimation, float startAnimFrom) { triggerAnimation(PlayerAnimResources.getAnimation(newAnimation), startAnimFrom); return true; } - PlayerAnimLibMod.LOGGER.error("Could not find animation with the name:" + newAnimation); + PlayerAnimLibMod.LOGGER.error("Could not find animation with the name:{}", newAnimation); return false; } @@ -78,12 +83,27 @@ public boolean replaceAnimationWithFade(@NotNull AbstractFadeModifier fadeModifi */ public @Nullable PoseStack getBoneWorldPositionPoseStack(String name, float tickDelta, Vec3 cameraPos) { if (!this.activeBones.containsKey(name)) return null; + return getBoneWorldPositionPoseStack(this.activeBones.get(name), tickDelta, cameraPos); + } + + public @NotNull PoseStack getBoneWorldPositionPoseStack(PlayerAnimBone bone, float tickDelta, Vec3 cameraPos) { PoseStack poseStack = new PoseStack(); - Vec3f pivot = getBonePosition(name); + Vec3f pivot = getBonePosition(bone.getName()); Vec3 position = avatar.getPosition(tickDelta).subtract(cameraPos).add(pivot.x(), pivot.y(), pivot.z()); poseStack.translate(position.x(), position.y(), position.z()); poseStack.mulPose(Axis.YP.rotationDegrees(180 - Mth.lerp(tickDelta, avatar.yBodyRotO, avatar.yBodyRot))); - RenderUtil.translateMatrixToBone(poseStack, this.activeBones.get(name)); + RenderUtil.translateMatrixToBone(poseStack, bone); return poseStack; } + + @Override + protected @Nullable PlatformModel loadCustomModel(@Nullable DecodedImage texture, @Nullable JsonArray elements) { + if (texture == null || elements == null || elements.isEmpty()) return null; + try { + return new MinecraftModel(texture, elements); + } catch (Exception e) { + PlayerAnimLib.LOGGER.error("Failed to load custom model!", e); + return null; + } + } } diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/animation/PlayerRawAnimationBuilder.java b/minecraft/src/main/java/com/zigythebird/playeranim/animation/PlayerRawAnimationBuilder.java similarity index 100% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/animation/PlayerRawAnimationBuilder.java rename to minecraft/src/main/java/com/zigythebird/playeranim/animation/PlayerRawAnimationBuilder.java diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/animation/keyframe/event/builtin/AutoPlayingSoundKeyframeHandler.java b/minecraft/src/main/java/com/zigythebird/playeranim/animation/keyframe/event/builtin/AutoPlayingSoundKeyframeHandler.java similarity index 100% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/animation/keyframe/event/builtin/AutoPlayingSoundKeyframeHandler.java rename to minecraft/src/main/java/com/zigythebird/playeranim/animation/keyframe/event/builtin/AutoPlayingSoundKeyframeHandler.java diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/animation/layered/modifier/HeadBoundCameraModifier.java b/minecraft/src/main/java/com/zigythebird/playeranim/animation/layered/modifier/HeadBoundCameraModifier.java similarity index 100% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/animation/layered/modifier/HeadBoundCameraModifier.java rename to minecraft/src/main/java/com/zigythebird/playeranim/animation/layered/modifier/HeadBoundCameraModifier.java diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/animation/layered/modifier/MirrorIfLeftHandModifier.java b/minecraft/src/main/java/com/zigythebird/playeranim/animation/layered/modifier/MirrorIfLeftHandModifier.java similarity index 85% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/animation/layered/modifier/MirrorIfLeftHandModifier.java rename to minecraft/src/main/java/com/zigythebird/playeranim/animation/layered/modifier/MirrorIfLeftHandModifier.java index e4259988..bccba01f 100644 --- a/minecraft/common/src/main/java/com/zigythebird/playeranim/animation/layered/modifier/MirrorIfLeftHandModifier.java +++ b/minecraft/src/main/java/com/zigythebird/playeranim/animation/layered/modifier/MirrorIfLeftHandModifier.java @@ -14,8 +14,8 @@ public MirrorIfLeftHandModifier() { } @Override - public PlayerAnimBone get3DTransform(@NotNull PlayerAnimBone bone) { - if (getController() instanceof PlayerAnimationController controller && controller.getAvatar() == Minecraft.getInstance().player && Minecraft.getInstance().options.mainHand().get() == HumanoidArm.LEFT) return bone; - return super.get3DTransform(bone); + public void get3DTransform(@NotNull PlayerAnimBone bone) { + if (getController() instanceof PlayerAnimationController controller && controller.getAvatar() == Minecraft.getInstance().player && Minecraft.getInstance().options.mainHand().get() == HumanoidArm.LEFT) return; + super.get3DTransform(bone); } } diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/api/PlayerAnimationAccess.java b/minecraft/src/main/java/com/zigythebird/playeranim/api/PlayerAnimationAccess.java similarity index 100% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/api/PlayerAnimationAccess.java rename to minecraft/src/main/java/com/zigythebird/playeranim/api/PlayerAnimationAccess.java diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/api/PlayerAnimationFactory.java b/minecraft/src/main/java/com/zigythebird/playeranim/api/PlayerAnimationFactory.java similarity index 100% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/api/PlayerAnimationFactory.java rename to minecraft/src/main/java/com/zigythebird/playeranim/api/PlayerAnimationFactory.java diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/commands/AnimationArgumentProvider.java b/minecraft/src/main/java/com/zigythebird/playeranim/commands/AnimationArgumentProvider.java similarity index 100% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/commands/AnimationArgumentProvider.java rename to minecraft/src/main/java/com/zigythebird/playeranim/commands/AnimationArgumentProvider.java diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/commands/PlayerAnimCommands.java b/minecraft/src/main/java/com/zigythebird/playeranim/commands/PlayerAnimCommands.java similarity index 100% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/commands/PlayerAnimCommands.java rename to minecraft/src/main/java/com/zigythebird/playeranim/commands/PlayerAnimCommands.java diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/AvatarMixin.java b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/AvatarMixin.java similarity index 100% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/AvatarMixin.java rename to minecraft/src/main/java/com/zigythebird/playeranim/mixin/AvatarMixin.java diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/AvatarRenderStateMixin.java b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/AvatarRenderStateMixin.java similarity index 100% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/AvatarRenderStateMixin.java rename to minecraft/src/main/java/com/zigythebird/playeranim/mixin/AvatarRenderStateMixin.java diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/AvatarRendererMixin.java b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/AvatarRendererMixin.java similarity index 98% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/AvatarRendererMixin.java rename to minecraft/src/main/java/com/zigythebird/playeranim/mixin/AvatarRendererMixin.java index cd799c28..759c796a 100644 --- a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/AvatarRendererMixin.java +++ b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/AvatarRendererMixin.java @@ -27,7 +27,6 @@ import com.zigythebird.playeranim.accessors.IAnimatedAvatar; import com.zigythebird.playeranim.accessors.IAvatarAnimationState; import com.zigythebird.playeranim.animation.AvatarAnimManager; -import net.minecraft.client.Minecraft; import net.minecraft.client.model.player.PlayerModel; import net.minecraft.client.player.AbstractClientPlayer; import net.minecraft.client.renderer.entity.EntityRendererProvider; diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/CapeModelAccessor.java b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/CapeModelAccessor.java similarity index 100% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/CapeModelAccessor.java rename to minecraft/src/main/java/com/zigythebird/playeranim/mixin/CapeModelAccessor.java diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/ElytraLayerMixin.java b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/ElytraLayerMixin.java similarity index 92% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/ElytraLayerMixin.java rename to minecraft/src/main/java/com/zigythebird/playeranim/mixin/ElytraLayerMixin.java index 11032719..5db376e6 100644 --- a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/ElytraLayerMixin.java +++ b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/ElytraLayerMixin.java @@ -30,9 +30,9 @@ private void inject(PoseStack poseStack, SubmitNodeCollector submitNodeCollector if (emote != null && emote.isActive() && this.renderer instanceof AvatarRenderer playerRenderer) { playerRenderer.getModel().body.translateAndRotate(poseStack); poseStack.translate(0, 0, 0.125); - PlayerAnimBone bone = emote.get3DTransform(new PlayerAnimBone("elytra")); - bone.applyOtherBone(emote.get3DTransform(new PlayerAnimBone("cape"))); - bone.positionY *= -1; + PlayerAnimBone bone = emote.get3DTransform("elytra"); + bone.applyOtherBone(emote.get3DTransform("cape")); + bone.position.y *= -1; RenderUtil.translateMatrixToBone(poseStack, bone); poseStack.translate(0, 0, -0.125); } diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/ItemInHandLayerMixin.java b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/ItemInHandLayerMixin.java similarity index 89% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/ItemInHandLayerMixin.java rename to minecraft/src/main/java/com/zigythebird/playeranim/mixin/ItemInHandLayerMixin.java index a41ebd6c..3697255a 100644 --- a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/ItemInHandLayerMixin.java +++ b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/ItemInHandLayerMixin.java @@ -64,7 +64,7 @@ private void changeItemLocation(ArmedEntityRenderState renderState, ItemStackRen bone.setToInitialPose(); anim.get3DTransform(bone); - matrices.translate(bone.getPosX()/16, -bone.getPosY()/16, bone.getPosZ()/16); + matrices.translate(bone.position.x/16, -bone.position.y/16, bone.position.z/16); } else active.set(false); } @@ -77,16 +77,16 @@ private void changeItemRotationAndScale(ArmedEntityRenderState renderState, Item if (arm == HumanoidArm.LEFT) bone = playerAnimLib$leftItem; else bone = playerAnimLib$rightItem; - if (bone.getRotY() != 0) - poseStack.mulPose(Axis.ZP.rotation(-bone.getRotY())); + if (bone.rotation.z != 0) + poseStack.mulPose(Axis.ZP.rotation(-bone.rotation.y)); - if (bone.getRotZ() != 0) - poseStack.mulPose(Axis.YP.rotation(-bone.getRotZ())); + if (bone.rotation.y != 0) + poseStack.mulPose(Axis.YP.rotation(-bone.rotation.z)); - if (bone.getRotX() != 0) - poseStack.mulPose(Axis.XP.rotation(-bone.getRotX())); + if (bone.rotation.x != 0) + poseStack.mulPose(Axis.XP.rotation(-bone.rotation.x)); - poseStack.scale(bone.getScaleX(), bone.getScaleY(), bone.getScaleZ()); + poseStack.scale(bone.scale.x, bone.scale.y, bone.scale.z); } } } diff --git a/minecraft/src/main/java/com/zigythebird/playeranim/mixin/LivingEntityRendererMixin.java b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/LivingEntityRendererMixin.java new file mode 100644 index 00000000..b36c13ce --- /dev/null +++ b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/LivingEntityRendererMixin.java @@ -0,0 +1,139 @@ +/* + * MIT License + * + * Copyright (c) 2022 KosmX + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.zigythebird.playeranim.mixin; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.QuadInstance; +import com.zigythebird.playeranim.accessors.IAvatarAnimationState; +import com.zigythebird.playeranim.animation.AvatarAnimManager; +import com.zigythebird.playeranim.animation.MinecraftModel; +import com.zigythebird.playeranim.util.RenderUtil; +import com.zigythebird.playeranimcore.bindings.PlatformModel; +import com.zigythebird.playeranimcore.bones.PlayerAnimBone; +import com.zigythebird.playeranimcore.util.MatrixUtil; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.renderer.SubmitNodeCollector; +import net.minecraft.client.renderer.block.ModelBlockRenderer; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.client.renderer.entity.LivingEntityRenderer; +import net.minecraft.client.renderer.entity.state.LivingEntityRenderState; +import net.minecraft.client.renderer.state.level.CameraRenderState; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.client.resources.model.geometry.BakedQuad; +import net.minecraft.client.resources.model.geometry.QuadCollection; +import net.minecraft.core.Direction; +import net.minecraft.world.entity.LivingEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(LivingEntityRenderer.class) +public abstract class LivingEntityRendererMixin> extends EntityRenderer { + protected LivingEntityRendererMixin(EntityRendererProvider.Context context) { + super(context); + } + + @Inject(method = "submit(Lnet/minecraft/client/renderer/entity/state/LivingEntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/state/level/CameraRenderState;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/LivingEntityRenderer;scale(Lnet/minecraft/client/renderer/entity/state/LivingEntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;)V")) + private void doTranslations(S state, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, CameraRenderState camera, CallbackInfo ci) { + if (state instanceof IAvatarAnimationState avatarRenderState) { + var animationPlayer = avatarRenderState.playerAnimLib$getAnimManager(); + if (animationPlayer != null && animationPlayer.isActive()) { + avatarRenderState.playerAnimLib$getAnimManager().handleAnimations(animationPlayer.getTickDelta(), false, avatarRenderState.playerAnimLib$isFirstPersonPass()); + poseStack.scale(-1.0F, -1.0F, 1.0F); + + //These are additive properties + PlayerAnimBone body = animationPlayer.get3DTransform("body"); + + poseStack.translate(-body.position.x/16, body.position.y/16 + 0.75, body.position.z/16); + body.rotation.x *= -1; + body.rotation.y *= -1; + RenderUtil.rotateMatrixAroundBone(poseStack, body); + poseStack.scale(body.scale.x, body.scale.y, body.scale.z); + + poseStack.translate(0, -0.75, 0); + + poseStack.scale(-1.0F, -1.0F, 1.0F); + } + } + } + + @Inject( + method = "submit(Lnet/minecraft/client/renderer/entity/state/LivingEntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/state/level/CameraRenderState;)V", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitModel(Lnet/minecraft/client/model/Model;Ljava/lang/Object;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/rendertype/RenderType;IIILnet/minecraft/client/renderer/texture/TextureAtlasSprite;ILnet/minecraft/client/renderer/feature/ModelFeatureRenderer$CrumblingOverlay;)V", + shift = At.Shift.AFTER + ) + ) + public void pal$renderCustomModels(S state, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, CameraRenderState camera, CallbackInfo ci) { + if (!(state instanceof IAvatarAnimationState avatarRenderState)) return; + + AvatarAnimManager animationPlayer = avatarRenderState.playerAnimLib$getAnimManager(); + if (animationPlayer == null || !animationPlayer.isActive()) return; + + int lightCoords = state.lightCoords; + + poseStack.pushPose(); + poseStack.scale(-1.0F, -1.0F, 1.0F); + poseStack.translate(-0.53F, -1.501F, -0.53F); + + animationPlayer.collectModels(bone -> { + PlatformModel platformModel = bone.getModel(); + if (!(platformModel instanceof MinecraftModel mcModel)) return; + + QuadCollection bakedPart = mcModel.getGeometry(); + + poseStack.pushPose(); + MatrixUtil.translateToPivotPoint(poseStack.last().pose(), bone.getPivot().div(16)); // idk + animationPlayer.get3DTransform(bone); + RenderUtil.translateMatrixToBone(poseStack, bone); + + submitNodeCollector.submitCustomGeometry( + poseStack, mcModel.getRenderType(), + + (pose, buffer) -> { + QuadInstance instance = new QuadInstance(); + instance.setLightCoords(lightCoords); + instance.setOverlayCoords(OverlayTexture.NO_OVERLAY); + + for (BakedQuad quad : bakedPart.getQuads(null)) { + buffer.putBakedQuad(pose, quad, instance); + } + for (Direction dir : ModelBlockRenderer.DIRECTIONS) { + for (BakedQuad quad : bakedPart.getQuads(dir)) { + buffer.putBakedQuad(pose, quad, instance); + } + } + } + ); + + poseStack.popPose(); + }); + + poseStack.popPose(); + } +} diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/PlayerCapeModelMixin.java b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/PlayerCapeModelMixin.java similarity index 78% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/PlayerCapeModelMixin.java rename to minecraft/src/main/java/com/zigythebird/playeranim/mixin/PlayerCapeModelMixin.java index c0c44b8a..6db51aee 100644 --- a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/PlayerCapeModelMixin.java +++ b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/PlayerCapeModelMixin.java @@ -2,7 +2,6 @@ import com.zigythebird.playeranim.accessors.IAvatarAnimationState; import com.zigythebird.playeranim.accessors.IBoneUpdater; -import com.zigythebird.playeranim.accessors.ICapeLayer; import com.zigythebird.playeranim.animation.AvatarAnimManager; import com.zigythebird.playeranim.util.RenderUtil; import com.zigythebird.playeranimcore.bones.PlayerAnimBone; @@ -20,7 +19,7 @@ //Set the priority high cause why not! @Mixin(value = PlayerCapeModel.class, priority = 2001) -public class PlayerCapeModelMixin implements IBoneUpdater, ICapeLayer { +public class PlayerCapeModelMixin implements IBoneUpdater { @Shadow @Final private ModelPart cape; @@ -31,15 +30,15 @@ private void setupAnim(AvatarRenderState avatarRenderState, CallbackInfo ci) { if (emote != null && emote.isActive()) { PlayerAnimBone bone = RenderUtil.copyVanillaPart(this.cape, new PlayerAnimBone("cape")); - bone.rotX -= MochaMath.PI; - bone.rotZ -= MochaMath.PI; - bone.rotX *= -1; - bone.rotY *= -1; - bone = emote.get3DTransform(bone); - bone.rotX *= -1; - bone.rotY *= -1; - bone.rotX += MochaMath.PI; - bone.rotZ += MochaMath.PI; + bone.rotation.x -= MochaMath.PI; + bone.rotation.z -= MochaMath.PI; + bone.rotation.x *= -1; + bone.rotation.y *= -1; + emote.get3DTransform(bone); + bone.rotation.x *= -1; + bone.rotation.y *= -1; + bone.rotation.x += MochaMath.PI; + bone.rotation.y += MochaMath.PI; this.pal$updatePart(emote, this.cape, bone); } else { @@ -50,11 +49,10 @@ private void setupAnim(AvatarRenderState avatarRenderState, CallbackInfo ci) { @Override public void pal$updatePart(AvatarAnimManager emote, ModelPart part, PlayerAnimBone bone) { RenderUtil.translatePartToCape(part, bone, part.getInitialPose()); - this.applyBend(emote, bone.getBend()); } @Override public void pal$resetAll(@Nullable AvatarAnimManager emote) { - this.resetBend(); + // no-op } } diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/PlayerModelMixin.java b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/PlayerModelMixin.java similarity index 100% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/PlayerModelMixin.java rename to minecraft/src/main/java/com/zigythebird/playeranim/mixin/PlayerModelMixin.java diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/HumanoidArmorLayerMixin.java b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/HumanoidArmorLayerMixin.java similarity index 98% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/HumanoidArmorLayerMixin.java rename to minecraft/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/HumanoidArmorLayerMixin.java index a1e5063e..636d2291 100644 --- a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/HumanoidArmorLayerMixin.java +++ b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/HumanoidArmorLayerMixin.java @@ -44,7 +44,7 @@ public abstract class HumanoidArmorLayerMixin humanoidModel) { if (humanoidRenderState instanceof IAvatarAnimationState state && state.playerAnimLib$isFirstPersonPass()) { - humanoidModel.setAllVisible(false); + humanoidModel.root().visible = false; AvatarAnimManager emote = state.playerAnimLib$getAnimManager(); if (equipmentSlot == EquipmentSlot.CHEST && emote.getFirstPersonConfiguration().isShowArmor()) { humanoidModel.rightArm.visible = emote.getFirstPersonConfiguration().isShowRightArm(); diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/ItemInHandLayerMixin.java b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/ItemInHandLayerMixin.java similarity index 100% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/ItemInHandLayerMixin.java rename to minecraft/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/ItemInHandLayerMixin.java diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/ItemInHandRendererMixin.java b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/ItemInHandRendererMixin.java similarity index 100% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/ItemInHandRendererMixin.java rename to minecraft/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/ItemInHandRendererMixin.java diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/LevelRendererMixin.java b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/LevelRendererMixin.java similarity index 97% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/LevelRendererMixin.java rename to minecraft/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/LevelRendererMixin.java index caa415af..1046b232 100644 --- a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/LevelRendererMixin.java +++ b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/LevelRendererMixin.java @@ -35,7 +35,7 @@ import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.culling.Frustum; import net.minecraft.client.renderer.entity.state.EntityRenderState; -import net.minecraft.client.renderer.state.LevelRenderState; +import net.minecraft.client.renderer.state.level.LevelRenderState; import net.minecraft.world.entity.Entity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/LivingEntityRendererMixin.java b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/LivingEntityRendererMixin.java similarity index 97% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/LivingEntityRendererMixin.java rename to minecraft/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/LivingEntityRendererMixin.java index 2fa6463e..b47c5ad4 100644 --- a/minecraft/common/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/LivingEntityRendererMixin.java +++ b/minecraft/src/main/java/com/zigythebird/playeranim/mixin/firstPerson/LivingEntityRendererMixin.java @@ -39,7 +39,7 @@ @Mixin(value = LivingEntityRenderer.class, priority = 2000) public class LivingEntityRendererMixin { @WrapWithCondition( - method = "submit(Lnet/minecraft/client/renderer/entity/state/LivingEntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/state/CameraRenderState;)V", + method = "submit(Lnet/minecraft/client/renderer/entity/state/LivingEntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/state/level/CameraRenderState;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/layers/RenderLayer;submit(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;ILnet/minecraft/client/renderer/entity/state/EntityRenderState;FF)V")) private boolean filterLayers(RenderLayer layer, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int i, EntityRenderState renderState, float v, float vq) { if (renderState instanceof IAvatarAnimationState state && state.playerAnimLib$isFirstPersonPass()) { diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/molang/MolangQueries.java b/minecraft/src/main/java/com/zigythebird/playeranim/molang/MolangQueries.java similarity index 99% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/molang/MolangQueries.java rename to minecraft/src/main/java/com/zigythebird/playeranim/molang/MolangQueries.java index adb6e600..2e202f15 100644 --- a/minecraft/common/src/main/java/com/zigythebird/playeranim/molang/MolangQueries.java +++ b/minecraft/src/main/java/com/zigythebird/playeranim/molang/MolangQueries.java @@ -154,7 +154,7 @@ public static void setDefaultQueryValues(QueryBinding bindi return 0.0D; } }); - MolangLoader.setDoubleQuery(binding, TIME_OF_DAY, actor -> ((PlayerAnimationController) actor).getAvatar().level().getDayTime() / 24000d); + MolangLoader.setDoubleQuery(binding, TIME_OF_DAY, actor -> ((PlayerAnimationController) actor).getAvatar().level().getDefaultClockTime() / 24000d); MolangLoader.setDoubleQuery(binding, TIME_STAMP, actor -> ((PlayerAnimationController) actor).getAvatar().level().getGameTime()); setDefaultEntityQueryValues(binding); diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/util/ClientUtil.java b/minecraft/src/main/java/com/zigythebird/playeranim/util/ClientUtil.java similarity index 100% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/util/ClientUtil.java rename to minecraft/src/main/java/com/zigythebird/playeranim/util/ClientUtil.java diff --git a/minecraft/common/src/main/java/com/zigythebird/playeranim/util/RenderUtil.java b/minecraft/src/main/java/com/zigythebird/playeranim/util/RenderUtil.java similarity index 51% rename from minecraft/common/src/main/java/com/zigythebird/playeranim/util/RenderUtil.java rename to minecraft/src/main/java/com/zigythebird/playeranim/util/RenderUtil.java index 3f6bd267..913c4456 100644 --- a/minecraft/common/src/main/java/com/zigythebird/playeranim/util/RenderUtil.java +++ b/minecraft/src/main/java/com/zigythebird/playeranim/util/RenderUtil.java @@ -10,65 +10,55 @@ */ public final class RenderUtil { public static void rotateMatrixAroundBone(PoseStack poseStack, PlayerAnimBone bone) { - rotateZYX(poseStack.last(), bone.getRotZ(), bone.getRotY(), bone.getRotX()); + rotateZYX(poseStack.last(), bone.rotation.z, bone.rotation.y, bone.rotation.x); } /** * Here we do nothing with rotation because it is unnecessary. */ public static void translatePartToCape(ModelPart part, PlayerAnimBone bone, PartPose initialPose) { - part.x = bone.getPosX() + initialPose.x(); - part.y = -(bone.getPosY() + initialPose.y()); - part.z = bone.getPosZ() + initialPose.z(); + part.x = bone.position.x + initialPose.x(); + part.y = -(bone.position.y + initialPose.y()); + part.z = bone.position.z + initialPose.z(); - part.xRot = bone.getRotX(); - part.yRot = bone.getRotY(); - part.zRot = bone.getRotZ(); + part.xRot = bone.rotation.x; + part.yRot = bone.rotation.y; + part.zRot = bone.rotation.z; - part.xScale = bone.getScaleX(); - part.yScale = bone.getScaleY(); - part.zScale = bone.getScaleZ(); + part.xScale = bone.scale.x; + part.yScale = bone.scale.y; + part.zScale = bone.scale.z; } /** * Initial pose only applied to yRot and position because that's all that's needed for vanilla parts. */ public static void translatePartToBone(ModelPart part, PlayerAnimBone bone, PartPose initialPose) { - part.x = bone.getPosX() + initialPose.x(); - part.y = -bone.getPosY() + initialPose.y(); - part.z = bone.getPosZ() + initialPose.z(); + part.x = bone.position.x + initialPose.x(); + part.y = -bone.position.y + initialPose.y(); + part.z = bone.position.z + initialPose.z(); - part.xRot = bone.getRotX(); - part.yRot = bone.getRotY() + initialPose.yRot(); - part.zRot = bone.getRotZ(); + part.xRot = bone.rotation.x; + part.yRot = bone.rotation.y + initialPose.yRot(); + part.zRot = bone.rotation.z; - part.xScale = bone.getScaleX(); - part.yScale = bone.getScaleY(); - part.zScale = bone.getScaleZ(); + part.xScale = bone.scale.x; + part.yScale = bone.scale.y; + part.zScale = bone.scale.z; } public static void translateMatrixToBone(PoseStack poseStack, PlayerAnimBone bone) { - poseStack.translate(bone.getPosX() / 16, bone.getPosY() / 16, bone.getPosZ() / 16); + poseStack.translate(bone.position.x / 16, bone.position.y / 16, bone.position.z / 16); RenderUtil.rotateMatrixAroundBone(poseStack, bone); - poseStack.scale(bone.getScaleX(), bone.getScaleY(), bone.getScaleZ()); + poseStack.scale(bone.scale.x, bone.scale.y, bone.scale.z); } public static PlayerAnimBone copyVanillaPart(ModelPart part, PlayerAnimBone bone) { PartPose initialPose = part.getInitialPose(); - bone.setPosX(part.x - initialPose.x()); - bone.setPosY(-(part.y - initialPose.y())); - bone.setPosZ(part.z - initialPose.z()); - - bone.setRotX(part.xRot); - bone.setRotY(part.yRot); - bone.setRotZ(part.zRot); - - bone.setScaleX(part.xScale); - bone.setScaleY(part.yScale); - bone.setScaleZ(part.zScale); - - bone.setBend(0); + bone.position.set(part.x - initialPose.x(), -(part.y - initialPose.y()), part.z - initialPose.z()); + bone.rotation.set(part.xRot, part.yRot, part.zRot); + bone.scale.set(part.xScale, part.yScale, part.zScale); return bone; } diff --git a/minecraft/fabric/src/main/resources/assets/player_animation_library/lang/es_ar.json b/minecraft/src/main/resources/assets/player_animation_library/lang/es_ar.json similarity index 100% rename from minecraft/fabric/src/main/resources/assets/player_animation_library/lang/es_ar.json rename to minecraft/src/main/resources/assets/player_animation_library/lang/es_ar.json diff --git a/minecraft/fabric/src/main/resources/assets/player_animation_library/lang/tt_ru.json b/minecraft/src/main/resources/assets/player_animation_library/lang/tt_ru.json similarity index 100% rename from minecraft/fabric/src/main/resources/assets/player_animation_library/lang/tt_ru.json rename to minecraft/src/main/resources/assets/player_animation_library/lang/tt_ru.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/arm_scale_test_legacy.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/arm_scale_test_legacy.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/arm_scale_test_legacy.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/arm_scale_test_legacy.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/arm_stretch_test.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/arm_stretch_test.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/arm_stretch_test.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/arm_stretch_test.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/axis_test.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/axis_test.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/axis_test.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/axis_test.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/axis_test_blender.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/axis_test_blender.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/axis_test_blender.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/axis_test_blender.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/axis_test_body.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/axis_test_body.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/axis_test_body.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/axis_test_body.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/axis_test_body_blender.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/axis_test_body_blender.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/axis_test_body_blender.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/axis_test_body_blender.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/backflip.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/backflip.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/backflip.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/backflip.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/bend_test.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/bend_test.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/bend_test.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/bend_test.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/bend_test7.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/bend_test7.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/bend_test7.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/bend_test7.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/bend_test8.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/bend_test8.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/bend_test8.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/bend_test8.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/body_translation_axis_test.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/body_translation_axis_test.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/body_translation_axis_test.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/body_translation_axis_test.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/body_translation_axis_test_blender.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/body_translation_axis_test_blender.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/body_translation_axis_test_blender.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/body_translation_axis_test_blender.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/camera_test.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/camera_test.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/camera_test.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/camera_test.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/cape_elytra_testing.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/cape_elytra_testing.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/cape_elytra_testing.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/cape_elytra_testing.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/cape_rot_axis_test.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/cape_rot_axis_test.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/cape_rot_axis_test.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/cape_rot_axis_test.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/cape_translation_axis_test.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/cape_translation_axis_test.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/cape_translation_axis_test.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/cape_translation_axis_test.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/club_penguin_dance.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/club_penguin_dance.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/club_penguin_dance.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/club_penguin_dance.json diff --git a/minecraft/src/main/resources/assets/player_animation_library/player_animations/cmm_test.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/cmm_test.json new file mode 100644 index 00000000..9abb53c1 --- /dev/null +++ b/minecraft/src/main/resources/assets/player_animation_library/player_animations/cmm_test.json @@ -0,0 +1,32 @@ +{ + "format_version": "1.8.0", + "model": { + "cmm": { + "pivot": [ 0, 12, 0 ], + + "texture": "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAfUlEQVR4Xo1QiRHAIAhzUAZgC7foAg5KjSkq1OsVr1qS8Jby18TE1PivBi/R1a4JwmtRIp1uHUYOHeIlnxEOQoyz5ZBB40MOxNNPAsL6vKEIBIxBHx5/ECzqIHBwFQg9+BT7XeOguUTYw56DL5p9LZvrxpggE00DzJOZD7sBRaHjpRD91mQAAAAASUVORK5CYII=", + "elements": [ + { + "from": [ 0, 0.25, 0 ], + "to": [ 16, 0.25, 16 ], + "faces": { + "down": { "uv": [ 0, 16, 16, 0 ], "texture": "#texture", "tintindex": 0 }, + "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#texture", "tintindex": 0 } + } + } + ] + } + }, + "animations": { + "cmm_test1": { + "loop": true, + "bones": { + "cmm": { + "rotation": { + "vector": [0, "q.anim_time * 20", 0] + } + } + } + } + } +} \ No newline at end of file diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/custom_pivot_test.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/custom_pivot_test.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/custom_pivot_test.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/custom_pivot_test.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/disable_tests.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/disable_tests.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/disable_tests.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/disable_tests.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/gun_reload.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/gun_reload.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/gun_reload.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/gun_reload.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/hold_on_last_frame.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/hold_on_last_frame.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/hold_on_last_frame.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/hold_on_last_frame.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/item_pos_axis_test.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/item_pos_axis_test.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/item_pos_axis_test.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/item_pos_axis_test.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/item_pos_axis_test2_blender.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/item_pos_axis_test2_blender.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/item_pos_axis_test2_blender.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/item_pos_axis_test2_blender.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/item_pos_axis_test_blender.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/item_pos_axis_test_blender.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/item_pos_axis_test_blender.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/item_pos_axis_test_blender.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/item_rot_axis_test.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/item_rot_axis_test.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/item_rot_axis_test.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/item_rot_axis_test.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/item_rot_axis_test2_blender.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/item_rot_axis_test2_blender.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/item_rot_axis_test2_blender.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/item_rot_axis_test2_blender.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/item_rot_axis_test_blender.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/item_rot_axis_test_blender.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/item_rot_axis_test_blender.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/item_rot_axis_test_blender.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/kazotsky_kick.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/kazotsky_kick.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/kazotsky_kick.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/kazotsky_kick.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/molang_tests.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/molang_tests.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/molang_tests.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/molang_tests.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/running.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/running.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/running.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/running.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/test_cape_example.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/test_cape_example.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/test_cape_example.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/test_cape_example.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/test_cape_example_head.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/test_cape_example_head.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/test_cape_example_head.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/test_cape_example_head.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/test_cape_example_torso_0.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/test_cape_example_torso_0.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/test_cape_example_torso_0.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/test_cape_example_torso_0.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/test_cape_example_torso_1.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/test_cape_example_torso_1.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/test_cape_example_torso_1.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/test_cape_example_torso_1.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/test_cape_example_torso_2.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/test_cape_example_torso_2.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/test_cape_example_torso_2.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/test_cape_example_torso_2.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/test_cape_shit.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/test_cape_shit.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/test_cape_shit.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/test_cape_shit.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/test_cape_shit2.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/test_cape_shit2.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/test_cape_shit2.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/test_cape_shit2.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/test_test_cape_axes.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/test_test_cape_axes.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/test_test_cape_axes.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/test_test_cape_axes.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/torso_rot_axis_test.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/torso_rot_axis_test.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/torso_rot_axis_test.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/torso_rot_axis_test.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/torso_translation_axis_test.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/torso_translation_axis_test.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/torso_translation_axis_test.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/torso_translation_axis_test.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/translation_axis_test.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/translation_axis_test.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/translation_axis_test.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/translation_axis_test.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/translation_axis_test_blender.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/translation_axis_test_blender.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/translation_axis_test_blender.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/translation_axis_test_blender.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/twerk.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/twerk.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/twerk.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/twerk.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/wave.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/wave.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/wave.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/wave.json diff --git a/minecraft/common/src/main/resources/assets/player_animation_library/player_animations/waving.json b/minecraft/src/main/resources/assets/player_animation_library/player_animations/waving.json similarity index 100% rename from minecraft/common/src/main/resources/assets/player_animation_library/player_animations/waving.json rename to minecraft/src/main/resources/assets/player_animation_library/player_animations/waving.json diff --git a/minecraft/fabric/src/main/resources/icon.png b/minecraft/src/main/resources/icon.png similarity index 100% rename from minecraft/fabric/src/main/resources/icon.png rename to minecraft/src/main/resources/icon.png diff --git a/minecraft/src/main/resources/player_animation_library.classtweaker b/minecraft/src/main/resources/player_animation_library.classtweaker new file mode 100644 index 00000000..99db3247 --- /dev/null +++ b/minecraft/src/main/resources/player_animation_library.classtweaker @@ -0,0 +1,10 @@ +classTweaker v1 official +extendable class net/minecraft/client/model/geom/ModelPart +accessible field net/minecraft/client/renderer/LevelRenderer levelRenderState Lnet/minecraft/client/renderer/state/level/LevelRenderState; +accessible field net/minecraft/client/renderer/entity/layers/RenderLayer renderer Lnet/minecraft/client/renderer/entity/RenderLayerParent; +accessible field net/minecraft/client/renderer/entity/LivingEntityRenderer layers Ljava/util/List; +accessible field net/minecraft/client/resources/model/cuboid/CuboidModel GSON Lcom/google/gson/Gson; +accessible method net/minecraft/client/renderer/texture/TextureAtlasSprite (Lnet/minecraft/resources/Identifier;Lnet/minecraft/client/renderer/texture/SpriteContents;IIIII)V +accessible field net/minecraft/client/renderer/block/ModelBlockRenderer DIRECTIONS [Lnet/minecraft/core/Direction; +transitive-inject-interface net/minecraft/world/entity/Avatar com/zigythebird/playeranim/accessors/IAnimatedAvatar +transitive-inject-interface net/minecraft/client/renderer/entity/state/AvatarRenderState com/zigythebird/playeranim/accessors/IAvatarAnimationState diff --git a/minecraft/common/src/main/resources/player_animation_library.mixins.json b/minecraft/src/main/resources/player_animation_library.mixins.json similarity index 100% rename from minecraft/common/src/main/resources/player_animation_library.mixins.json rename to minecraft/src/main/resources/player_animation_library.mixins.json diff --git a/minecraft/neoforge/src/main/java/com/zigythebird/playeranim/neoforge/PlayerAnimLibModNeo.java b/minecraft/src/neoforge/java/com/zigythebird/playeranim/neoforge/PlayerAnimLibModNeo.java similarity index 100% rename from minecraft/neoforge/src/main/java/com/zigythebird/playeranim/neoforge/PlayerAnimLibModNeo.java rename to minecraft/src/neoforge/java/com/zigythebird/playeranim/neoforge/PlayerAnimLibModNeo.java diff --git a/minecraft/neoforge/src/main/java/com/zigythebird/playeranim/neoforge/PlayerAnimLibServiceImpl.java b/minecraft/src/neoforge/java/com/zigythebird/playeranim/neoforge/PlayerAnimLibServiceImpl.java similarity index 62% rename from minecraft/neoforge/src/main/java/com/zigythebird/playeranim/neoforge/PlayerAnimLibServiceImpl.java rename to minecraft/src/neoforge/java/com/zigythebird/playeranim/neoforge/PlayerAnimLibServiceImpl.java index 35e10ea5..5bdd337d 100644 --- a/minecraft/neoforge/src/main/java/com/zigythebird/playeranim/neoforge/PlayerAnimLibServiceImpl.java +++ b/minecraft/src/neoforge/java/com/zigythebird/playeranim/neoforge/PlayerAnimLibServiceImpl.java @@ -4,6 +4,16 @@ import net.neoforged.fml.loading.FMLLoader; public final class PlayerAnimLibServiceImpl implements PlayerAnimLibService { + @Override + public boolean isActive() { + try { + Class.forName("net.neoforged.fml.loading.FMLLoader"); + return true; + } catch (Exception th) { + return false; + } + } + @Override public boolean isModLoaded(String id) { return FMLLoader.getCurrent().getLoadingModList().getModFileById(id) != null; diff --git a/minecraft/neoforge/src/main/java/com/zigythebird/playeranim/neoforge/event/MolangEvent.java b/minecraft/src/neoforge/java/com/zigythebird/playeranim/neoforge/event/MolangEvent.java similarity index 100% rename from minecraft/neoforge/src/main/java/com/zigythebird/playeranim/neoforge/event/MolangEvent.java rename to minecraft/src/neoforge/java/com/zigythebird/playeranim/neoforge/event/MolangEvent.java diff --git a/minecraft/neoforge/src/main/java/com/zigythebird/playeranim/neoforge/event/PlayerAnimationRegisterEvent.java b/minecraft/src/neoforge/java/com/zigythebird/playeranim/neoforge/event/PlayerAnimationRegisterEvent.java similarity index 100% rename from minecraft/neoforge/src/main/java/com/zigythebird/playeranim/neoforge/event/PlayerAnimationRegisterEvent.java rename to minecraft/src/neoforge/java/com/zigythebird/playeranim/neoforge/event/PlayerAnimationRegisterEvent.java diff --git a/minecraft/src/neoforge/resources/META-INF/accesstransformer.cfg b/minecraft/src/neoforge/resources/META-INF/accesstransformer.cfg new file mode 100644 index 00000000..d3da0041 --- /dev/null +++ b/minecraft/src/neoforge/resources/META-INF/accesstransformer.cfg @@ -0,0 +1,6 @@ +public-f net.minecraft.client.model.geom.ModelPart +public net.minecraft.client.renderer.LevelRenderer levelRenderState +public net.minecraft.client.renderer.entity.layers.RenderLayer renderer +public net.minecraft.client.renderer.entity.LivingEntityRenderer layers +public net.minecraft.client.renderer.block.model.BlockModel GSON +public net.minecraft.client.renderer.texture.TextureAtlasSprite (Lnet/minecraft/resources/Identifier;Lnet/minecraft/client/renderer/texture/SpriteContents;IIIII)V \ No newline at end of file diff --git a/minecraft/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/minecraft/src/neoforge/resources/META-INF/neoforge.mods.toml similarity index 92% rename from minecraft/neoforge/src/main/resources/META-INF/neoforge.mods.toml rename to minecraft/src/neoforge/resources/META-INF/neoforge.mods.toml index bcaf4147..542f6547 100644 --- a/minecraft/neoforge/src/main/resources/META-INF/neoforge.mods.toml +++ b/minecraft/src/neoforge/resources/META-INF/neoforge.mods.toml @@ -18,14 +18,14 @@ logoFile = "icon.png" [[dependencies.player_animation_library]] modId = "neoforge" type = "required" -versionRange = "[21.11.0-beta,)" +versionRange = "[26.1.0.0-alpha,)" ordering = "NONE" side = "BOTH" [[dependencies.player_animation_library]] modId = "minecraft" type = "required" -versionRange = "[1.21.11,)" +versionRange = "[26.1,)" ordering = "NONE" side = "BOTH" diff --git a/minecraft/neoforge/src/main/resources/META-INF/services/com.zigythebird.playeranim.PlayerAnimLibService b/minecraft/src/neoforge/resources/META-INF/services/com.zigythebird.playeranim.PlayerAnimLibService similarity index 100% rename from minecraft/neoforge/src/main/resources/META-INF/services/com.zigythebird.playeranim.PlayerAnimLibService rename to minecraft/src/neoforge/resources/META-INF/services/com.zigythebird.playeranim.PlayerAnimLibService diff --git a/settings.gradle b/settings.gradle index bf4d7959..a9a06409 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,9 +1,8 @@ pluginManagement { repositories { - maven { url = "https://maven.fabricmc.net/" } - maven { url = "https://maven.architectury.dev/" } - maven { url = "https://maven.neoforged.net/releases" } maven { url = "https://repo.redlance.org/public" } + maven { url = "https://maven.wagyourtail.xyz/releases" } + maven { url = "https://maven.wagyourtail.xyz/snapshots" } gradlePluginPortal() } } @@ -12,7 +11,3 @@ rootProject.name = "player_animation_library" include("core") include("minecraft") - -include("minecraft:common") -include("minecraft:fabric") -include("minecraft:neoforge")