From ccec6bd87e7a79ac31bc077c6766b1b4304293b5 Mon Sep 17 00:00:00 2001 From: notevil Date: Wed, 22 Apr 2026 21:42:22 +0200 Subject: [PATCH] Phase 2.3 review fixes : P2-BUG-01/02/03 + RISK-02 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Résout les findings P0 remontés par la review post-Phase 2.3 (@4780c96). P2-BUG-01 — Pipeline RIG dormant au runtime EntityPatchProvider.registerEntityPatches() et registerEntityPatchesClient() étaient définis mais JAMAIS appelés depuis TiedUpMod setups → CAPABILITIES map vide → aucun patch ne se crée, pipeline entier dormant. Fix : - commonSetup : event.enqueueWork(EntityPatchProvider::registerEntityPatches) - ClientModEvents.onClientSetup : event.enqueueWork( EntityPatchProvider::registerEntityPatchesClient) avant BondageAnimationManager.init P2-BUG-02 — Memory leak LazyOptional non invalidée EntityPatchProvider.optional jamais invalidated → chaque respawn/dim change fuit patch + animator + armature. Fix : - EntityPatchProvider.invalidate() public méthode qui appelle optional.invalidate() - TiedUpCapabilityEvents.attachEntityCapability : event.addListener(provider::invalidate) après addCapability. Pattern aligné sur V2BondageEquipmentProvider existant. P2-BUG-03 — NPE latent HumanoidModelBaker.bakeArmor Ligne 88 retournait entityMesh.getHumanoidArmorModel(slot).get() mais le getter retourne null (Phase 0 strip S-03 : Meshes.HELMET/CHESTPLATE/LEGGINS/BOOTS strippés). Null-check + fallback null + commentaire pointant vers V3-REW-04. P2-RISK-02 — @OnlyIn(Dist.CLIENT) sur transformers VanillaModelTransformer, HumanoidModelTransformer, HumanoidModelBaker importent HumanoidModel/PoseStack (client-only). Risque NoClassDefFoundError si code serveur touche HumanoidModelBaker.VANILLA_TRANSFORMER static field. Fix : @OnlyIn(Dist.CLIENT) sur les 3 classes. P2-RISK-01/03 + SMELL-01/02/03 tracés dans docs/plans/rig/PHASE0_DEGRADATIONS.md Phase 2.1-2.3 findings section. Compile BUILD SUCCESSFUL + 11 tests bridge GREEN maintenus. --- src/main/java/com/tiedup/remake/core/TiedUpMod.java | 6 ++++++ .../rig/mesh/transformer/HumanoidModelBaker.java | 10 +++++++++- .../rig/mesh/transformer/HumanoidModelTransformer.java | 4 ++++ .../rig/mesh/transformer/VanillaModelTransformer.java | 4 ++++ .../tiedup/remake/rig/patch/EntityPatchProvider.java | 10 ++++++++++ .../remake/rig/patch/TiedUpCapabilityEvents.java | 5 +++++ 6 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/tiedup/remake/core/TiedUpMod.java b/src/main/java/com/tiedup/remake/core/TiedUpMod.java index 6b13fd9..3aa3615 100644 --- a/src/main/java/com/tiedup/remake/core/TiedUpMod.java +++ b/src/main/java/com/tiedup/remake/core/TiedUpMod.java @@ -137,6 +137,9 @@ public class TiedUpMod { // Register dispenser behaviors (must be on main thread) event.enqueueWork(DispenserBehaviors::register); + + // RIG Phase 2 — dispatcher EntityType → EntityPatch (PLAYER Phase 2, NPCs Phase 5) + event.enqueueWork(com.tiedup.remake.rig.patch.EntityPatchProvider::registerEntityPatches); } /** @@ -185,6 +188,9 @@ public class TiedUpMod { // Initialize animation system event.enqueueWork(() -> { + // RIG Phase 2 — override client dispatch PLAYER → Local/Client/ServerPlayerPatch + com.tiedup.remake.rig.patch.EntityPatchProvider.registerEntityPatchesClient(); + // Initialize unified BondageAnimationManager com.tiedup.remake.client.animation.BondageAnimationManager.init(); LOGGER.info("BondageAnimationManager initialized"); diff --git a/src/main/java/com/tiedup/remake/rig/mesh/transformer/HumanoidModelBaker.java b/src/main/java/com/tiedup/remake/rig/mesh/transformer/HumanoidModelBaker.java index 86f72e5..bcc3b2a 100644 --- a/src/main/java/com/tiedup/remake/rig/mesh/transformer/HumanoidModelBaker.java +++ b/src/main/java/com/tiedup/remake/rig/mesh/transformer/HumanoidModelBaker.java @@ -32,11 +32,14 @@ import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ArmorItem; import net.minecraft.world.item.ItemStack; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.registries.ForgeRegistries; import com.tiedup.remake.rig.mesh.SkinnedMesh; import com.tiedup.remake.rig.mesh.HumanoidMesh; import com.tiedup.remake.rig.TiedUpRigConstants; +@OnlyIn(Dist.CLIENT) public class HumanoidModelBaker { static final Map BAKED_MODELS = Maps.newHashMap(); static final List MODEL_TRANSFORMERS = Lists.newArrayList(); @@ -85,7 +88,12 @@ public class HumanoidModelBaker { if (!EXCEPTIONAL_MODELS.contains(armorItem)) { if (forgeModel == originalModel || !(forgeModel instanceof HumanoidModel humanoidModel)) { - return entityMesh.getHumanoidArmorModel(slot).get(); + // RIG Phase 0 : Meshes.HELMET/CHESTPLATE/LEGGINS/BOOTS strippés → + // HumanoidMesh.getHumanoidArmorModel(slot) retourne null. + // Safe-guard ici pour éviter NPE si bakeArmor est appelé avant que + // V3-REW-04 soit implémenté (armor rendering rework). + var armorAccessor = entityMesh.getHumanoidArmorModel(slot); + return armorAccessor != null ? armorAccessor.get() : null; } for (HumanoidModelTransformer modelTransformer : MODEL_TRANSFORMERS) { diff --git a/src/main/java/com/tiedup/remake/rig/mesh/transformer/HumanoidModelTransformer.java b/src/main/java/com/tiedup/remake/rig/mesh/transformer/HumanoidModelTransformer.java index e7c340d..3bdfd80 100644 --- a/src/main/java/com/tiedup/remake/rig/mesh/transformer/HumanoidModelTransformer.java +++ b/src/main/java/com/tiedup/remake/rig/mesh/transformer/HumanoidModelTransformer.java @@ -14,10 +14,14 @@ import com.mojang.blaze3d.vertex.PoseStack; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import net.minecraft.client.model.HumanoidModel; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + import com.tiedup.remake.rig.mesh.MeshPartDefinition; import com.tiedup.remake.rig.mesh.SingleGroupVertexBuilder; import com.tiedup.remake.rig.mesh.SkinnedMesh; +@OnlyIn(Dist.CLIENT) public abstract class HumanoidModelTransformer { public abstract SkinnedMesh transformArmorModel(HumanoidModel humanoidModel); diff --git a/src/main/java/com/tiedup/remake/rig/mesh/transformer/VanillaModelTransformer.java b/src/main/java/com/tiedup/remake/rig/mesh/transformer/VanillaModelTransformer.java index bb78f81..8ee4571 100644 --- a/src/main/java/com/tiedup/remake/rig/mesh/transformer/VanillaModelTransformer.java +++ b/src/main/java/com/tiedup/remake/rig/mesh/transformer/VanillaModelTransformer.java @@ -36,8 +36,12 @@ import com.tiedup.remake.rig.math.OpenMatrix4f; import com.tiedup.remake.rig.math.QuaternionUtils; import com.tiedup.remake.rig.math.Vec2f; import com.tiedup.remake.rig.math.Vec3f; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + import com.tiedup.remake.rig.mixin.client.MixinAgeableListModel; +@OnlyIn(Dist.CLIENT) public class VanillaModelTransformer extends HumanoidModelTransformer { public static final SimpleTransformer HEAD = new SimpleTransformer(AABB.ofSize(new Vec3(0.0D, -4.0D, 0.0D), 8.0D, 8.0D, 8.0D), 9); public static final SimpleTransformer LEFT_FEET = new SimpleTransformer(AABB.ofSize(new Vec3(0.0D, -4.0D, 0.0D), 8.0D, 8.0D, 8.0D), 5); diff --git a/src/main/java/com/tiedup/remake/rig/patch/EntityPatchProvider.java b/src/main/java/com/tiedup/remake/rig/patch/EntityPatchProvider.java index f696fae..7ad9701 100644 --- a/src/main/java/com/tiedup/remake/rig/patch/EntityPatchProvider.java +++ b/src/main/java/com/tiedup/remake/rig/patch/EntityPatchProvider.java @@ -148,4 +148,14 @@ public class EntityPatchProvider implements ICapabilityProvider, NonNullSupplier public LazyOptional getCapability(Capability cap, Direction side) { return cap == TiedUpCapabilities.CAPABILITY_ENTITY ? this.optional.cast() : LazyOptional.empty(); } + + /** + * Invalide la {@link LazyOptional} portée par ce provider. À appeler depuis + * {@code AttachCapabilitiesEvent.addListener} — sans ça les références vers + * le patch, l'animator et l'armature persistent à chaque respawn / dimension + * change → fuite mémoire. + */ + public void invalidate() { + this.optional.invalidate(); + } } diff --git a/src/main/java/com/tiedup/remake/rig/patch/TiedUpCapabilityEvents.java b/src/main/java/com/tiedup/remake/rig/patch/TiedUpCapabilityEvents.java index 4419e69..c59ec3e 100644 --- a/src/main/java/com/tiedup/remake/rig/patch/TiedUpCapabilityEvents.java +++ b/src/main/java/com/tiedup/remake/rig/patch/TiedUpCapabilityEvents.java @@ -69,5 +69,10 @@ public class TiedUpCapabilityEvents { // l'entity commence son premier tick. patch.onConstructed(entity); event.addCapability(ENTITY_CAPABILITY_KEY, provider); + + // CRITICAL : invalide la LazyOptional au respawn / dim change, sinon + // chaque mort fuit patch + animator + armature. Pattern Forge standard + // (cf. V2BondageEquipmentProvider.invalidate, CapabilityEventHandler:50). + event.addListener(provider::invalidate); } }