Phase 2.3 : capability system RIG (EntityPatchProvider + events)
5 classes ajoutées dans rig/patch/ : - TiedUpCapabilities.java Holder du Capability<EntityPatch> CAPABILITY_ENTITY (CapabilityToken auto-register) + helpers getEntityPatch / getPlayerPatch / getPlayerPatchAsOptional. Simplifié de EF (pas de ITEM/PROJECTILE/SKILL caps, combat only). - EntityPatchProvider.java ICapabilityProvider + Map<EntityType, Function<Entity, Supplier<EntityPatch<?>>>>. registerEntityPatches() pour commonSetup (EntityType.PLAYER seul Phase 2), registerEntityPatchesClient() pour clientSetup (dispatch LocalPlayerPatch vs ClientPlayerPatch<RemotePlayer> vs ServerPlayerPatch). CUSTOM_CAPABILITIES pour extensions futures. Pas de GlobalMobPatch combat fallback. IMPORTANT : n'enregistre PAS EntityType.VILLAGER (MCA conflict V3-REW-10). - TiedUpCapabilityEvents.java @Mod.EventBusSubscriber sur AttachCapabilitiesEvent<Entity>. Check oldPatch pour éviter double-attach, construit provider, appelle onConstructed eager (D-01 pattern EF), addCapability. Priority NORMAL (order d'attachement ne matière pas, c'est les runtime cross-cap reads qui importent et ceux-là sont déjà lazy dans onConstructed). 3 stubs PlayerPatch subclasses (placeholders Phase 2.4) : - ServerPlayerPatch : overrideRender=false, getArmature=null stub, updateMotion no-op - ClientPlayerPatch<T extends AbstractClientPlayer> : overrideRender=true, @OnlyIn CLIENT - LocalPlayerPatch extends ClientPlayerPatch<LocalPlayer> : vide pour l'instant Ces stubs satisfont le compile de EntityPatchProvider.registerEntityPatchesClient(). Le getArmature() null est non-bloquant Phase 2.3 mais devra être fixé Phase 2.4 pour le vrai rendering (lien avec TiedUpRigRegistry.BIPED à créer Phase 2.7). Compile BUILD SUCCESSFUL + 11 tests bridge GREEN maintenus.
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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 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.
|
||||
*
|
||||
* <p>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).</p>
|
||||
*
|
||||
* <p>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.</p>
|
||||
*/
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class ClientPlayerPatch<T extends AbstractClientPlayer> extends PlayerPatch<T> {
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.common.util.NonNullSupplier;
|
||||
|
||||
import com.tiedup.remake.rig.TiedUpRigConstants;
|
||||
|
||||
/**
|
||||
* Dispatcher + {@link ICapabilityProvider} qui construit l'{@link EntityPatch}
|
||||
* approprié pour un {@link Entity} donné, basé sur son {@link EntityType}.
|
||||
*
|
||||
* <p>Simplifié de EF {@code yesman.epicfight.world.capabilities.provider.EntityPatchProvider} :</p>
|
||||
* <ul>
|
||||
* <li>Pas de projectile (ProjectilePatch / ArrowPatch strippés)</li>
|
||||
* <li>Pas de GlobalMobPatch fallback sur gamerule stun</li>
|
||||
* <li>Pas d'EntityPatchRegistryEvent posté à ModLoader (pas de tiers mods EF pour l'instant)</li>
|
||||
* <li>{@link #CUSTOM_CAPABILITIES} reste exposé via {@link #putCustomEntityPatch(EntityType, Function)}
|
||||
* pour un hook d'extension future</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p><b>Attention MCA</b> : on ne doit PAS enregistrer {@link EntityType#VILLAGER}
|
||||
* dans {@link #CAPABILITIES}. MCA gère son propre rendering custom via
|
||||
* {@code MixinVillagerEntityMCAAnimated} et attacher notre patch causerait
|
||||
* double-rendering + rupture des anims MCA (cf.
|
||||
* {@code docs/plans/rig/V3_REWORK_BACKLOG.md} V3-REW-10).</p>
|
||||
*
|
||||
* <p><b>Init order</b> : {@link #registerEntityPatches()} doit être appelé en
|
||||
* {@code FMLCommonSetupEvent} (serveur + client), {@link #registerEntityPatchesClient()}
|
||||
* en {@code FMLClientSetupEvent} uniquement.</p>
|
||||
*/
|
||||
public class EntityPatchProvider implements ICapabilityProvider, NonNullSupplier<EntityPatch<?>> {
|
||||
|
||||
/** Provider map populée au setup, lu au spawn entity. */
|
||||
private static final Map<EntityType<?>, Function<Entity, Supplier<EntityPatch<?>>>> CAPABILITIES = Maps.newHashMap();
|
||||
|
||||
/** Hook extension pour mods/datapacks tiers. Prioritaire sur {@link #CAPABILITIES}. */
|
||||
private static final Map<EntityType<?>, Function<Entity, Supplier<EntityPatch<?>>>> CUSTOM_CAPABILITIES = Maps.newHashMap();
|
||||
|
||||
/**
|
||||
* À appeler en {@code FMLCommonSetupEvent.event.enqueueWork(...)}.
|
||||
*
|
||||
* <p>Phase 2 : enregistre uniquement {@link EntityType#PLAYER} côté serveur.
|
||||
* Les NPCs TiedUp (Damsel, Maid, Master, Kidnapper) seront ajoutés Phase 5
|
||||
* quand on aura des animations adaptées.</p>
|
||||
*/
|
||||
public static void registerEntityPatches() {
|
||||
CAPABILITIES.put(EntityType.PLAYER, (entityIn) -> ServerPlayerPatch::new);
|
||||
|
||||
TiedUpRigConstants.LOGGER.debug(
|
||||
"EntityPatchProvider: registered {} entity types (common)", CAPABILITIES.size()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* À appeler en {@code FMLClientSetupEvent.event.enqueueWork(...)}.
|
||||
*
|
||||
* <p>Surcharge {@link EntityType#PLAYER} côté client pour dispatcher vers
|
||||
* {@link LocalPlayerPatch} (joueur local) vs {@link ClientPlayerPatch}
|
||||
* (remote players) vs {@link ServerPlayerPatch} (si logical server même JVM).</p>
|
||||
*/
|
||||
public static void registerEntityPatchesClient() {
|
||||
CAPABILITIES.put(EntityType.PLAYER, (entityIn) -> {
|
||||
if (entityIn instanceof net.minecraft.client.player.LocalPlayer) {
|
||||
return LocalPlayerPatch::new;
|
||||
} else if (entityIn instanceof net.minecraft.client.player.RemotePlayer) {
|
||||
return ClientPlayerPatch<net.minecraft.client.player.RemotePlayer>::new;
|
||||
} else if (entityIn instanceof net.minecraft.server.level.ServerPlayer) {
|
||||
return ServerPlayerPatch::new;
|
||||
}
|
||||
return () -> null;
|
||||
});
|
||||
|
||||
TiedUpRigConstants.LOGGER.debug(
|
||||
"EntityPatchProvider: client-side player dispatch installed"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enregistre un patch provider custom pour un {@link EntityType} donné.
|
||||
* Utilisé pour extensions tierces (compat mods) ou datapack-driven patches.
|
||||
*
|
||||
* <p>Prioritaire sur {@link #CAPABILITIES} : un call custom override la
|
||||
* version par défaut si elle existe.</p>
|
||||
*/
|
||||
public static void putCustomEntityPatch(EntityType<?> entityType, Function<Entity, Supplier<EntityPatch<?>>> provider) {
|
||||
CUSTOM_CAPABILITIES.put(entityType, provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Nettoie les custom patches (typiquement au datapack reload).
|
||||
*/
|
||||
public static void clearCustom() {
|
||||
CUSTOM_CAPABILITIES.clear();
|
||||
}
|
||||
|
||||
// ---------- instance ----------
|
||||
|
||||
private EntityPatch<?> capability;
|
||||
private final LazyOptional<EntityPatch<?>> optional = LazyOptional.of(this);
|
||||
|
||||
public EntityPatchProvider(Entity entity) {
|
||||
Function<Entity, Supplier<EntityPatch<?>>> provider =
|
||||
CUSTOM_CAPABILITIES.getOrDefault(entity.getType(), CAPABILITIES.get(entity.getType()));
|
||||
|
||||
if (provider != null) {
|
||||
try {
|
||||
this.capability = provider.apply(entity).get();
|
||||
} catch (Exception e) {
|
||||
TiedUpRigConstants.LOGGER.error(
|
||||
"EntityPatchProvider: failed to construct patch for {}",
|
||||
entity.getType(), e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true si ce provider a bien construit un patch pour l'entity
|
||||
* (= entity est dans la whitelist PLAYER / future NPCs TiedUp).
|
||||
*/
|
||||
public boolean hasCapability() {
|
||||
return this.capability != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityPatch<?> get() {
|
||||
return this.capability;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
|
||||
return cap == TiedUpCapabilities.CAPABILITY_ENTITY ? this.optional.cast() : LazyOptional.empty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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 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).
|
||||
*
|
||||
* <p>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.</p>
|
||||
*
|
||||
* <p>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.</p>
|
||||
*/
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class LocalPlayerPatch extends ClientPlayerPatch<LocalPlayer> {
|
||||
|
||||
// Hooks first-person / caméra / input → Phase 2.4
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 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+.
|
||||
*
|
||||
* <p>Garanties actuelles :</p>
|
||||
* <ul>
|
||||
* <li>{@code overrideRender() = false} — serveur ne rend rien, pas de besoin
|
||||
* d'intercepter le render pipeline</li>
|
||||
* <li>{@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}.</li>
|
||||
* <li>{@code updateMotion} no-op — Phase 2.7 hook tick réel</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class ServerPlayerPatch extends PlayerPatch<ServerPlayer> {
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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 javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.CapabilityManager;
|
||||
import net.minecraftforge.common.capabilities.CapabilityToken;
|
||||
|
||||
/**
|
||||
* Holder du {@link Capability} central RIG, analogue à EF
|
||||
* {@code yesman.epicfight.world.capabilities.EpicFightCapabilities} mais réduit
|
||||
* à l'essentiel pour TiedUp :
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link #CAPABILITY_ENTITY} — attaché à {@code Player} (Phase 2) et NPCs
|
||||
* TiedUp (Phase 5). Porte l'{@link EntityPatch} qui contient l'Animator,
|
||||
* l'Armature, l'état d'animation, etc.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>EF a également {@code CAPABILITY_ITEM}, {@code CAPABILITY_PROJECTILE},
|
||||
* {@code CAPABILITY_SKILL} — tous combat-only, strippés pour TiedUp.</p>
|
||||
*
|
||||
* <p><b>Auto-registration</b> : {@link CapabilityToken} utilise une TypeToken
|
||||
* pour enregistrer le capability via réflection. Pas besoin d'abonner un
|
||||
* {@code RegisterCapabilitiesEvent} (comportement Forge 1.20.1, déjà utilisé
|
||||
* pour {@code V2_BONDAGE_EQUIPMENT} dans TiedUp).</p>
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class TiedUpCapabilities {
|
||||
|
||||
public static final Capability<EntityPatch> CAPABILITY_ENTITY =
|
||||
CapabilityManager.get(new CapabilityToken<>() {});
|
||||
|
||||
private TiedUpCapabilities() {}
|
||||
|
||||
/**
|
||||
* Extrait l'{@link EntityPatch} d'un entity avec null-check + type-check.
|
||||
*
|
||||
* @return le patch cast au type demandé, ou null si entity null / pas de
|
||||
* capability / type incompatible
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
public static <T extends EntityPatch> T getEntityPatch(@Nullable Entity entity, Class<T> type) {
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
EntityPatch<?> patch = entity.getCapability(CAPABILITY_ENTITY).orElse(null);
|
||||
if (patch != null && type.isAssignableFrom(patch.getClass())) {
|
||||
return (T) patch;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper court pour extraire un {@link PlayerPatch} d'un {@link Player}.
|
||||
*/
|
||||
@Nullable
|
||||
public static PlayerPatch<?> getPlayerPatch(@Nullable Player player) {
|
||||
if (player == null) {
|
||||
return null;
|
||||
}
|
||||
EntityPatch<?> patch = player.getCapability(CAPABILITY_ENTITY).orElse(null);
|
||||
return patch instanceof PlayerPatch<?> pp ? pp : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Version {@link Optional} de {@link #getPlayerPatch(Player)} pour les
|
||||
* call sites qui veulent un flow {@code .ifPresent(...)}.
|
||||
*/
|
||||
public static Optional<PlayerPatch<?>> getPlayerPatchAsOptional(@Nullable Entity entity) {
|
||||
if (entity == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
EntityPatch<?> patch = entity.getCapability(CAPABILITY_ENTITY).orElse(null);
|
||||
return patch instanceof PlayerPatch<?> pp ? Optional.of(pp) : Optional.empty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraftforge.event.AttachCapabilitiesEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
import com.tiedup.remake.core.TiedUpMod;
|
||||
import com.tiedup.remake.rig.TiedUpRigConstants;
|
||||
|
||||
/**
|
||||
* Subscriber Forge qui attache un {@link EntityPatchProvider} sur chaque
|
||||
* {@link Entity} dont l'{@link net.minecraft.world.entity.EntityType} est
|
||||
* enregistré dans {@link EntityPatchProvider#CAPABILITIES CAPABILITIES}
|
||||
* (Phase 2 : PLAYER uniquement).
|
||||
*
|
||||
* <p>Pattern EF {@code yesman.epicfight.events.CapabilityEvents:36-59} mais
|
||||
* simplifié : pas de dual-capability pour CAPABILITY_SKILL (combat strippé).</p>
|
||||
*
|
||||
* <p><b>Init paresseux</b> : l'{@code onConstructed} de {@link EntityPatch}
|
||||
* ne fait PAS de cross-capability lookup (pas de
|
||||
* {@code entity.getCapability(V2_BONDAGE_EQUIPMENT)}) pour éviter toute race
|
||||
* avec l'ordre d'attachement inter-mods Forge. Voir adversarial review
|
||||
* 2026-04-22 §2 pour le raisonnement.</p>
|
||||
*/
|
||||
@Mod.EventBusSubscriber(modid = TiedUpMod.MOD_ID)
|
||||
public class TiedUpCapabilityEvents {
|
||||
|
||||
private static final ResourceLocation ENTITY_CAPABILITY_KEY =
|
||||
ResourceLocation.fromNamespaceAndPath(TiedUpMod.MOD_ID, "rig_entity_cap");
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@SubscribeEvent
|
||||
public static void attachEntityCapability(AttachCapabilitiesEvent<Entity> event) {
|
||||
Entity entity = event.getObject();
|
||||
|
||||
// Skip si déjà attaché par un autre subscriber (ex. datapack override via
|
||||
// CUSTOM_CAPABILITIES) — évite double-attach silencieux.
|
||||
EntityPatch oldPatch = TiedUpCapabilities.getEntityPatch(entity, EntityPatch.class);
|
||||
if (oldPatch != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityPatchProvider provider = new EntityPatchProvider(entity);
|
||||
if (!provider.hasCapability()) {
|
||||
return; // pas dans la whitelist (VILLAGER MCA, mobs non TiedUp, etc.)
|
||||
}
|
||||
|
||||
EntityPatch patch = provider.getCapability(
|
||||
TiedUpCapabilities.CAPABILITY_ENTITY, null
|
||||
).orElse(null);
|
||||
|
||||
if (patch == null) {
|
||||
TiedUpRigConstants.LOGGER.warn(
|
||||
"TiedUpCapabilityEvents: EntityPatchProvider reported hasCapability but CAPABILITY_ENTITY empty for {}",
|
||||
entity.getType()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Eager init (pattern EF) : construire l'Animator + Armature avant que
|
||||
// l'entity commence son premier tick.
|
||||
patch.onConstructed(entity);
|
||||
event.addCapability(ENTITY_CAPABILITY_KEY, provider);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user