Files
TiedUp-/src/main/java/com/tiedup/remake/rig/patch/ClientPlayerPatch.java
notevil f0d8408384 WIP: stub ClientConfig + gameasset registries, strip Meshes mobs
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.
2026-04-22 00:53:42 +02:00

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;
}
}