Nouveaux stubs core :
- TiedUpAnimationConfig — remplace yesman.epicfight.config.ClientConfig.
Flags animation/rendu, no-op pour combat.
- TiedUpRigRegistry — remplace gameasset.Animations.EMPTY_ANIMATION +
gameasset.Armatures.ArmatureContructor.
Fichiers forkés additionnels (dépendances transitives découvertes) :
- anim/types/DirectStaticAnimation.java (EMPTY_ANIMATION est un DirectStaticAnimation)
- event/InitAnimatorEvent.java (postInit() forge event)
- event/EntityPatchRegistryEvent.java (mod bus event pour register patches)
Strip combat :
- Meshes.java : retiré les 11 mob meshes (CreeperMesh, DragonMesh, VexMesh,
WitherMesh, etc.) + armor + particle + cape. Garde BIPED
et ALEX / BIPED_OLD_TEX / BIPED_OUTLAYER (variants joueur).
- Animator.playDeathAnimation : Animations.BIPED_DEATH (ARR asset) →
EMPTY_ANIMATION fallback.
- AnimationManager.apply : Armatures.reload() stripped (no-op, à rebrancher
Phase 2 sur TiedUpArmatures).
- ClientPlayerPatch.entityPairing : body entier strippé (combat skills
Technician/Adrenaline/Emergency Escape).
sed global : ClientConfig.* → TiedUpAnimationConfig.*
sed global : Animations.EMPTY_ANIMATION → TiedUpRigRegistry.EMPTY_ANIMATION
sed global : Armatures.ArmatureContructor → TiedUpRigRegistry.ArmatureContructor
Résidus yesman.epicfight : 86 → 74 (-12)
Reste : physics (16) + network (13) + world combat (10) + particle (3) +
collider (2) + client misc (2) + skill (2). Tous combat-entangled,
demandent strip méthode par méthode.
480 lines
19 KiB
Java
480 lines
19 KiB
Java
/*
|
|
* Derived from Epic Fight (https://github.com/Epic-Fight/epicfight)
|
|
* by the Epic Fight Team, licensed under GPLv3.
|
|
* Modifications © 2026 TiedUp! Remake Contributors, distributed under GPLv3.
|
|
*/
|
|
|
|
package com.tiedup.remake.rig.patch;
|
|
|
|
import java.util.Optional;
|
|
|
|
import org.joml.Vector4f;
|
|
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.player.AbstractClientPlayer;
|
|
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.world.InteractionHand;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.entity.PlayerRideableJumping;
|
|
import net.minecraft.world.item.Item;
|
|
import net.minecraft.world.item.Items;
|
|
import net.minecraft.world.item.UseAnim;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import net.minecraftforge.common.MinecraftForge;
|
|
import net.minecraftforge.event.entity.EntityJoinLevelEvent;
|
|
import net.minecraftforge.event.entity.living.LivingEvent;
|
|
import com.tiedup.remake.rig.anim.Animator;
|
|
import com.tiedup.remake.rig.armature.JointTransform;
|
|
import com.tiedup.remake.rig.anim.LivingMotion;
|
|
import com.tiedup.remake.rig.anim.LivingMotions;
|
|
import com.tiedup.remake.rig.anim.Pose;
|
|
import com.tiedup.remake.rig.anim.property.AnimationProperty.StaticAnimationProperty;
|
|
import com.tiedup.remake.rig.anim.types.ActionAnimation;
|
|
import com.tiedup.remake.rig.anim.types.DynamicAnimation;
|
|
import com.tiedup.remake.rig.anim.client.ClientAnimator;
|
|
import com.tiedup.remake.rig.anim.client.Layer;
|
|
import com.tiedup.remake.rig.event.RenderEpicFightPlayerEvent;
|
|
import com.tiedup.remake.rig.event.UpdatePlayerMotionEvent;
|
|
import yesman.epicfight.client.online.EpicSkins;
|
|
import com.tiedup.remake.rig.cloth.ClothSimulatable;
|
|
import com.tiedup.remake.rig.cloth.ClothSimulator;
|
|
import yesman.epicfight.api.physics.PhysicsSimulator;
|
|
import yesman.epicfight.api.physics.SimulationTypes;
|
|
import com.tiedup.remake.rig.util.EntitySnapshot;
|
|
import com.tiedup.remake.rig.math.MathUtils;
|
|
import com.tiedup.remake.rig.math.OpenMatrix4f;
|
|
import com.tiedup.remake.rig.math.Vec3f;
|
|
import com.tiedup.remake.rig.TiedUpAnimationConfig;
|
|
import yesman.epicfight.gameasset.EpicFightSounds;
|
|
import yesman.epicfight.network.EntityPairingPacketTypes;
|
|
import yesman.epicfight.network.server.SPEntityPairingPacket;
|
|
import yesman.epicfight.particle.EpicFightParticles;
|
|
import com.tiedup.remake.rig.patch.EntityDecorations;
|
|
import com.tiedup.remake.rig.patch.EntityDecorations.RenderAttributeModifier;
|
|
import com.tiedup.remake.rig.patch.PlayerPatch;
|
|
import com.tiedup.remake.rig.patch.item.CapabilityItem;
|
|
import yesman.epicfight.world.entity.eventlistener.PlayerEventListener.EventType;
|
|
|
|
public class AbstractClientPlayerPatch<T extends AbstractClientPlayer> extends PlayerPatch<T> implements ClothSimulatable {
|
|
private Item prevHeldItem;
|
|
private Item prevHeldItemOffHand;
|
|
protected EpicSkins epicSkinsInformation;
|
|
|
|
@Override
|
|
public void onJoinWorld(T entity, EntityJoinLevelEvent event) {
|
|
super.onJoinWorld(entity, event);
|
|
|
|
this.prevHeldItem = Items.AIR;
|
|
this.prevHeldItemOffHand = Items.AIR;
|
|
|
|
EpicSkins.initEpicSkins(this);
|
|
}
|
|
|
|
@Override
|
|
public void updateMotion(boolean considerInaction) {
|
|
if (this.original.getHealth() <= 0.0F) {
|
|
currentLivingMotion = LivingMotions.DEATH;
|
|
} else if (!this.state.updateLivingMotion() && considerInaction) {
|
|
currentLivingMotion = LivingMotions.INACTION;
|
|
} else {
|
|
if (original.isFallFlying() || original.isAutoSpinAttack()) {
|
|
currentLivingMotion = LivingMotions.FLY;
|
|
} else if (original.getVehicle() != null) {
|
|
if (original.getVehicle() instanceof PlayerRideableJumping)
|
|
currentLivingMotion = LivingMotions.MOUNT;
|
|
else
|
|
currentLivingMotion = LivingMotions.SIT;
|
|
} else if (original.isVisuallySwimming()) {
|
|
currentLivingMotion = LivingMotions.SWIM;
|
|
} else if (original.isSleeping()) {
|
|
currentLivingMotion = LivingMotions.SLEEP;
|
|
} else if (!original.onGround() && original.onClimbable()) {
|
|
currentLivingMotion = LivingMotions.CLIMB;
|
|
} else if (!original.getAbilities().flying) {
|
|
ClientAnimator animator = this.getClientAnimator();
|
|
|
|
if (original.isUnderWater() && (original.getY() - this.yo) < -0.005)
|
|
currentLivingMotion = LivingMotions.FLOAT;
|
|
else if (original.getY() - this.yo < -0.4F || this.isAirborneState())
|
|
currentLivingMotion = LivingMotions.FALL;
|
|
else if (this.isMoving()) {
|
|
if (original.isCrouching())
|
|
currentLivingMotion = LivingMotions.SNEAK;
|
|
else if (original.isSprinting())
|
|
currentLivingMotion = LivingMotions.RUN;
|
|
else
|
|
currentLivingMotion = LivingMotions.WALK;
|
|
|
|
animator.baseLayer.animationPlayer.setReversed(this.dz < 0);
|
|
|
|
} else {
|
|
animator.baseLayer.animationPlayer.setReversed(false);
|
|
|
|
if (original.isCrouching())
|
|
currentLivingMotion = LivingMotions.KNEEL;
|
|
else
|
|
currentLivingMotion = LivingMotions.IDLE;
|
|
}
|
|
} else {
|
|
if (this.isMoving())
|
|
currentLivingMotion = LivingMotions.CREATIVE_FLY;
|
|
else
|
|
currentLivingMotion = LivingMotions.CREATIVE_IDLE;
|
|
}
|
|
}
|
|
|
|
UpdatePlayerMotionEvent.BaseLayer baseLayerEvent = new UpdatePlayerMotionEvent.BaseLayer(this, this.currentLivingMotion, !this.state.updateLivingMotion() && considerInaction);
|
|
this.eventListeners.triggerEvents(EventType.UPDATE_BASE_LIVING_MOTION_EVENT, baseLayerEvent);
|
|
MinecraftForge.EVENT_BUS.post(baseLayerEvent);
|
|
|
|
this.currentLivingMotion = baseLayerEvent.getMotion();
|
|
|
|
if (!this.state.updateLivingMotion() && considerInaction) {
|
|
this.currentCompositeMotion = LivingMotions.NONE;
|
|
} else {
|
|
CapabilityItem mainhandItemCap = this.getHoldingItemCapability(InteractionHand.MAIN_HAND);
|
|
CapabilityItem offhandItemCap = this.getHoldingItemCapability(InteractionHand.OFF_HAND);
|
|
LivingMotion customLivingMotion = mainhandItemCap.getLivingMotion(this, InteractionHand.MAIN_HAND);
|
|
|
|
if (customLivingMotion == null) customLivingMotion = offhandItemCap.getLivingMotion(this, InteractionHand.OFF_HAND);
|
|
|
|
// When item capabilities has custom living motion
|
|
if (customLivingMotion != null)
|
|
currentCompositeMotion = customLivingMotion;
|
|
else if (this.original.isUsingItem()) {
|
|
UseAnim useAnim = this.original.getUseItem().getUseAnimation();
|
|
if (useAnim == UseAnim.BLOCK)
|
|
currentCompositeMotion = LivingMotions.BLOCK_SHIELD;
|
|
else if (useAnim == UseAnim.CROSSBOW)
|
|
currentCompositeMotion = LivingMotions.RELOAD;
|
|
else if (useAnim == UseAnim.DRINK)
|
|
currentCompositeMotion = LivingMotions.DRINK;
|
|
else if (useAnim == UseAnim.EAT)
|
|
currentCompositeMotion = LivingMotions.EAT;
|
|
else if (useAnim == UseAnim.SPYGLASS)
|
|
currentCompositeMotion = LivingMotions.SPECTATE;
|
|
else
|
|
currentCompositeMotion = currentLivingMotion;
|
|
} else {
|
|
if (this.getClientAnimator().getCompositeLayer(Layer.Priority.MIDDLE).animationPlayer.getRealAnimation().get().isReboundAnimation())
|
|
currentCompositeMotion = LivingMotions.SHOT;
|
|
else if (this.original.swinging && this.original.getSleepingPos().isEmpty())
|
|
currentCompositeMotion = LivingMotions.DIGGING;
|
|
else
|
|
currentCompositeMotion = currentLivingMotion;
|
|
}
|
|
|
|
UpdatePlayerMotionEvent.CompositeLayer compositeLayerEvent = new UpdatePlayerMotionEvent.CompositeLayer(this, this.currentCompositeMotion);
|
|
this.eventListeners.triggerEvents(EventType.UPDATE_COMPOSITE_LIVING_MOTION_EVENT, compositeLayerEvent);
|
|
MinecraftForge.EVENT_BUS.post(compositeLayerEvent);
|
|
|
|
this.currentCompositeMotion = compositeLayerEvent.getMotion();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onOldPosUpdate() {
|
|
this.modelYRotO2 = this.modelYRotO;
|
|
this.xPosO2 = (float)this.original.xOld;
|
|
this.yPosO2 = (float)this.original.yOld;
|
|
this.zPosO2 = (float)this.original.zOld;
|
|
}
|
|
|
|
@Override
|
|
protected void clientTick(LivingEvent.LivingTickEvent event) {
|
|
this.xCloakO2 = this.original.xCloakO;
|
|
this.yCloakO2 = this.original.yCloakO;
|
|
this.zCloakO2 = this.original.zCloakO;
|
|
|
|
super.clientTick(event);
|
|
|
|
if (!this.getEntityState().updateLivingMotion()) {
|
|
this.original.yBodyRot = this.original.yHeadRot;
|
|
}
|
|
|
|
boolean isMainHandChanged = this.prevHeldItem != this.original.getInventory().getSelected().getItem();
|
|
boolean isOffHandChanged = this.prevHeldItemOffHand != this.original.getInventory().offhand.get(0).getItem();
|
|
|
|
if (isMainHandChanged || isOffHandChanged) {
|
|
this.updateHeldItem(this.getHoldingItemCapability(InteractionHand.MAIN_HAND), this.getHoldingItemCapability(InteractionHand.OFF_HAND));
|
|
|
|
if (isMainHandChanged) {
|
|
this.prevHeldItem = this.original.getInventory().getSelected().getItem();
|
|
}
|
|
|
|
if (isOffHandChanged) {
|
|
this.prevHeldItemOffHand = this.original.getInventory().offhand.get(0).getItem();
|
|
}
|
|
}
|
|
|
|
/** {@link LivingDeathEvent} never fired for client players **/
|
|
if (this.original.deathTime == 1) {
|
|
this.getClientAnimator().playDeathAnimation();
|
|
}
|
|
|
|
this.clothSimulator.tick(this);
|
|
}
|
|
|
|
protected boolean isMoving() {
|
|
return Math.abs(this.dx) > 0.01F || Math.abs(this.dz) > 0.01F;
|
|
}
|
|
|
|
public void updateHeldItem(CapabilityItem mainHandCap, CapabilityItem offHandCap) {
|
|
this.cancelItemUse();
|
|
|
|
this.getClientAnimator().iterAllLayers((layer) -> {
|
|
if (layer.isOff()) {
|
|
return;
|
|
}
|
|
|
|
layer.animationPlayer.getRealAnimation().get().getProperty(StaticAnimationProperty.ON_ITEM_CHANGE_EVENT).ifPresent((event) -> {
|
|
event.params(mainHandCap, offHandCap);
|
|
event.execute(this, layer.animationPlayer.getRealAnimation(), layer.animationPlayer.getPrevElapsedTime(), layer.animationPlayer.getElapsedTime());
|
|
});
|
|
});
|
|
}
|
|
|
|
// RIG : entityPairing() EF = hook combat skills (Technician, Adrenaline,
|
|
// Emergency Escape). Strippé intégralement — ces skills n'existent pas
|
|
// en TiedUp. Le super.entityPairing() de base reste disponible si jamais
|
|
// une extension TiedUp veut hooker des paires custom.
|
|
|
|
@Override
|
|
public boolean overrideRender() {
|
|
RenderEpicFightPlayerEvent renderepicfightplayerevent = new RenderEpicFightPlayerEvent(this, !TiedUpAnimationConfig.enableOriginalModel || this.isEpicFightMode());
|
|
MinecraftForge.EVENT_BUS.post(renderepicfightplayerevent);
|
|
return renderepicfightplayerevent.getShouldRender();
|
|
}
|
|
|
|
@Override
|
|
public boolean shouldMoveOnCurrentSide(ActionAnimation actionAnimation) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void poseTick(DynamicAnimation animation, Pose pose, float elapsedTime, float partialTick) {
|
|
if (pose.hasTransform("Head") && this.armature.hasJoint("Head")) {
|
|
if (animation.doesHeadRotFollowEntityHead()) {
|
|
float headRelativeRot = Mth.rotLerp(partialTick, Mth.wrapDegrees(this.modelYRotO - this.original.yHeadRotO), Mth.wrapDegrees(this.modelYRot - this.original.yHeadRot));
|
|
OpenMatrix4f headTransform = this.armature.getBoundTransformFor(pose, this.armature.searchJointByName("Head"));
|
|
OpenMatrix4f toOriginalRotation = headTransform.removeScale().removeTranslation().invert();
|
|
Vec3f xAxis = OpenMatrix4f.transform3v(toOriginalRotation, Vec3f.X_AXIS, null);
|
|
Vec3f yAxis = OpenMatrix4f.transform3v(toOriginalRotation, Vec3f.Y_AXIS, null);
|
|
OpenMatrix4f headRotation = OpenMatrix4f.createRotatorDeg(headRelativeRot, yAxis).rotateDeg(-Mth.rotLerp(partialTick, this.original.xRotO, this.original.getXRot()), xAxis);
|
|
pose.orElseEmpty("Head").frontResult(JointTransform.fromMatrix(headRotation), OpenMatrix4f::mul);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public OpenMatrix4f getModelMatrix(float partialTick) {
|
|
if (this.original.isAutoSpinAttack()) {
|
|
OpenMatrix4f mat = MathUtils.getModelMatrixIntegral(0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0, 0, 0, 0, partialTick, PLAYER_SCALE, PLAYER_SCALE, PLAYER_SCALE);
|
|
float yRot = MathUtils.lerpBetween(this.original.yRotO, this.original.getYRot(), partialTick);
|
|
float xRot = MathUtils.lerpBetween(this.original.xRotO, this.original.getXRot(), partialTick);
|
|
|
|
mat.rotateDeg(-yRot, Vec3f.Y_AXIS)
|
|
.rotateDeg(-xRot, Vec3f.X_AXIS)
|
|
.rotateDeg((this.original.tickCount + partialTick) * -55.0F, Vec3f.Z_AXIS)
|
|
.translate(0F, -0.39F, 0F);
|
|
|
|
return mat;
|
|
} else if (this.original.isFallFlying()) {
|
|
OpenMatrix4f mat = MathUtils.getModelMatrixIntegral(0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0, 0, 0, 0, partialTick, PLAYER_SCALE, PLAYER_SCALE, PLAYER_SCALE);
|
|
float f1 = (float)this.original.getFallFlyingTicks() + partialTick;
|
|
float f2 = Mth.clamp(f1 * f1 / 100.0F, 0.0F, 1.0F);
|
|
|
|
mat.rotateDeg(-Mth.rotLerp(partialTick, this.original.yBodyRotO, this.original.yBodyRot), Vec3f.Y_AXIS).rotateDeg(f2 * (-this.original.getXRot()), Vec3f.X_AXIS);
|
|
|
|
Vec3 vec3d = this.original.getViewVector(partialTick);
|
|
Vec3 vec3d1 = this.original.getDeltaMovementLerped(partialTick);
|
|
double d0 = vec3d1.horizontalDistanceSqr();
|
|
double d1 = vec3d.horizontalDistanceSqr();
|
|
|
|
if (d0 > 0.0D && d1 > 0.0D) {
|
|
double d2 = (vec3d1.x * vec3d.x + vec3d1.z * vec3d.z) / (Math.sqrt(d0) * Math.sqrt(d1));
|
|
double d3 = vec3d1.x * vec3d.z - vec3d1.z * vec3d.x;
|
|
mat.rotate((float)-((Math.signum(d3) * Math.acos(d2))), Vec3f.Z_AXIS);
|
|
}
|
|
|
|
return mat;
|
|
|
|
} else if (this.original.isSleeping()) {
|
|
BlockState blockstate = this.original.getFeetBlockState();
|
|
float yRot = 0.0F;
|
|
|
|
if (blockstate.isBed(this.original.level(), this.original.getSleepingPos().orElse(null), this.original)) {
|
|
if (blockstate.hasProperty(BlockStateProperties.HORIZONTAL_FACING)) {
|
|
switch(blockstate.getValue(BlockStateProperties.HORIZONTAL_FACING)) {
|
|
case EAST:
|
|
yRot = 90.0F;
|
|
break;
|
|
case WEST:
|
|
yRot = -90.0F;
|
|
break;
|
|
case SOUTH:
|
|
yRot = 180.0F;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return MathUtils.getModelMatrixIntegral(0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, yRot, yRot, 0, PLAYER_SCALE, PLAYER_SCALE, PLAYER_SCALE);
|
|
} else {
|
|
float yRotO;
|
|
float yRot;
|
|
float xRotO = 0;
|
|
float xRot = 0;
|
|
|
|
if (this.original.getVehicle() instanceof LivingEntity ridingEntity) {
|
|
yRotO = ridingEntity.yBodyRotO;
|
|
yRot = ridingEntity.yBodyRot;
|
|
} else {
|
|
yRotO = this.modelYRotO;
|
|
yRot = this.modelYRot;
|
|
}
|
|
|
|
if (!this.getEntityState().inaction() && this.original.getPose() == net.minecraft.world.entity.Pose.SWIMMING) {
|
|
float f = this.original.getSwimAmount(partialTick);
|
|
float f3 = this.original.isInWater() ? this.original.getXRot() : 0;
|
|
float f4 = Mth.lerp(f, 0.0F, f3);
|
|
xRotO = f4;
|
|
xRot = f4;
|
|
}
|
|
|
|
return MathUtils.getModelMatrixIntegral(0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, xRotO, xRot, yRotO, yRot, partialTick, PLAYER_SCALE, PLAYER_SCALE, PLAYER_SCALE);
|
|
}
|
|
}
|
|
|
|
public void setEpicSkinsInformation(EpicSkins epicSkinsInformation) {
|
|
this.epicSkinsInformation = epicSkinsInformation;
|
|
}
|
|
|
|
public EpicSkins getEpicSkinsInformation() {
|
|
return this.epicSkinsInformation;
|
|
}
|
|
|
|
public boolean isEpicSkinsLoaded() {
|
|
return this.epicSkinsInformation != null;
|
|
}
|
|
|
|
@Override
|
|
public EntitySnapshot<?> captureEntitySnapshot() {
|
|
return EntitySnapshot.capturePlayer(this);
|
|
}
|
|
|
|
private final ClothSimulator clothSimulator = new ClothSimulator();
|
|
public float modelYRotO2;
|
|
public double xPosO2;
|
|
public double yPosO2;
|
|
public double zPosO2;
|
|
public double xCloakO2;
|
|
public double yCloakO2;
|
|
public double zCloakO2;
|
|
|
|
@SuppressWarnings("unchecked")
|
|
@Override
|
|
public <SIM extends PhysicsSimulator<?, ?, ?, ?, ?>> Optional<SIM> getSimulator(SimulationTypes<?, ?, ?, ?, ?, SIM> simulationType) {
|
|
if (simulationType == SimulationTypes.CLOTH) {
|
|
return Optional.of((SIM)this.clothSimulator);
|
|
}
|
|
|
|
return Optional.empty();
|
|
}
|
|
|
|
@Override
|
|
public ClothSimulator getClothSimulator() {
|
|
return this.clothSimulator;
|
|
}
|
|
|
|
@Override
|
|
public Vec3 getAccurateCloakLocation(float partialFrame) {
|
|
if (partialFrame < 0.0F) {
|
|
partialFrame = 1.0F - partialFrame;
|
|
|
|
double x = Mth.lerp((double)partialFrame, this.xCloakO2, this.original.xCloakO) - Mth.lerp((double)partialFrame, this.xPosO2, this.original.xo);
|
|
double y = Mth.lerp((double)partialFrame, this.yCloakO2, this.original.yCloakO) - Mth.lerp((double)partialFrame, this.yPosO2, this.original.yo);
|
|
double z = Mth.lerp((double)partialFrame, this.zCloakO2, this.original.zCloakO) - Mth.lerp((double)partialFrame, this.zPosO2, this.original.zo);
|
|
|
|
return new Vec3(x, y, z);
|
|
} else {
|
|
double x = Mth.lerp((double)partialFrame, this.original.xCloakO, this.original.xCloak) - Mth.lerp((double)partialFrame, this.original.xo, this.original.getX());
|
|
double y = Mth.lerp((double)partialFrame, this.original.yCloakO, this.original.yCloak) - Mth.lerp((double)partialFrame, this.original.yo, this.original.getY());
|
|
double z = Mth.lerp((double)partialFrame, this.original.zCloakO, this.original.zCloak) - Mth.lerp((double)partialFrame, this.original.zo, this.original.getZ());
|
|
|
|
return new Vec3(x, y, z);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Vec3 getAccuratePartialLocation(float partialFrame) {
|
|
if (partialFrame < 0.0F) {
|
|
partialFrame = 1.0F + partialFrame;
|
|
|
|
double x = Mth.lerp((double)partialFrame, this.xPosO2, this.original.xOld);
|
|
double y = Mth.lerp((double)partialFrame, this.yPosO2, this.original.yOld);
|
|
double z = Mth.lerp((double)partialFrame, this.zPosO2, this.original.zOld);
|
|
|
|
return new Vec3(x, y, z);
|
|
} else {
|
|
double x = Mth.lerp((double)partialFrame, this.original.xOld, this.original.getX());
|
|
double y = Mth.lerp((double)partialFrame, this.original.yOld, this.original.getY());
|
|
double z = Mth.lerp((double)partialFrame, this.original.zOld, this.original.getZ());
|
|
|
|
return new Vec3(x, y, z);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Vec3 getObjectVelocity() {
|
|
return new Vec3(this.original.getX() - this.original.xOld, this.original.getY() - this.original.yOld, this.original.getZ() - this.original.zOld);
|
|
}
|
|
|
|
@Override
|
|
public float getAccurateYRot(float partialFrame) {
|
|
if (partialFrame < 0.0F) {
|
|
partialFrame = 1.0F + partialFrame;
|
|
|
|
return Mth.rotLerp(partialFrame, this.modelYRotO2, this.getYRotO());
|
|
} else {
|
|
return Mth.rotLerp(partialFrame, this.getYRotO(), this.getYRot());
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public float getYRotDelta(float partialFrame) {
|
|
if (partialFrame < 0.0F) {
|
|
partialFrame = 1.0F + partialFrame;
|
|
|
|
return Mth.rotLerp(partialFrame, this.modelYRotO2, this.getYRotO()) - this.modelYRotO2;
|
|
} else {
|
|
return Mth.rotLerp(partialFrame, this.getYRotO(), this.getYRot()) - this.getYRotO();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean invalid() {
|
|
return this.original.isRemoved();
|
|
}
|
|
|
|
@Override
|
|
public float getScale() {
|
|
return PLAYER_SCALE;
|
|
}
|
|
|
|
@Override
|
|
public Animator getSimulatableAnimator() {
|
|
return this.animator;
|
|
}
|
|
|
|
@Override
|
|
public float getGravity() {
|
|
return this.getOriginal().isUnderWater() ? 0.98F : 9.8F;
|
|
}
|
|
}
|