From ce8d4128cad4ab8b98613efa2304ba63f433d1eb Mon Sep 17 00:00:00 2001 From: 17146 <1714673995@qq.com> Date: Sun, 1 Jun 2025 02:49:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9E=81=E5=85=B6=E9=80=86?= =?UTF-8?q?=E5=A4=A9=E7=9A=84molang=E6=B8=B2=E6=9F=93=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/model/item/CustomGunModel.java | 78 ++++++++++++++++++- .../mixins/AnimationProcessorAccessor.java | 14 ++++ .../mixins/GeoModelAccessor.java | 27 +++++++ src/main/resources/mixins.superbwarfare.json | 2 + 4 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/atsuishio/superbwarfare/mixins/AnimationProcessorAccessor.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/mixins/GeoModelAccessor.java diff --git a/src/main/java/com/atsuishio/superbwarfare/client/model/item/CustomGunModel.java b/src/main/java/com/atsuishio/superbwarfare/client/model/item/CustomGunModel.java index 60263a9e1..e3a6dbbee 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/model/item/CustomGunModel.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/model/item/CustomGunModel.java @@ -3,21 +3,68 @@ package com.atsuishio.superbwarfare.client.model.item; import com.atsuishio.superbwarfare.client.molang.MolangVariable; import com.atsuishio.superbwarfare.data.gun.GunData; import com.atsuishio.superbwarfare.item.gun.GunItem; +import com.atsuishio.superbwarfare.mixins.AnimationProcessorAccessor; +import com.atsuishio.superbwarfare.mixins.GeoModelAccessor; import net.minecraft.client.Minecraft; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; import software.bernie.geckolib.animatable.GeoAnimatable; import software.bernie.geckolib.animatable.GeoItem; +import software.bernie.geckolib.animation.AnimatableManager; +import software.bernie.geckolib.animation.AnimationProcessor; import software.bernie.geckolib.animation.AnimationState; import software.bernie.geckolib.constant.DataTickets; import software.bernie.geckolib.loading.math.MathParser; import software.bernie.geckolib.loading.math.MolangQueries; import software.bernie.geckolib.model.GeoModel; +import software.bernie.geckolib.util.RenderUtil; import java.util.function.DoubleSupplier; public abstract class CustomGunModel extends GeoModel { + // TODO 优化这一坨 + @Override + public void setCustomAnimations(T animatable, long instanceId, AnimationState animationState) { + Minecraft mc = Minecraft.getInstance(); + AnimatableManager animatableManager = animatable.getAnimatableInstanceCache().getManagerForId(instanceId); + Double currentTick = animationState.getData(DataTickets.TICK); + + if (currentTick == null) + currentTick = RenderUtil.getCurrentTick(); + +// if (animatableManager.getFirstTickTime() == -1) +// animatableManager.startedAt(currentTick + mc.getFrameTime()); + + double currentFrameTime = currentTick - animatableManager.getFirstTickTime(); + boolean isReRender = !animatableManager.isFirstTick() && currentFrameTime == animatableManager.getLastUpdateTime(); + + if (isReRender && instanceId == ((GeoModelAccessor) this).getLastRenderedInstance()) + return; + + if (!mc.isPaused() || animatable.shouldPlayAnimsWhileGamePaused()) { + animatableManager.updatedAt(currentFrameTime); + + double lastUpdateTime = animatableManager.getLastUpdateTime(); + ((GeoModelAccessor) this).setAnimTime(((GeoModelAccessor) this).getAnimTime() + lastUpdateTime - ((GeoModelAccessor) this).getLastGameTickTime()); + ((GeoModelAccessor) this).setLastGameTickTime(lastUpdateTime); + } + + animationState.animationTick = ((GeoModelAccessor) this).getAnimTime(); + ((GeoModelAccessor) this).setLastRenderedInstance(instanceId); + AnimationProcessor processor = getAnimationProcessor(); + + var model = ((AnimationProcessorAccessor) processor).getModel(); + if (model instanceof CustomGunModel customGunModel) { + customGunModel.applyCustomMolangQueries(animationState, ((GeoModelAccessor) this).getAnimTime()); + } + + if (!processor.getRegisteredBones().isEmpty()) + processor.tickAnimation(animatable, this, animatableManager, ((GeoModelAccessor) this).getAnimTime(), animationState, crashIfBoneMissing()); + + setCustomAnimations(animatable, instanceId, animationState); + } + @Override public void applyMolangQueries(AnimationState animationState, double animTime) { Minecraft mc = Minecraft.getInstance(); @@ -31,14 +78,37 @@ public abstract class CustomGunModel extends } set(MolangVariable.SBW_SYSTEM_TIME, System::currentTimeMillis); + } + + public void applyCustomMolangQueries(AnimationState animationState, double animTime) { + this.applyMolangQueries(animationState, animTime); + + Minecraft mc = Minecraft.getInstance(); // GunData var player = mc.player; - if (player == null) return; + if (player == null) { + resetQueryValue(); + return; + } var stack = player.getMainHandItem(); - if (!(stack.getItem() instanceof GunItem)) return; + if (!(stack.getItem() instanceof GunItem)) { + resetQueryValue(); + return; + } + + var item = animationState.getData(DataTickets.ITEMSTACK); + if (item == null || GeoItem.getId(item) != GeoItem.getId(stack)) { + resetQueryValue(); + return; + } + + if (animationState.getData(DataTickets.ITEM_RENDER_PERSPECTIVE) != ItemDisplayContext.FIRST_PERSON_RIGHT_HAND) { + resetQueryValue(); + return; + } var data = GunData.from(stack); @@ -50,6 +120,10 @@ public abstract class CustomGunModel extends MathParser.setVariable(key, value); } + private void resetQueryValue() { + MathParser.setVariable(MolangVariable.SBW_IS_EMPTY, () -> 0); + } + public boolean shouldCancelRender(ItemStack stack, AnimationState animationState) { if (!(stack.getItem() instanceof GunItem)) return true; var item = animationState.getData(DataTickets.ITEMSTACK); diff --git a/src/main/java/com/atsuishio/superbwarfare/mixins/AnimationProcessorAccessor.java b/src/main/java/com/atsuishio/superbwarfare/mixins/AnimationProcessorAccessor.java new file mode 100644 index 000000000..4458408f1 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/mixins/AnimationProcessorAccessor.java @@ -0,0 +1,14 @@ +package com.atsuishio.superbwarfare.mixins; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import software.bernie.geckolib.animatable.GeoAnimatable; +import software.bernie.geckolib.animation.AnimationProcessor; +import software.bernie.geckolib.model.GeoModel; + +@Mixin(AnimationProcessor.class) +public interface AnimationProcessorAccessor { + + @Accessor(value = "model", remap = false) + GeoModel getModel(); +} diff --git a/src/main/java/com/atsuishio/superbwarfare/mixins/GeoModelAccessor.java b/src/main/java/com/atsuishio/superbwarfare/mixins/GeoModelAccessor.java new file mode 100644 index 000000000..3ca25babc --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/mixins/GeoModelAccessor.java @@ -0,0 +1,27 @@ +package com.atsuishio.superbwarfare.mixins; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import software.bernie.geckolib.model.GeoModel; + +@Mixin(GeoModel.class) +public interface GeoModelAccessor { + + @Accessor(value = "animTime", remap = false) + double getAnimTime(); + + @Accessor(value = "animTime", remap = false) + void setAnimTime(double animTime); + + @Accessor(value = "lastGameTickTime", remap = false) + double getLastGameTickTime(); + + @Accessor(value = "lastGameTickTime", remap = false) + void setLastGameTickTime(double lastGameTickTime); + + @Accessor(value = "lastRenderedInstance", remap = false) + long getLastRenderedInstance(); + + @Accessor(value = "lastRenderedInstance", remap = false) + void setLastRenderedInstance(long lastRenderedInstance); +} diff --git a/src/main/resources/mixins.superbwarfare.json b/src/main/resources/mixins.superbwarfare.json index 5ca591322..f807b8e49 100644 --- a/src/main/resources/mixins.superbwarfare.json +++ b/src/main/resources/mixins.superbwarfare.json @@ -4,10 +4,12 @@ "compatibilityLevel": "JAVA_21", "refmap": "mixins.superbwarfare.refmap.json", "mixins": [ + "AnimationProcessorAccessor", "BeastMixin", "ClientboundSetPassengersPacketMixin", "EntityMixin", "FishingHookMixin", + "GeoModelAccessor", "LivingEntityMixin", "PlayerMixin", "VillagerMixin"