diff --git a/coreLib/src/main/java/dev/kosmx/playerAnim/api/firstPerson/FirstPersonConfiguration.java b/coreLib/src/main/java/dev/kosmx/playerAnim/api/firstPerson/FirstPersonConfiguration.java index 167307c..c3bb413 100644 --- a/coreLib/src/main/java/dev/kosmx/playerAnim/api/firstPerson/FirstPersonConfiguration.java +++ b/coreLib/src/main/java/dev/kosmx/playerAnim/api/firstPerson/FirstPersonConfiguration.java @@ -14,4 +14,5 @@ public class FirstPersonConfiguration { boolean showLeftArm = false; boolean showRightItem = true; boolean showLeftItem = true; + boolean showArmor = false; } diff --git a/coreLib/src/main/java/dev/kosmx/playerAnim/api/firstPerson/FirstPersonMode.java b/coreLib/src/main/java/dev/kosmx/playerAnim/api/firstPerson/FirstPersonMode.java index 1894a0b..3b35197 100644 --- a/coreLib/src/main/java/dev/kosmx/playerAnim/api/firstPerson/FirstPersonMode.java +++ b/coreLib/src/main/java/dev/kosmx/playerAnim/api/firstPerson/FirstPersonMode.java @@ -15,7 +15,8 @@ public enum FirstPersonMode { VANILLA(true), /** - * Use the 3rd person player model (only arms/items) to render accurate first-person perspective + * Use the 3rd person player model (only arms/items/shoulder armor) to render accurate first-person perspective. + * Note that armor rendering is disabled in the default FirstPersonConfiguration. {@link FirstPersonConfiguration#showShoulder} */ THIRD_PERSON_MODEL(true), @@ -24,7 +25,7 @@ public enum FirstPersonMode { */ DISABLED(false), -; + ; @Getter private final boolean enabled; diff --git a/minecraft/common/src/main/java/dev/kosmx/playerAnim/mixin/ArmorFeatureRendererMixin.java b/minecraft/common/src/main/java/dev/kosmx/playerAnim/mixin/ArmorFeatureRendererMixin.java index e3631e1..157a3a1 100644 --- a/minecraft/common/src/main/java/dev/kosmx/playerAnim/mixin/ArmorFeatureRendererMixin.java +++ b/minecraft/common/src/main/java/dev/kosmx/playerAnim/mixin/ArmorFeatureRendererMixin.java @@ -1,21 +1,51 @@ package dev.kosmx.playerAnim.mixin; +import dev.kosmx.playerAnim.api.firstPerson.FirstPersonMode; +import dev.kosmx.playerAnim.impl.IAnimatedPlayer; import dev.kosmx.playerAnim.impl.IUpperPartHelper; +import dev.kosmx.playerAnim.impl.animation.AnimationApplier; +import net.minecraft.client.Minecraft; import net.minecraft.client.model.HumanoidModel; import net.minecraft.client.renderer.entity.RenderLayerParent; import net.minecraft.client.renderer.entity.layers.HumanoidArmorLayer; +import net.minecraft.client.renderer.entity.layers.RenderLayer; import net.minecraft.client.resources.model.ModelManager; +import net.minecraft.world.entity.EquipmentSlot; 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; +import static net.minecraft.world.entity.EquipmentSlot.CHEST; + @Mixin(HumanoidArmorLayer.class) -public class ArmorFeatureRendererMixin, A extends HumanoidModel> { +public abstract class ArmorFeatureRendererMixin, A extends HumanoidModel> extends RenderLayer { + + protected ArmorFeatureRendererMixin(RenderLayerParent renderLayerParent) { + super(renderLayerParent); + } @Inject(method = "", at = @At("RETURN")) - private void initInject(RenderLayerParent context, A leggingsModel, A bodyModel, ModelManager modelManager, CallbackInfo ci){ - ((IUpperPartHelper)this).setUpperPart(false); + private void initInject(RenderLayerParent context, A leggingsModel, A bodyModel, ModelManager modelManager, CallbackInfo ci) { + ((IUpperPartHelper) this).setUpperPart(false); + } + + @Inject( + method = "setPartVisibility", + at = @At("HEAD"), + cancellable = true + ) + private void modifyArmorVisibility(A humanoidModel, EquipmentSlot equipmentSlot, CallbackInfo ci) { + AnimationApplier emote = ((IAnimatedPlayer) Minecraft.getInstance().player).playerAnimator_getAnimation(); + if (emote.isActive() && emote.getFirstPersonMode() == FirstPersonMode.THIRD_PERSON_MODEL && emote.getFirstPersonConfiguration().isShowArmor() && FirstPersonMode.isFirstPersonPass()) { + humanoidModel.setAllVisible(false); + if (equipmentSlot == CHEST) { + humanoidModel.rightArm.visible = emote.getFirstPersonConfiguration().isShowRightArm(); + humanoidModel.leftArm.visible = emote.getFirstPersonConfiguration().isShowLeftArm(); + humanoidModel.body.visible = false; + } + ci.cancel(); + } } } diff --git a/minecraft/common/src/main/java/dev/kosmx/playerAnim/mixin/firstPerson/ItemInHandRendererMixin.java b/minecraft/common/src/main/java/dev/kosmx/playerAnim/mixin/firstPerson/ItemInHandRendererMixin.java index 4da8a80..3a0a66f 100644 --- a/minecraft/common/src/main/java/dev/kosmx/playerAnim/mixin/firstPerson/ItemInHandRendererMixin.java +++ b/minecraft/common/src/main/java/dev/kosmx/playerAnim/mixin/firstPerson/ItemInHandRendererMixin.java @@ -19,9 +19,10 @@ public class ItemInHandRendererMixin { @Inject(method = "renderHandsWithItems", at = @At("HEAD"), cancellable = true) private void disableDefaultItemIfNeeded(float f, PoseStack poseStack, MultiBufferSource.BufferSource bufferSource, LocalPlayer localPlayer, int i, CallbackInfo ci) { - if (localPlayer instanceof IAnimatedPlayer player && player.playerAnimator_getAnimation().getFirstPersonMode() == FirstPersonMode.THIRD_PERSON_MODEL) { - ci.cancel(); - } + if (localPlayer instanceof IAnimatedPlayer player && (player.playerAnimator_getAnimation().getFirstPersonMode() == FirstPersonMode.THIRD_PERSON_MODEL)) { + ci.cancel(); + } + } /* AW needed, I may do it later diff --git a/minecraft/common/src/main/java/dev/kosmx/playerAnim/mixin/firstPerson/LevelRendererMixin.java b/minecraft/common/src/main/java/dev/kosmx/playerAnim/mixin/firstPerson/LevelRendererMixin.java index af85199..67f9b6e 100644 --- a/minecraft/common/src/main/java/dev/kosmx/playerAnim/mixin/firstPerson/LevelRendererMixin.java +++ b/minecraft/common/src/main/java/dev/kosmx/playerAnim/mixin/firstPerson/LevelRendererMixin.java @@ -31,18 +31,18 @@ public class LevelRendererMixin { private void fakeThirdPersonMode(DeltaTracker deltaTracker, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, Matrix4f matrix4f2, CallbackInfo ci) { // mods may need to redirect that method, I want to avoid compatibility issues as long as possible defaultCameraState = camera.isDetached(); - if (camera.getEntity() instanceof IAnimatedPlayer player && player.playerAnimator_getAnimation().getFirstPersonMode() == FirstPersonMode.THIRD_PERSON_MODEL) { - FirstPersonMode.setFirstPersonPass(!camera.isDetached() && (!(camera.getEntity() instanceof LivingEntity) || !((LivingEntity)camera.getEntity()).isSleeping())); // this will cause a lot of pain - ((CameraAccessor)camera).setDetached(true); + if (camera.getEntity() instanceof IAnimatedPlayer player && (player.playerAnimator_getAnimation().getFirstPersonMode() == FirstPersonMode.THIRD_PERSON_MODEL)) { + FirstPersonMode.setFirstPersonPass(!camera.isDetached() && (!(camera.getEntity() instanceof LivingEntity) || !((LivingEntity) camera.getEntity()).isSleeping())); // this will cause a lot of pain + ((CameraAccessor) camera).setDetached(true); } } + @Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;isDetached()Z", shift = At.Shift.AFTER)) private void resetThirdPerson(DeltaTracker deltaTracker, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, Matrix4f matrix4f2, CallbackInfo ci) { - ((CameraAccessor)camera).setDetached(defaultCameraState); + ((CameraAccessor) camera).setDetached(defaultCameraState); } - @Inject(method = "renderEntity", at = @At("TAIL")) private void dontRenderEntity_End(Entity entity, double cameraX, double cameraY, double cameraZ, float tickDelta, PoseStack matrices, MultiBufferSource vertexConsumers, CallbackInfo ci) { diff --git a/minecraft/common/src/main/java/dev/kosmx/playerAnim/mixin/firstPerson/LivingEntityRendererMixin.java b/minecraft/common/src/main/java/dev/kosmx/playerAnim/mixin/firstPerson/LivingEntityRendererMixin.java index b5d162a..6f1e030 100644 --- a/minecraft/common/src/main/java/dev/kosmx/playerAnim/mixin/firstPerson/LivingEntityRendererMixin.java +++ b/minecraft/common/src/main/java/dev/kosmx/playerAnim/mixin/firstPerson/LivingEntityRendererMixin.java @@ -5,6 +5,7 @@ import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.entity.LivingEntityRenderer; +import net.minecraft.client.renderer.entity.layers.HumanoidArmorLayer; import net.minecraft.client.renderer.entity.layers.PlayerItemInHandLayer; import net.minecraft.world.entity.LivingEntity; import org.objectweb.asm.Opcodes; @@ -25,7 +26,7 @@ public class LivingEntityRendererMixin { at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/entity/LivingEntityRenderer;layers:Ljava/util/List;", opcode = Opcodes.GETFIELD)) private List filterLayers(LivingEntityRenderer instance, LivingEntity entity, float f, float g, PoseStack poseStack, MultiBufferSource multiBufferSource, int i) { if (entity instanceof LocalPlayer && FirstPersonMode.isFirstPersonPass()) { - return layers.stream().filter(layer -> layer instanceof PlayerItemInHandLayer).toList(); + return layers.stream().filter(layer -> layer instanceof PlayerItemInHandLayer || layer instanceof HumanoidArmorLayer).toList(); } else return layers; } }