From 79fc470aa034922abdd8e7d9c9f2e10f40067f06 Mon Sep 17 00:00:00 2001 From: notevil Date: Wed, 22 Apr 2026 22:12:44 +0200 Subject: [PATCH] =?UTF-8?q?Phase=202.4=20:=20=C3=A9toffer=20PlayerPatch=20?= =?UTF-8?q?stubs=20+=20biped=20armature=20proc=C3=A9durale?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PlayerPatch : getArmature→TiedUpArmatures.BIPED, overrideRender→true, getModelMatrix avec PLAYER_SCALE=15/16, initAnimator bind IDLE→EMPTY. ServerPlayerPatch : ré-override overrideRender→false (le serveur ne rend pas). ClientPlayerPatch : stub isFirstPersonHidden() pour Phase 3 (V3-REW-01). LocalPlayerPatch : override render→false si on est soi-même en first-person (laisse rendre les bras vanilla), true sinon. TiedUpArmatures.BIPED : HumanoidArmature procédurale 20 joints identity (Root → Thigh/Leg/Knee_R/L, Torso → Chest → Head + Shoulder/Arm/Elbow/ Hand/Tool_R/L). Phase 2.7 remplacera par JSON Blender-authored. Fixe P2-RISK-01 (InitAnimatorEvent listeners NPE si getArmature()=null). Tests : 11 bridge tests GREEN, full suite GREEN, compile clean. --- .../tiedup/remake/rig/TiedUpArmatures.java | 193 ++++++++++++++++++ .../remake/rig/patch/ClientPlayerPatch.java | 69 ++++--- .../remake/rig/patch/LocalPlayerPatch.java | 56 ++++- .../tiedup/remake/rig/patch/PlayerPatch.java | 147 ++++++++++++- .../remake/rig/patch/ServerPlayerPatch.java | 64 +++--- 5 files changed, 450 insertions(+), 79 deletions(-) create mode 100644 src/main/java/com/tiedup/remake/rig/TiedUpArmatures.java diff --git a/src/main/java/com/tiedup/remake/rig/TiedUpArmatures.java b/src/main/java/com/tiedup/remake/rig/TiedUpArmatures.java new file mode 100644 index 0000000..c0f7d34 --- /dev/null +++ b/src/main/java/com/tiedup/remake/rig/TiedUpArmatures.java @@ -0,0 +1,193 @@ +/* + * 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; + +import java.util.LinkedHashMap; +import java.util.Map; + +import net.minecraft.resources.ResourceLocation; + +import com.tiedup.remake.rig.armature.HumanoidArmature; +import com.tiedup.remake.rig.armature.Joint; +import com.tiedup.remake.rig.asset.AssetAccessor; +import com.tiedup.remake.rig.math.OpenMatrix4f; + +/** + * Registry des armatures TiedUp exposé via {@link AssetAccessor} constants. + * + *

Phase 2.4 — version procédurale

+ * + *

Cette classe construit le biped TiedUp from scratch en Java + * (hiérarchie + offsets identity). Suffisant pour débloquer le rendering RIG + * Phase 2.4 : les joints existent dans le map, {@code searchJointByName} + * fonctionne, le GLB → SkinnedMesh bridge a un mapping valide, etc.

+ * + *

Phase 2.7 remplacera par un JSON Blender-authored hot-reloadable. + * Pour l'instant, les joints sont tous à l'identité (offset/rotation nuls). + * Visuellement ça donnera un biped "effondré" sur le point d'origine si on + * rend sans animation — c'est acceptable car :

+ * + * + *

Hiérarchie biped EF (20 joints)

+ * + *
+ *   Root
+ *   ├─ Thigh_R ── Leg_R ── Knee_R
+ *   ├─ Thigh_L ── Leg_L ── Knee_L
+ *   └─ Torso
+ *      └─ Chest
+ *         ├─ Head
+ *         ├─ Shoulder_R ── Arm_R ── Elbow_R ── Hand_R ── Tool_R
+ *         └─ Shoulder_L ── Arm_L ── Elbow_L ── Hand_L ── Tool_L
+ * 
+ * + *

Noms conservés verbatim EF (pas renommés en TiedUp style) car :

+ * + */ +public final class TiedUpArmatures { + + private TiedUpArmatures() {} + + /** ResourceLocation registry pour l'accessor (même path que EF pour cohérence doc). */ + private static final ResourceLocation BIPED_REGISTRY_NAME = + ResourceLocation.fromNamespaceAndPath(TiedUpRigConstants.MODID, "armature/biped"); + + /** + * Singleton biped — chargé à la première ref (init order : + * {@link TiedUpRigConstants} → chaînes d'ids → ici via + * {@link com.tiedup.remake.rig.patch.PlayerPatch#getArmature()}). + * + *

Si construit plus tôt (ex. static init combat-lourd avant FMLCommonSetup) + * risquerait de toucher des classes client — garder cet accès lazy si les + * call sites évoluent.

+ */ + private static HumanoidArmature BIPED_INSTANCE; + + /** + * AssetAccessor biped biped TiedUp. Construit à la première lecture de + * {@link AssetAccessor#get()}. + * + *

Utilisé par {@link com.tiedup.remake.rig.patch.PlayerPatch#getArmature()} + * et par les futurs {@code StaticAnimation(… , BIPED)} Phase 2.7+.

+ */ + public static final AssetAccessor BIPED = new AssetAccessor<>() { + @Override + public HumanoidArmature get() { + if (BIPED_INSTANCE == null) { + BIPED_INSTANCE = buildBiped(); + } + return BIPED_INSTANCE; + } + + @Override + public ResourceLocation registryName() { + return BIPED_REGISTRY_NAME; + } + + @Override + public boolean inRegistry() { + // Pas dans un JsonAssetLoader registry tant que Phase 2.7 n'a pas + // posé le biped.json. Une fois fait, ce flag repassera à true via + // un nouveau registry layer. + return false; + } + }; + + /** + * Build procédural de la hiérarchie biped EF. 20 joints, IDs 0..19 dans + * l'ordre d'insertion (important pour {@link Joint#getId()} stabilité + * inter-runs). + * + *

Toutes les transforms sont identity — Phase 2.7 remplacera par les + * offsets Blender mesurés (cf. doc header).

+ */ + private static HumanoidArmature buildBiped() { + // Tous les joints (ID == ordre d'insertion dans la map). + // On utilise LinkedHashMap pour garantir l'ordre d'itération stable + // (OpenMatrix4f.allocateMatrixArray dimensionne sur jointCount). + Map joints = new LinkedHashMap<>(20); + + // Pattern EF : tous les joints démarrent avec une localTransform identity. + // bakeOriginMatrices() calcule ensuite les toOrigin relatives à la + // hiérarchie parent→enfant. + Joint root = joint(joints, "Root", 0); + + // Jambes + Joint thighR = joint(joints, "Thigh_R", 1); + Joint legR = joint(joints, "Leg_R", 2); + Joint kneeR = joint(joints, "Knee_R", 3); + Joint thighL = joint(joints, "Thigh_L", 4); + Joint legL = joint(joints, "Leg_L", 5); + Joint kneeL = joint(joints, "Knee_L", 6); + + // Tronc + Joint torso = joint(joints, "Torso", 7); + Joint chest = joint(joints, "Chest", 8); + Joint head = joint(joints, "Head", 9); + + // Bras droit + Joint shoulderR = joint(joints, "Shoulder_R", 10); + Joint armR = joint(joints, "Arm_R", 11); + Joint elbowR = joint(joints, "Elbow_R", 12); + Joint handR = joint(joints, "Hand_R", 13); + Joint toolR = joint(joints, "Tool_R", 14); + + // Bras gauche + Joint shoulderL = joint(joints, "Shoulder_L", 15); + Joint armL = joint(joints, "Arm_L", 16); + Joint elbowL = joint(joints, "Elbow_L", 17); + Joint handL = joint(joints, "Hand_L", 18); + Joint toolL = joint(joints, "Tool_L", 19); + + // Hiérarchie. addSubJoints est idempotent (skip si déjà présent) — safe + // de le réappeler, utile si on étend plus tard. + root.addSubJoints(thighR, thighL, torso); + thighR.addSubJoints(legR); + legR.addSubJoints(kneeR); + thighL.addSubJoints(legL); + legL.addSubJoints(kneeL); + + torso.addSubJoints(chest); + chest.addSubJoints(head, shoulderR, shoulderL); + + shoulderR.addSubJoints(armR); + armR.addSubJoints(elbowR); + elbowR.addSubJoints(handR); + handR.addSubJoints(toolR); + + shoulderL.addSubJoints(armL); + armL.addSubJoints(elbowL); + elbowL.addSubJoints(handL); + handL.addSubJoints(toolL); + + HumanoidArmature arm = new HumanoidArmature("biped", joints.size(), root, joints); + + // Calcule les toOrigin relatifs — obligatoire après la construction + // sinon Pose.orElseEmpty retournerait des matrices non initialisées. + arm.bakeOriginMatrices(); + + return arm; + } + + private static Joint joint(Map target, String name, int id) { + Joint j = new Joint(name, id, new OpenMatrix4f()); + target.put(name, j); + return j; + } +} diff --git a/src/main/java/com/tiedup/remake/rig/patch/ClientPlayerPatch.java b/src/main/java/com/tiedup/remake/rig/patch/ClientPlayerPatch.java index 532562e..1cff54b 100644 --- a/src/main/java/com/tiedup/remake/rig/patch/ClientPlayerPatch.java +++ b/src/main/java/com/tiedup/remake/rig/patch/ClientPlayerPatch.java @@ -10,45 +10,50 @@ import net.minecraft.client.player.AbstractClientPlayer; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import com.tiedup.remake.rig.armature.Armature; -import com.tiedup.remake.rig.math.OpenMatrix4f; - /** - * Stub Phase 2.3 — patch côté client pour les joueurs remote (autres joueurs - * dans une session multi). Etoffé Phase 2.4 avec la logique cape / scale / - * slim vs default model selection. + * Patch côté client pour les joueurs remote (autres joueurs en session multi). * - *

Version minimale : {@code overrideRender=true} (on veut que le renderer - * patched intercepte et dispatch au RIG), {@code getArmature=null} stub (TODO - * Phase 2.4), {@code updateMotion} no-op (Phase 2.7).

+ *

Hérite tout de {@link PlayerPatch} : + * {@link #overrideRender()} = true, armature biped, updateMotion stub. + * Pour un remote player on veut systématiquement le rendering RIG — pas de + * cas où on voudrait le modèle vanilla MC (qui perdrait les items bondage + * RIG-attached Phase 3).

+ * + *

Différence avec {@link LocalPlayerPatch} : ce dernier override + * {@link #overrideRender()} pour désactiver le render RIG en first-person + * (sinon on verrait l'intérieur du mesh). Les remote players ne sont jamais + * en first-person du point de vue de l'observer → pas besoin.

* *

Forke conceptuellement {@code yesman.epicfight.client.world.capabilites.entitypatch.player.AbstractClientPlayerPatch} * (EF 479 LOC) mais réécrit from scratch (D-04) car ~80% du contenu original - * est combat/skill non réutilisable pour TiedUp.

+ * est combat/skill non réutilisable pour TiedUp (slim/default model switch, + * cape handling, skin tick — tout ça pourrait être utile Phase 5 si on + * restaure le rendering custom skin layer).

+ * + * @param concrete type (remote player, et fallback pour LocalPlayer via + * {@link LocalPlayerPatch}) */ @OnlyIn(Dist.CLIENT) public class ClientPlayerPatch extends PlayerPatch { - @Override - public void updateMotion(boolean considerInaction) { - // no-op stub — Phase 2.7 - } - - @Override - public Armature getArmature() { - // TODO Phase 2.4 — retourner TiedUpRigRegistry.BIPED.get() - return null; - } - - @Override - public boolean overrideRender() { - // On veut que le render pipeline patched prenne la main pour les - // remote players visibles. - return true; - } - - @Override - public OpenMatrix4f getModelMatrix(float partialTick) { - return getMatrix(partialTick); - } + /** + * Placeholder pour la logique "cacher le player en first-person pour les + * items de type wrap / latex_sack / cape-over-head" (V3-REW-01, item + * rework Phase 3). + * + *

Actuellement retourne toujours {@code false} — aucun item ne demande + * ce hide. Sera re-implémenté Phase 3 quand le + * {@code PlayerArmHideEventHandler} V2 sera porté en jointMask-based + * logic côté StaticAnimation (cf. + * {@code docs/plans/rig/V3_REWORK_BACKLOG.md} V3-REW-01).

+ * + *

Appelé depuis le renderer patched Phase 2.5+ : si true, skip le + * draw du mesh player (mais draw les items bondage attachés).

+ * + * @return true si le player doit être invisible en first-person + */ + public boolean isFirstPersonHidden() { + // TODO Phase 3 (V3-REW-01) : check equipped items pour wrap / latex_sack. + return false; + } } diff --git a/src/main/java/com/tiedup/remake/rig/patch/LocalPlayerPatch.java b/src/main/java/com/tiedup/remake/rig/patch/LocalPlayerPatch.java index 829bf2b..f6cb02a 100644 --- a/src/main/java/com/tiedup/remake/rig/patch/LocalPlayerPatch.java +++ b/src/main/java/com/tiedup/remake/rig/patch/LocalPlayerPatch.java @@ -6,25 +6,61 @@ package com.tiedup.remake.rig.patch; +import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; /** - * Stub Phase 2.3 — patch spécifique au joueur local (self). Spécialisation de - * {@link ClientPlayerPatch} pour les hooks first-person / caméra / input - * capture bondage-specific (struggle keys, adjustment menu). + * Patch spécifique au joueur local (self). Override + * {@link #overrideRender()} pour gérer le cas first-person : * - *

Version minimale : hérite de {@link ClientPlayerPatch} sans override. - * Phase 2.4 ajoutera les hooks first-person hide (arms/hands invisibles sous - * wrap/latex_sack), camera sync leash, etc.

+ *
    + *
  • First-person (F5 = first) : retourne {@code false} — on laisse + * le rendu vanilla Minecraft prendre la main (bras en FP, item held, + * overlay mains). Rendre le biped TiedUp en FP donnerait une vue + * depuis l'intérieur du mesh, illisible.
  • + *
  • Third-person (F5 = third, either view) ou tout autre cas : + * retourne {@code true} — le renderer RIG patched prend la main et + * dessine le biped TiedUp comme pour les autres players.
  • + *
* - *

Forke conceptuellement {@code yesman.epicfight.client.world.capabilites.entitypatch.player.LocalPlayerPatch} - * (EF 572 LOC) mais réécrit from scratch (D-04) car skill UI state / input / - * camera cinematics non réutilisables.

+ *

Pourquoi la check {@code entity == Minecraft.getInstance().player} : + * {@link LocalPlayerPatch} est attaché uniquement au LocalPlayer (cf. + * {@link EntityPatchProvider#registerEntityPatchesClient()}), donc en pratique + * {@code this.original == Minecraft.getInstance().player} toujours. Le check + * est une ceinture-bretelles au cas où le dispatcher change un jour pour + * attacher ce patch à autre chose (très improbable).

+ * + *

Pattern EF équivalent : {@code LocalPlayerPatch.java:143-152} — + * même logique mais EF ajoute un toggle {@code ClientConfig.enableAnimatedFirstPersonModel} + * pour ceux qui veulent le biped rendu même en FP. TiedUp peut l'ajouter + * plus tard si demande gameplay, mais par défaut FP = vanilla.

+ * + *

Hooks first-person hide specific bondage items (wrap / latex_sack / + * blindfold = vision obstruée) → Phase 3 via + * {@link ClientPlayerPatch#isFirstPersonHidden()} (V3-REW-01).

*/ @OnlyIn(Dist.CLIENT) public class LocalPlayerPatch extends ClientPlayerPatch { - // Hooks first-person / caméra / input → Phase 2.4 + /** + * @return {@code false} si on est en first-person sur soi-même (laisse + * rendre le vanilla), {@code true} dans tous les autres cas. + */ + @Override + public boolean overrideRender() { + Minecraft mc = Minecraft.getInstance(); + + // mc.player peut être null durant un rejoin (~1 tick entre + // disconnect et respawn). Dans ce cas pas de FP à gérer, on tombe + // sur le comportement parent (true). + if (mc.player != null && this.original == mc.player) { + if (mc.options.getCameraType().isFirstPerson()) { + return false; + } + } + + return super.overrideRender(); + } } diff --git a/src/main/java/com/tiedup/remake/rig/patch/PlayerPatch.java b/src/main/java/com/tiedup/remake/rig/patch/PlayerPatch.java index b47449c..1d17d20 100644 --- a/src/main/java/com/tiedup/remake/rig/patch/PlayerPatch.java +++ b/src/main/java/com/tiedup/remake/rig/patch/PlayerPatch.java @@ -8,10 +8,151 @@ package com.tiedup.remake.rig.patch; import net.minecraft.world.entity.player.Player; +import com.tiedup.remake.rig.TiedUpArmatures; +import com.tiedup.remake.rig.TiedUpRigRegistry; +import com.tiedup.remake.rig.anim.Animator; +import com.tiedup.remake.rig.anim.LivingMotions; +import com.tiedup.remake.rig.armature.HumanoidArmature; +import com.tiedup.remake.rig.math.MathUtils; +import com.tiedup.remake.rig.math.OpenMatrix4f; + /** - * Stub RIG Phase 0 — patch de capability attaché à un {@link Player}. - * Re-implém complète Phase 2 (séparation ClientPlayerPatch / ServerPlayerPatch, - * input handling, first-person, cam sync). + * RIG Phase 2.4 — patch de capability attaché à un {@link Player}. + * + *

Étoffé à partir du stub Phase 0 pour :

+ *
    + *
  • Fournir l'{@link #getArmature() armature biped} TiedUp + * ({@link TiedUpArmatures#BIPED})
  • + *
  • Activer le rendering RIG patched ({@link #overrideRender()} = true) + * — {@link ServerPlayerPatch} ré-override à false et + * {@link LocalPlayerPatch} gère le cas first-person
  • + *
  • Fournir un {@link #getModelMatrix(float)} avec scale player vanilla + * ({@value #PLAYER_SCALE}) — cf. EF {@code PlayerPatch:82,176}
  • + *
  • Stub {@link #initAnimator(Animator)} qui bind + * {@code LivingMotions.IDLE → EMPTY_ANIMATION} (Phase 2.7 remplacera par + * {@code CONTEXT_STAND_IDLE} co-authored)
  • + *
+ * + *

Ce qui manque vs EF PlayerPatch (766 LOC), voulu :

+ *
    + *
  • Stamina system ({@code STAMINA} EntityDataAccessor + regen logic)
  • + *
  • PlayerMode VANILLA/EPICFIGHT toggle
  • + *
  • modelYRot sync / turningLocked handling
  • + *
  • xo/yo/zo previous pos caching
  • + *
  • PlayerEventListener — remplacé par SystemMessageManager/events TiedUp
  • + *
  • Skill system entièrement
  • + *
  • Toute la logique attaque / damage / offhand / armor negation
  • + *
+ * + *

TiedUp n'a pas de combat — ces features seraient dead code. Si on en + * veut une (ex. stamina pour struggle), on l'ajoutera au cas par cas (D-04).

*/ public abstract class PlayerPatch extends LivingEntityPatch { + + /** + * Scale vanilla player EF-identique (15/16 ≈ 0.9375). Le modèle vanilla + * Minecraft rend le joueur à 15/16 de sa taille logique — si on ne + * compense pas, le skinned mesh apparaît "trop grand" comparé à la hitbox. + * + *

Source : EF {@code PlayerPatch:82}.

+ */ + protected static final float PLAYER_SCALE = 15.0F / 16.0F; + + /** + * Override — stub sans transition / sans vélocité. + * + *

Phase 2.7+ implémentera la détection de motion (walk/run/sneak/sit/ + * swim/kneel pour TiedUp) via vélocité + state checks. Ici on ne fait + * rien pour que les {@link #currentLivingMotion} restent à IDLE par + * défaut (cf. {@link LivingEntityPatch}).

+ * + * @param considerInaction paramètre EF legacy — si true, l'impl complète + * doit bloquer la transition de motion si l'entité + * est dans une {@code inaction()}. Pas utilisé ici. + */ + @Override + public void updateMotion(boolean considerInaction) { + // Stub Phase 2.4 — pas de motion detection. + // Phase 2.7 : cf. EF LivingEntityPatch.updateMotion (velocity + state + // machine) + mapping sur LivingMotions TiedUp (idle/walk/kneel/sit). + } + + /** + * Retourne l'armature biped TiedUp — identique pour tous les players. + * + *

Phase 2.4 : version procédurale ({@link TiedUpArmatures#BIPED} + * construit from scratch). Phase 2.7 remplacera par un chargement JSON + * avec offsets Blender-authored.

+ * + *

Pattern EF : + * {@code AbstractClientPlayerPatch.java:~70} expose {@code this.armature} + * initialisé au constructor. On renvoie directement le singleton — léger + * et thread-safe (construction lazy dans {@link TiedUpArmatures#BIPED}).

+ */ + @Override + public HumanoidArmature getArmature() { + return TiedUpArmatures.BIPED.get(); + } + + /** + * Override — tous les players passent par le renderer RIG patched. + * + *

{@link ServerPlayerPatch} ré-override à false (le serveur ne rend + * rien). {@link LocalPlayerPatch} ré-override pour gérer le cas + * first-person (cf. doc là-bas).

+ */ + @Override + public boolean overrideRender() { + return true; + } + + /** + * Model matrix pour le render : position identity (le renderer applique + * déjà la translation) + rotation yaw (le corps suit la caméra) + scale + * {@value #PLAYER_SCALE}. + * + *

Simplifié vs EF : pas de handling {@code modelYRot} (self-managed + * rotation lerp pour turning lock) et pas de {@code ridingEntity} override + * — Phase 2.7+ si on ajoute un système de mount TiedUp (maid pet sitting + * etc.).

+ * + *

Baby support (half scale) — EF applique 0.5 si {@code isBaby}. On + * garde pour cohérence (les NPCs Damsel n'ont pas d'état baby mais + * VillagerMCA si un jour on les patch le veut).

+ */ + @Override + public OpenMatrix4f getModelMatrix(float partialTick) { + float scale = (this.original.isBaby() ? 0.5F : 1.0F) * PLAYER_SCALE; + + // Signature : xPosO, xPos, yPosO, yPos, zPosO, zPos, xRotO, xRot, + // yRotO, yRot, partialTick, scaleX, scaleY, scaleZ + // On ignore pos/xRot (delta pose) — l'entity renderer applique déjà + // la position monde. Seul le yRot (yaw corps, pas tête) est utile + // pour que le mesh s'oriente avec l'entity. + return MathUtils.getModelMatrixIntegral( + 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, + 0.0F, 0.0F, + this.original.yBodyRotO, this.original.yBodyRot, + partialTick, scale, scale, scale + ); + } + + /** + * Hook {@link LivingEntityPatch#initAnimator(Animator)} : bind la motion + * IDLE sur l'animation "ne fait rien" par défaut. Phase 2.7 remplacera + * par {@code TiedUpAnimationRegistry.CONTEXT_STAND_IDLE} avec quelques + * keyframes de balancement. + * + *

L'ordre EF ajoute ~25 motions différentes (WALK, RUN, SNEAK, SIT, + * SLEEP, etc.). On se limite à IDLE Phase 2.4 — ajouter les autres + * sans anim source = pollution registre pour rien. Au fur et à mesure + * que les JSON co-authored arrivent (Phase 2.7 / 4), on ajoute les + * binds correspondants.

+ */ + @Override + protected void initAnimator(Animator animator) { + super.initAnimator(animator); + animator.addLivingAnimation(LivingMotions.IDLE, TiedUpRigRegistry.EMPTY_ANIMATION); + } + } diff --git a/src/main/java/com/tiedup/remake/rig/patch/ServerPlayerPatch.java b/src/main/java/com/tiedup/remake/rig/patch/ServerPlayerPatch.java index 2d56af0..b1ea197 100644 --- a/src/main/java/com/tiedup/remake/rig/patch/ServerPlayerPatch.java +++ b/src/main/java/com/tiedup/remake/rig/patch/ServerPlayerPatch.java @@ -8,45 +8,41 @@ package com.tiedup.remake.rig.patch; import net.minecraft.server.level.ServerPlayer; -import com.tiedup.remake.rig.armature.Armature; -import com.tiedup.remake.rig.math.OpenMatrix4f; - /** - * Stub Phase 2.3 — patch côté serveur pour les joueurs. Version minimale pour - * débloquer le dispatch via {@link EntityPatchProvider}. La version complète - * (kidnap state sync, struggle progression, ownership) est Phase 2.4+. + * Patch côté serveur pour les joueurs. Hérite tout de {@link PlayerPatch} — + * on ne garde qu'un seul override : {@link #overrideRender()} forcé à + * {@code false}. * - *

Garanties actuelles :

+ *

Pourquoi override render → false : le serveur ne rend rien + * visuellement, mais l'animator continue de tourner pour calculer la pose + * "aveugle" (pos joints à un tick donné). Cette pose sert au tracker serveur + * (combat hitboxes EF, hook AI TiedUp). {@link PlayerPatch#overrideRender()} + * retourne {@code true} par défaut → si on oubliait l'override, un dispatcher + * de rendering théorique côté serveur (il n'y en a pas actuellement, mais + * l'API publique le permet) se déclencherait à tort.

+ * + *

Ce qui est dans PlayerPatch et hérité ici :

*
    - *
  • {@code overrideRender() = false} — serveur ne rend rien, pas de besoin - * d'intercepter le render pipeline
  • - *
  • {@code getArmature() = null} — le serveur n'a pas besoin de mesh data, - * il joue des animations "blind" (calcule la pose pour syncer aux clients). - * Sera fixé en Phase 2.4 avec un fallback vers {@code TiedUpRigRegistry.BIPED}.
  • - *
  • {@code updateMotion} no-op — Phase 2.7 hook tick réel
  • + *
  • {@code getArmature()} → {@link com.tiedup.remake.rig.TiedUpArmatures#BIPED}
  • + *
  • {@code getModelMatrix(partialTick)} — inutile côté serveur mais pas de + * coût à le garder (pas appelé)
  • + *
  • {@code updateMotion(boolean)} no-op Phase 2.4
  • + *
  • {@code initAnimator} bind IDLE → EMPTY_ANIMATION
  • *
+ * + *

Phase 2.7+ : {@code serverTick} override pour poser motion + sync aux + * clients via packet (cf. EF {@code PlayerPatch.serverTick}). Phase 3+ : + * hooks struggle / kidnap state ici.

*/ public class ServerPlayerPatch extends PlayerPatch { - @Override - public void updateMotion(boolean considerInaction) { - // no-op stub — Phase 2.7 - } - - @Override - public Armature getArmature() { - // TODO Phase 2.4 — retourner TiedUpRigRegistry.BIPED.get() - return null; - } - - @Override - public boolean overrideRender() { - // Serveur ne rend rien. - return false; - } - - @Override - public OpenMatrix4f getModelMatrix(float partialTick) { - return getMatrix(partialTick); - } + /** + * Override à false — le serveur n'intercepte jamais le render (il ne rend + * pas). Voir doc classe pour pourquoi c'est important malgré l'absence + * de renderer serveur actuel. + */ + @Override + public boolean overrideRender() { + return false; + } }