mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-23 21:38:00 +01:00
Add climbing animations in first person mode and fixed changeling's climbing animations not playing. Fixes #164
This commit is contained in:
parent
27051ec13f
commit
b8a0167ff7
5 changed files with 159 additions and 30 deletions
|
@ -2,15 +2,18 @@ package com.minelittlepony.unicopia.client;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import com.google.common.base.MoreObjects;
|
||||||
import com.minelittlepony.unicopia.client.render.AccessoryFeatureRenderer;
|
import com.minelittlepony.unicopia.client.render.AccessoryFeatureRenderer;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
|
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.network.ClientPlayerEntity;
|
import net.minecraft.client.network.ClientPlayerEntity;
|
||||||
import net.minecraft.client.render.VertexConsumerProvider;
|
import net.minecraft.client.render.VertexConsumerProvider;
|
||||||
import net.minecraft.client.render.item.HeldItemRenderer;
|
import net.minecraft.client.render.item.HeldItemRenderer;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.util.Arm;
|
import net.minecraft.util.Arm;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
|
||||||
public class FirstPersonRendererOverrides {
|
public class FirstPersonRendererOverrides {
|
||||||
public static final FirstPersonRendererOverrides INSTANCE = new FirstPersonRendererOverrides();
|
public static final FirstPersonRendererOverrides INSTANCE = new FirstPersonRendererOverrides();
|
||||||
|
@ -21,12 +24,35 @@ public class FirstPersonRendererOverrides {
|
||||||
|
|
||||||
public boolean beforeRenderHands(ArmRenderer sender, float tickDelta, MatrixStack matrices, VertexConsumerProvider.Immediate vertexConsumers, ClientPlayerEntity player, int light) {
|
public boolean beforeRenderHands(ArmRenderer sender, float tickDelta, MatrixStack matrices, VertexConsumerProvider.Immediate vertexConsumers, ClientPlayerEntity player, int light) {
|
||||||
var root = AccessoryFeatureRenderer.FeatureRoot.of(player);
|
var root = AccessoryFeatureRenderer.FeatureRoot.of(player);
|
||||||
return root != null && root.getAccessories().beforeRenderArms(sender, tickDelta, matrices, vertexConsumers, player, light);
|
boolean cancelled = root != null && root.getAccessories().beforeRenderArms(sender, tickDelta, matrices, vertexConsumers, player, light);
|
||||||
|
|
||||||
|
if (cancelled) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Pony.of(player).getAnimation().renderBothArms()) {
|
||||||
|
float swingProgress = player.getHandSwingProgress(MinecraftClient.getInstance().getTickDelta());
|
||||||
|
|
||||||
|
Hand hand = MoreObjects.firstNonNull(player.preferredHand, Hand.MAIN_HAND);
|
||||||
|
|
||||||
|
if (player.getMainHandStack().isEmpty()) {
|
||||||
|
matrices.push();
|
||||||
|
sender.invokeRenderArmHoldingItem(matrices, vertexConsumers, light, 1 - sender.getEquipProgress(Hand.MAIN_HAND, tickDelta), hand == Hand.MAIN_HAND ? swingProgress : 0, player.getMainArm());
|
||||||
|
matrices.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.getOffHandStack().isEmpty()) {
|
||||||
|
matrices.push();
|
||||||
|
sender.invokeRenderArmHoldingItem(matrices, vertexConsumers, light, 1 - sender.getEquipProgress(Hand.OFF_HAND, tickDelta), hand == Hand.OFF_HAND ? swingProgress : 0, player.getMainArm().getOpposite());
|
||||||
|
matrices.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ArmRenderer {
|
public interface ArmRenderer {
|
||||||
void invokeRenderArmHoldingItem(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, float equipProgress, float swingProgress, Arm arm);
|
void invokeRenderArmHoldingItem(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, float equipProgress, float swingProgress, Arm arm);
|
||||||
|
|
||||||
float getEquipProgress(float tickDelta);
|
float getEquipProgress(Hand hand, float tickDelta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.util.Arm;
|
import net.minecraft.util.Arm;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.math.*;
|
import net.minecraft.util.math.*;
|
||||||
|
|
||||||
public class HeldEntityFeatureRenderer<E extends LivingEntity> implements AccessoryFeatureRenderer.Feature<E> {
|
public class HeldEntityFeatureRenderer<E extends LivingEntity> implements AccessoryFeatureRenderer.Feature<E> {
|
||||||
|
@ -67,7 +68,7 @@ public class HeldEntityFeatureRenderer<E extends LivingEntity> implements Access
|
||||||
renderCarriedEntity(passenger.asEntity(), matrices, vertexConsumers, light, tickDelta);
|
renderCarriedEntity(passenger.asEntity(), matrices, vertexConsumers, light, tickDelta);
|
||||||
matrices.pop();
|
matrices.pop();
|
||||||
|
|
||||||
float equipProgress = 1 - sender.getEquipProgress(tickDelta);
|
float equipProgress = 1 - sender.getEquipProgress(Hand.MAIN_HAND, tickDelta);
|
||||||
|
|
||||||
matrices.push();
|
matrices.push();
|
||||||
sender.invokeRenderArmHoldingItem(matrices, vertexConsumers, light, equipProgress, swingProgress, Arm.LEFT);
|
sender.invokeRenderArmHoldingItem(matrices, vertexConsumers, light, equipProgress, swingProgress, Arm.LEFT);
|
||||||
|
|
|
@ -33,6 +33,7 @@ public class PlayerPoser {
|
||||||
|
|
||||||
public void applyPosing(MatrixStack matrices, PlayerEntity player, BipedEntityModel<?> model, Context context) {
|
public void applyPosing(MatrixStack matrices, PlayerEntity player, BipedEntityModel<?> model, Context context) {
|
||||||
Pony pony = Pony.of(player);
|
Pony pony = Pony.of(player);
|
||||||
|
float tickDelta = MinecraftClient.getInstance().getTickDelta();
|
||||||
float progress = pony.getAnimationProgress(MinecraftClient.getInstance().getTickDelta());
|
float progress = pony.getAnimationProgress(MinecraftClient.getInstance().getTickDelta());
|
||||||
AnimationInstance animation = pony.getAnimation();
|
AnimationInstance animation = pony.getAnimation();
|
||||||
Race ponyRace = MineLPDelegate.getInstance().getPlayerPonyRace(player);
|
Race ponyRace = MineLPDelegate.getInstance().getPlayerPonyRace(player);
|
||||||
|
@ -130,6 +131,51 @@ public class PlayerPoser {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case HANG: {
|
||||||
|
float saw = MathHelper.sin(player.limbAnimator.getPos());
|
||||||
|
|
||||||
|
float pitch = 0.8F * saw;
|
||||||
|
|
||||||
|
float basePitch = 3.25F;
|
||||||
|
|
||||||
|
if (context == Context.THIRD_PERSON) {
|
||||||
|
|
||||||
|
if (ponyRace.isEquine()) {
|
||||||
|
rearUp(matrices, model, 1);
|
||||||
|
model.head.pitch += 0.8F;
|
||||||
|
basePitch = 2.25F;
|
||||||
|
}
|
||||||
|
|
||||||
|
rotateArm(model.leftArm, basePitch - pitch, -0.3F, 0);
|
||||||
|
rotateArm(model.rightArm, basePitch + pitch, 0.3F, 0);
|
||||||
|
|
||||||
|
rotateArm(model.leftLeg, 0, 0.1F, 0);
|
||||||
|
rotateArm(model.rightLeg, 0, -0.1F, 0);
|
||||||
|
} else {
|
||||||
|
pitch *= 0.5F;
|
||||||
|
|
||||||
|
float x = ponyRace.isEquine() ? 9 : 10;
|
||||||
|
float y = ponyRace.isEquine() ? -3 : -1;
|
||||||
|
float z = ponyRace.isEquine() ? -8 : -6;
|
||||||
|
|
||||||
|
float cameraPitch = player.getPitch(tickDelta) * MathHelper.RADIANS_PER_DEGREE;
|
||||||
|
|
||||||
|
rotateArm(model.leftArm, 0, 0, -0.4F + pitch);
|
||||||
|
rotateArm(model.rightArm, 0, 0, 0.4F + pitch);
|
||||||
|
|
||||||
|
model.leftArm.pivotX += x;
|
||||||
|
model.leftArm.pivotY += y;
|
||||||
|
model.leftArm.pivotZ += z;
|
||||||
|
model.leftArm.roll -= cameraPitch;
|
||||||
|
|
||||||
|
|
||||||
|
model.rightArm.pivotX -= x;
|
||||||
|
model.rightArm.pivotY += y;
|
||||||
|
model.rightArm.pivotZ += z;
|
||||||
|
model.rightArm.roll += cameraPitch;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ARMS_UP: {
|
case ARMS_UP: {
|
||||||
float saw = AnimationUtil.seesaw(progress);
|
float saw = AnimationUtil.seesaw(progress);
|
||||||
|
|
||||||
|
@ -138,14 +184,14 @@ public class PlayerPoser {
|
||||||
|
|
||||||
if (ponyRace.isEquine()) {
|
if (ponyRace.isEquine()) {
|
||||||
rearUp(matrices, model, saw);
|
rearUp(matrices, model, saw);
|
||||||
pitch = saw * 2F;
|
|
||||||
model.head.pitch += saw * 0.5F;
|
model.head.pitch += saw * 0.5F;
|
||||||
|
pitch = saw * 2F;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (liftLeftArm) {
|
if (liftLeftArm) {
|
||||||
rotateArm(model.leftArm, pitch, -yaw, yaw);
|
rotateArm(model.leftArm, pitch, -yaw, yaw);
|
||||||
} else if (ponyRace.isEquine()) {
|
} else if (ponyRace.isEquine()) {
|
||||||
model.leftArm.pitch += saw / 4F;
|
model.leftArm.pitch -= saw / 4F;
|
||||||
model.leftArm.roll -= saw / 4F;
|
model.leftArm.roll -= saw / 4F;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,15 +210,25 @@ public class PlayerPoser {
|
||||||
float pitch = MathHelper.clamp(3F * saw, 1, 2);
|
float pitch = MathHelper.clamp(3F * saw, 1, 2);
|
||||||
float yaw = 0.5F * saw;
|
float yaw = 0.5F * saw;
|
||||||
|
|
||||||
|
if (context == Context.THIRD_PERSON) {
|
||||||
if (ponyRace.isEquine()) {
|
if (ponyRace.isEquine()) {
|
||||||
rearUp(matrices, model, saw);
|
rearUp(matrices, model, 1);
|
||||||
pitch = saw * 2F;
|
pitch = saw * 2F;
|
||||||
model.head.pitch += saw * 0.5F;
|
model.head.pitch += saw * 0.5F;
|
||||||
}
|
|
||||||
|
|
||||||
rotateArm(model.leftArm, pitch, -yaw, yaw / 2F);
|
rotateArm(model.leftArm, pitch, -yaw, yaw / 2F);
|
||||||
rotateArm(model.rightLeg, pitch / 2F, yaw, 0);
|
rotateArm(model.rightLeg, pitch / 2F, yaw, 0);
|
||||||
|
|
||||||
|
saw = AnimationUtil.seesaw(progress + 0.5F);
|
||||||
|
yaw = 0.5F * -saw;
|
||||||
|
|
||||||
|
rotateArm(model.rightArm, pitch, yaw, -yaw / 2F);
|
||||||
|
rotateArm(model.leftLeg, pitch / 2F, -yaw, 0);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
rotateArm(model.leftArm, pitch, -yaw, yaw / 2F);
|
||||||
|
rotateArm(model.rightLeg, pitch / 2F, yaw, 0);
|
||||||
|
|
||||||
saw = AnimationUtil.seesaw((progress + 0.5F) % 1);
|
saw = AnimationUtil.seesaw((progress + 0.5F) % 1);
|
||||||
|
|
||||||
pitch = MathHelper.clamp(3F * saw, 1, 2) * (ponyRace.isEquine() ? 2 : 1);
|
pitch = MathHelper.clamp(3F * saw, 1, 2) * (ponyRace.isEquine() ? 2 : 1);
|
||||||
|
@ -180,6 +236,29 @@ public class PlayerPoser {
|
||||||
|
|
||||||
rotateArm(model.rightArm, pitch, yaw, -yaw / 2F);
|
rotateArm(model.rightArm, pitch, yaw, -yaw / 2F);
|
||||||
rotateArm(model.leftLeg, pitch / 2F, -yaw, 0);
|
rotateArm(model.leftLeg, pitch / 2F, -yaw, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//saw = MathHelper.sin(progress * 2);
|
||||||
|
float x = ponyRace.isEquine() ? 9 : 0;
|
||||||
|
float y = ponyRace.isEquine() ? -3 : 0;
|
||||||
|
float z = ponyRace.isEquine() ? -8 : -2;
|
||||||
|
|
||||||
|
float cameraPitch = player.getPitch(tickDelta) * MathHelper.RADIANS_PER_DEGREE;
|
||||||
|
pitch = MathHelper.sin((progress * 2) * MathHelper.PI) * 0.6F;
|
||||||
|
|
||||||
|
rotateArm(model.leftArm, 0, 0, pitch);
|
||||||
|
rotateArm(model.rightArm, 0, 0, pitch);
|
||||||
|
|
||||||
|
model.leftArm.pivotX += x;
|
||||||
|
model.leftArm.pivotY += y;
|
||||||
|
model.leftArm.pivotZ += z;
|
||||||
|
model.leftArm.roll -= cameraPitch;
|
||||||
|
|
||||||
|
model.rightArm.pivotX -= x;
|
||||||
|
model.rightArm.pivotY += y;
|
||||||
|
model.rightArm.pivotZ += z;
|
||||||
|
model.rightArm.roll += cameraPitch;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -324,6 +403,10 @@ public class PlayerPoser {
|
||||||
public boolean canPlay(boolean isPony) {
|
public boolean canPlay(boolean isPony) {
|
||||||
return !isOf(Animation.NONE) && (recipient == Animation.Recipient.ANYONE || isPony == (recipient == Animation.Recipient.PONY));
|
return !isOf(Animation.NONE) && (recipient == Animation.Recipient.ANYONE || isPony == (recipient == Animation.Recipient.PONY));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean renderBothArms() {
|
||||||
|
return isOf(Animation.HANG) || isOf(Animation.CLIMB);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Animation implements CommandArgumentEnum<Animation> {
|
public enum Animation implements CommandArgumentEnum<Animation> {
|
||||||
|
@ -335,6 +418,7 @@ public class PlayerPoser {
|
||||||
WAVE_TWO(USounds.ENTITY_PLAYER_WHISTLE, 20),
|
WAVE_TWO(USounds.ENTITY_PLAYER_WHISTLE, 20),
|
||||||
KICK(USounds.ENTITY_PLAYER_KICK, 5),
|
KICK(USounds.ENTITY_PLAYER_KICK, 5),
|
||||||
CLIMB(20),
|
CLIMB(20),
|
||||||
|
HANG(20),
|
||||||
STOMP(5),
|
STOMP(5),
|
||||||
WIGGLE_NOSE(6),
|
WIGGLE_NOSE(6),
|
||||||
SPREAD_WINGS(6),
|
SPREAD_WINGS(6),
|
||||||
|
|
|
@ -146,10 +146,16 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAnimation(Animation animation, Animation.Recipient recipient) {
|
public void setAnimation(Animation animation, Animation.Recipient recipient) {
|
||||||
|
if (getAnimation().isOf(animation) && animationDuration > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
setAnimation(new AnimationInstance(animation, recipient), animation.getDuration());
|
setAnimation(new AnimationInstance(animation, recipient), animation.getDuration());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAnimation(Animation animation, Animation.Recipient recipient, int duration) {
|
public void setAnimation(Animation animation, Animation.Recipient recipient, int duration) {
|
||||||
|
if (getAnimation().isOf(animation) && animationDuration > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
setAnimation(new AnimationInstance(animation, recipient), duration);
|
setAnimation(new AnimationInstance(animation, recipient), duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,12 +426,10 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getAnimation().isOf(Animation.NONE) || (getAnimation().isOf(Animation.NONE) && canhangHere)) {
|
|
||||||
if (canhangHere) {
|
if (canhangHere) {
|
||||||
setAnimation(Animation.ARMS_UP, Recipient.HUMAN);
|
setAnimation(Animation.HANG, Recipient.ANYONE);
|
||||||
} else if (distanceClimbed > 1.5) {
|
} else if (distanceClimbed > 1.5) {
|
||||||
setAnimation(Animation.CLIMB, Recipient.HUMAN);
|
setAnimation(Animation.CLIMB, Recipient.ANYONE);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
distanceClimbed = 0;
|
distanceClimbed = 0;
|
||||||
|
@ -484,16 +488,21 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
||||||
private void updateAnimations() {
|
private void updateAnimations() {
|
||||||
|
|
||||||
if (distanceClimbed > 0
|
if (distanceClimbed > 0
|
||||||
&& ((animation.isOf(Animation.CLIMB) && entity.isSneaky()) || (animation.isOf(Animation.ARMS_UP) && isHanging()))
|
&& ((animation.isOf(Animation.CLIMB) && entity.isSneaky()) || animation.isOf(Animation.HANG))
|
||||||
&& entity.getClimbingPos().isPresent()
|
&& entity.getClimbingPos().isPresent()
|
||||||
&& entity.getVelocity().length() < 0.08F) {
|
&& entity.getVelocity().length() < 0.08F) {
|
||||||
if (animation.isOf(Animation.ARMS_UP)) {
|
if (animation.renderBothArms()) {
|
||||||
animationDuration = 2;
|
animationDuration = 2;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (animationDuration > 0 && --animationDuration <= 0) {
|
if (animationDuration > 0 && --animationDuration <= 0) {
|
||||||
|
|
||||||
|
if (animation.renderBothArms() && distanceClimbed > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setAnimation(AnimationInstance.NONE);
|
setAnimation(AnimationInstance.NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import net.minecraft.client.render.item.HeldItemRenderer;
|
||||||
import net.minecraft.client.render.item.HeldItemRenderer.HandRenderType;
|
import net.minecraft.client.render.item.HeldItemRenderer.HandRenderType;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.util.Arm;
|
import net.minecraft.util.Arm;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
@Mixin(HeldItemRenderer.class)
|
@Mixin(HeldItemRenderer.class)
|
||||||
|
@ -25,13 +26,21 @@ abstract class MixinHeldItemRenderer implements FirstPersonRendererOverrides.Arm
|
||||||
@Shadow
|
@Shadow
|
||||||
private float prevEquipProgressMainHand;
|
private float prevEquipProgressMainHand;
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
private float equipProgressOffHand;
|
||||||
|
@Shadow
|
||||||
|
private float prevEquipProgressOffHand;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Invoker("renderArmHoldingItem")
|
@Invoker("renderArmHoldingItem")
|
||||||
public abstract void invokeRenderArmHoldingItem(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, float equipProgress, float swingProgress, Arm arm);
|
public abstract void invokeRenderArmHoldingItem(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, float equipProgress, float swingProgress, Arm arm);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getEquipProgress(float tickDelta) {
|
public float getEquipProgress(Hand hand, float tickDelta) {
|
||||||
return MathHelper.lerp(tickDelta, prevEquipProgressMainHand, equipProgressMainHand);
|
return MathHelper.lerp(tickDelta,
|
||||||
|
hand == Hand.MAIN_HAND ? prevEquipProgressMainHand : prevEquipProgressOffHand,
|
||||||
|
hand == Hand.MAIN_HAND ? equipProgressMainHand : equipProgressOffHand
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(
|
@Inject(
|
||||||
|
|
Loading…
Reference in a new issue