From d129983eb72f538b810ce338bfa18e6790e798e0 Mon Sep 17 00:00:00 2001
From: notevil
Date: Wed, 22 Apr 2026 23:16:35 +0200
Subject: [PATCH] Phase 2.5 review fixes : P0 biped warn + CME guard +
double-draw prevention
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
P0-BUG-001 : LOGGER.warn dans TiedUpArmatures.Holder static init quand les
joints biped sont en identity (Phase 2.4 stub). Sans ça, Phase 2.6 renderer
afficherait un mesh effondré sans signal dev. Warn apparaît une seule fois
(class-init lock JVM).
P0-BUG-002 : Lists.newArrayList(renderer.layers) copie défensive dans
PatchedLivingEntityRenderer.renderLayer. Mods tiers (Wildfire, SkinLayers3D,
Cosmetic Armor) peuvent muter renderer.layers runtime via AddLayers event
-> CME garantie sans copie. TiedUp va au-dela d'EF upstream.
P1-RISK-001 : Pose.orElseEmpty(name) utilise Map.getOrDefault qui retourne
un JointTransform.empty() detache non stocke dans la map -> toute mutation
.frontResult est perdue si le joint est absent. En pratique l'Animator peuple
toujours Head via getComposedLayerPose, mais defensif : on recupere l'instance,
mute, puis pose.putJointData(Head, mutatedTransform). Meme bug latent en EF
upstream.
P1-RISK-003 : PlayerItemInHandLayer extends ItemInHandLayer mais le dispatch
patchedLayers.containsKey(layer.getClass()) est strict -> layer player-specifique
passe au travers. Ajout du mapping explicite dans TiedUpPlayerRenderer
constructor avec le meme stub PatchedItemInHandLayer. Preventif Phase 3.
P2-RISK-004 : @SuppressWarnings scope resserre des 2 methodes aux 2 call sites
dispatch raw PatchedLayer qui en ont reellement besoin. Commentaire pointant
vers l'invariant runtime addPatchedLayer.
Tests : 15/15 rig tests GREEN, compile GREEN.
Doc : docs/plans/rig/PHASE0_DEGRADATIONS.md section Phase 2.5 findings ajoutee
(fichier gitignore, changements locaux pour future session).
---
.../tiedup/remake/rig/TiedUpArmatures.java | 15 ++++++++++-
.../remake/rig/render/PHumanoidRenderer.java | 15 ++++++++++-
.../render/PatchedLivingEntityRenderer.java | 17 ++++++++++---
.../rig/render/TiedUpPlayerRenderer.java | 25 ++++++++++++++++---
4 files changed, 63 insertions(+), 9 deletions(-)
diff --git a/src/main/java/com/tiedup/remake/rig/TiedUpArmatures.java b/src/main/java/com/tiedup/remake/rig/TiedUpArmatures.java
index e004a66..202ec42 100644
--- a/src/main/java/com/tiedup/remake/rig/TiedUpArmatures.java
+++ b/src/main/java/com/tiedup/remake/rig/TiedUpArmatures.java
@@ -89,7 +89,20 @@ public final class TiedUpArmatures {
* le cache.
*/
private static final class Holder {
- static final HumanoidArmature INSTANCE = buildBiped();
+ static final HumanoidArmature INSTANCE;
+ static {
+ // Signal visible au dev que les joints sont en identity transform.
+ // Sans ça, Phase 2.6+ câblera le renderer et le mesh apparaîtra
+ // "effondré à l'origine" sans signal — debug cauchemar. Le warn
+ // n'apparaît qu'une fois (class-init lock JVM).
+ TiedUpRigConstants.LOGGER.warn(
+ "TiedUpArmatures.BIPED initialized with IDENTITY joint transforms (Phase 2.4 stub). "
+ + "Mesh will render collapsed-to-origin until Phase 2.7 provides biped.json "
+ + "Blender-authored offsets. See docs/plans/rig/PHASE0_DEGRADATIONS.md "
+ + "Phase 2.4 backlog entry #1."
+ );
+ INSTANCE = buildBiped();
+ }
private Holder() {}
}
diff --git a/src/main/java/com/tiedup/remake/rig/render/PHumanoidRenderer.java b/src/main/java/com/tiedup/remake/rig/render/PHumanoidRenderer.java
index d656efc..d88ba71 100644
--- a/src/main/java/com/tiedup/remake/rig/render/PHumanoidRenderer.java
+++ b/src/main/java/com/tiedup/remake/rig/render/PHumanoidRenderer.java
@@ -76,7 +76,20 @@ public class PHumanoidRenderer renderer, T entitypatch, E entity, OpenMatrix4f[] poses, MultiBufferSource buffer, PoseStack poseStack, int packedLight, float partialTicks) {
float f = MathUtils.lerpBetween(entity.yBodyRotO, entity.yBodyRot, partialTicks);
float f1 = MathUtils.lerpBetween(entity.yHeadRotO, entity.yHeadRot, partialTicks);
@@ -203,7 +202,12 @@ public abstract class PatchedLivingEntityRenderer layer : renderer.layers) {
+ // P0-BUG-002 (review Phase 2.5) : copie défensive de renderer.layers —
+ // la liste est mutable et peut être touchée par des mods tiers (cosmetics,
+ // wildfire gender, skin layers 3D) qui ajoutent un layer runtime via
+ // AddLayers event. Sans copie, CME garantie dès qu'un autre mod mute
+ // la liste pendant notre itération.
+ for (RenderLayer layer : Lists.newArrayList(renderer.layers)) {
Class> layerClass = layer.getClass();
if (layerClass.isAnonymousClass()) {
@@ -211,14 +215,19 @@ public abstract class PatchedLivingEntityRenderer → PatchedLayer>.
+ @SuppressWarnings({ "rawtypes", "unchecked" })
PatchedLayer patchedLayer = this.patchedLayers.get(layerClass);
patchedLayer.renderLayer(entity, entitypatch, layer, poseStack, buffer, packedLight, poses, bob, f2, f7, partialTicks);
}
}
for (PatchedLayer> patchedLayer : this.customLayers) {
- @SuppressWarnings("rawtypes")
+ @SuppressWarnings({ "rawtypes", "unchecked" })
PatchedLayer raw = patchedLayer;
raw.renderLayer(entity, entitypatch, null, poseStack, buffer, packedLight, poses, bob, f2, f7, partialTicks);
}
diff --git a/src/main/java/com/tiedup/remake/rig/render/TiedUpPlayerRenderer.java b/src/main/java/com/tiedup/remake/rig/render/TiedUpPlayerRenderer.java
index 310724a..cd85720 100644
--- a/src/main/java/com/tiedup/remake/rig/render/TiedUpPlayerRenderer.java
+++ b/src/main/java/com/tiedup/remake/rig/render/TiedUpPlayerRenderer.java
@@ -9,6 +9,7 @@ package com.tiedup.remake.rig.render;
import net.minecraft.client.model.PlayerModel;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
+import net.minecraft.client.renderer.entity.layers.PlayerItemInHandLayer;
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
import net.minecraft.world.entity.EntityType;
import net.minecraftforge.api.distmarker.Dist;
@@ -38,9 +39,16 @@ import com.tiedup.remake.rig.patch.ClientPlayerPatch;
* {@code ArrowLayer} — flèches plantées dans le player (V3-REW-09)
* {@code BeeStingerLayer} — dards d'abeille plantés (V3-REW-09)
* {@code CapeLayer} — cape vanilla (V3-REW-08, compat skin layers)
- * {@code PlayerItemInHandLayer} — items en main (version player-spécifique,
- * distincte de {@link net.minecraft.client.renderer.entity.layers.ItemInHandLayer}) —
- * le layer vanilla continue de dessiner jusqu'à la Phase 3
+ *
+ *
+ * Layers mappés Phase 2.5 :
+ *
+ * - {@code HumanoidArmorLayer} → {@code PatchedArmorLayer} (hérité de PHumanoidRenderer)
+ * - {@code ItemInHandLayer} → {@code PatchedItemInHandLayer} (hérité de PHumanoidRenderer)
+ * - {@link PlayerItemInHandLayer} → {@code PatchedItemInHandLayer} (ajouté ici,
+ * P1-RISK-003 review Phase 2.5 : dispatch par classe stricte, PlayerItemInHandLayer
+ * extends ItemInHandLayer mais {@code .getClass()} diffère → sans mapping explicite,
+ * double-draw item quand Phase 3 câblera le vrai rendu)
*
*
* Fork conceptuel de {@code yesman.epicfight.client.renderer.patched.entity.PPlayerRenderer}
@@ -51,6 +59,17 @@ public class TiedUpPlayerRenderer extends PHumanoidRenderer entityType) {
super(Meshes.BIPED, context, entityType);
+
+ // P1-RISK-003 (review Phase 2.5) : PlayerItemInHandLayer extends ItemInHandLayer
+ // mais le dispatch `patchedLayers.containsKey(layer.getClass())` fait un
+ // match strict de classe — sans mapping explicite, le stub parent n'est
+ // pas reconnu et le layer vanilla continue de dessiner (double-draw
+ // quand Phase 3 activera le vrai rendu item). On réutilise le même stub
+ // no-op PatchedItemInHandLayer.
+ //
+ // Note : pas de problème Phase 2.5 tant que PatchedItemInHandLayer est
+ // no-op complet (aucun draw dans les 2 layers). Préventif pour Phase 3+.
+ this.addPatchedLayer(PlayerItemInHandLayer.class, new PatchedItemInHandLayer<>());
}
@Override