LifePlay-Revival/Docs/Migration/etat/U58/U7/U7-T9-IMPL.md
edujiro5972 8084622450 LifePlay UE 5.8 : état de développement au 2026-10-19
Tickets : REP1-T4

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 22:57:42 +02:00

16 KiB
Raw Blame History

Fiche U7-T9 — Niveau N3 — Modèle prévu lp-impl (Opus xhigh) | utilisé Opus 5.5 (claude-opus-5-5) — Agent lp-impl — Skills ue-cpp-build, sk-protocol (lp-build, lp-ue-compat préchargés)

Marquage, dans le gestionnaire de mods, des lignes de mods refusés par la garde U7 (copie D:\Game\LifePlay-master 5.8, branche ue5.8). Décision utilisateur : C++ seulement, aucun Blueprint modifié. Statut : proposé, non compilé (BUILD = fiche séparée). Ni jeu, ni éditeur, ni commandlet, ni compilation lancés. Aucun commit.

1. Résultat

PASS-STATIC proposé (à recompter par la VAL). Critère d'arrêt (§ 9) non atteint : la ligne est identifiable sans Blueprint, et la reconstruction du widget ne rend pas le marquage instable (§ 3).

  • Ligne d'un mod refusé : nom suffixé « (not loaded) », ligne teintée rouge atténué, infobulle « Not loaded: <raisons anglaises de la fenêtre> », case ModEnabledBox désactivée. GI.ModEnableds n'est pas touché (choix du joueur conservé).
  • Idempotent : marque reconnue à la teinte de la ligne, suffixe protégé par EndsWith ; tri et images suivantes sans effet.
  • Une ligne Display par ouverture : Modules : gestionnaire, N mod(s) refuse(s) marque(s).
  • Aucun mod refusé : aucun ticker ajouté (coût nul).

2. Widget et propriétés (lecture seule des relevés, aucun outil lancé)

Élément Preuve Niveau
Gestionnaire /Game/UI/ModManager (classe ModManager_C), liste ModScrollBox (ScrollBox, variable) etat/L6e-CX-B09_widgets_apres.txt:14811, :14838 ; nom de classe ModManager_C : Source/LifePlay/LPDirectControlSubsystem.cpp:53 établi
Ligne /Game/UI/ModuleTick : ModEnabledBox (CheckBox), HoverButton (Button) contenant NameText et AuthorText (TextBlock, variables), UpButton, DownButton etat/L6e-CX-B09_widgets_apres.txt:14934, :14945, :14955, :14972, :14985, :14998, :15014 établi
Création à chaque ouverture : GI.CreateModManagerWidget → CreateWidget → AddToViewport ; fermeture RemoveFromParent etat/DOC-MOD_LPDumpFunction_20261007-083554.txt:1484, :1489, :1508 ; bouton titre → même événement : Source/LifePlayEditorTools/LPTitleModManagerCommandlet.cpp:295-296 établi
Par .lpmod : CreateWidget ModuleTick, FullString = fichier, UniqueID = ligne 1 après : (Trim, TrimTrailing) = MODULE_UNIQUEID, CheckIfModAlreadyFound, NameText.SetText (ligne 2), AuthorText.SetText (ligne 3), ajout à TempModuleTicks 083554.txt:1561, :1573, :1579, :1639, :1644, :3413 établi
Lignes ajoutées en bloc après la boucle (AddTempModuleTicks, dans l'ordre de ModEnableds) 083554.txt:3437, :3482 établi
Tri (▲/▼, SortLoadOrder) : Array_Swap(ModEnableds), ModScrollBox.ClearChildren, AddTempModuleTicks = mêmes objets remis 083554.txt:3497, :3501 établi
CheckIfModAlreadyFound fixe la variable ModEnabled de la ligne depuis ModEnableds (aucun SetIsChecked) etat/L6f_dump_GI.txt:153, :179 établi
ModuleTick, un seul graphe (EventGraph, 48 nœuds) : case → ModEnabled → GI.ToggleMod(UniqueID) ; un 2ᵉ événement inverse ModEnabled et appelle ToggleMod etat/DOC-MOD_LPDumpFunction_20261007-083154.txt:9-12 ; 083338.txt:141, :165, :182, :191, :211 établi
Ce 2ᵉ événement = HoverButton.OnClicked ; la case affiche ModEnabled par une liaison de propriété (pas de graphe de liaison) déduit : seul bouton restant hors ▲/▼ et survol ; aucun SetIsChecked dans le graphe estimé
Pocolov : dossier lpr_hair_pocolov, MODULE_UNIQUEID: lpr_hair_pocolov, MODULE_NAME: Pocolov Hairstyles, MODULE_AUTHOR: LifePlay Revival (hairstyles by Pocolov) D:\Game\LifePlay_Build_5.8_U7_P10\Windows\LifePlay\Content\Modules\lpr_hair_pocolov\lpr_hair_pocolov.lpmod:1-3 établi
Pocolov refusé et coché par défaut ...\P10\Windows\LifePlay\Saved\Logs\LifePlay.log:827 (refus), :887 (« actif par defaut (MODULE_DEFAULT_ENABLED), ajoute a la liste des mods ») établi

3. Mécanisme retenu, stabilité

  • Ticker FTSTicker à chaque image (0.f, comme LPSettingsSubsystem.cpp:437), ajouté seulement si au moins un mod est refusé. Recherche par TObjectIterator<UScrollBox> (requête par classe, UObjectIterator.h:251-265) de ModScrollBox dont le propriétaire est un ModManager* au viewport (UWidget::IsInViewport) de cette instance de jeu : une instance fermée (en attente de GC) est écartée.
  • Pour chaque enfant ModuleTick* : variable Blueprint UniqueID lue par réflexion (FStrProperty), recherchée dans une table RefusedTips construite à l'initialisation depuis FLPModGuard::GetVerdicts() (clés : nom du plugin et MODULE_UNIQUEID du .lpmod ; FString : égalité et hachage sans casse, UnrealString.h.inl:910-912, :2129-2132, comme le EqualEqual_StriStri du Blueprint).
  • Stabilité : les marques sont des propriétés UMG des objets (Text, ColorAndOpacity, bIsEnabled, ToolTipText), réappliquées à toute reconstruction Slate (UserWidget.cpp:406-422, Widget.cpp:321-333, :526-536, TextBlock.cpp:469-478). Tri = mêmes objets → marques conservées ; réouverture = nouveaux objets → marqués à la première image. Le Blueprint n'écrit NameText qu'à la création (avant l'ajout à la liste) : pas d'écrasement constaté.
  • Le marquage a lieu entre deux images (ticker), jamais au milieu de l'exécution Blueprint qui remplit la liste.

4. API moteur lues (UE 5.8.3, D:\Game\Launcher\Engine\UE_5.8\Engine\Source)

API Source
UWidget::IsInViewport (vrai si ajouté par AddToViewport) Runtime/UMG/Public/Components/Widget.h:547-549, Private/Components/Widget.cpp:344-354 ; AddToViewport → sous-système UserWidget.cpp:1366-1378, drapeau Blueprint/GameViewportSubsystem.cpp:158, :214
UWidget::SetIsEnabled, SetToolTipText, GetGameInstance Widget.h:545, :556, :871 ; Widget.cpp:321-333, :526-536
UUserWidget::SetColorAndOpacity (« affects all child widgets »), GetColorAndOpacity, GetWidgetFromName Blueprint/UserWidget.h:1050-1061, :1426 ; UserWidget.cpp:427-441, :1259-1262 ; réappliqué :406-422
UTextBlock::GetText, SetText Components/TextBlock.h:95, :103 ; TextBlock.cpp:457-478
UPanelWidget::GetChildrenCount, GetChildAt Components/PanelWidget.h:28, :36
Infobulle : chemin sous le curseur y compris widgets désactivés, de la feuille vers la racine, 1ʳᵉ infobulle non vide Runtime/Slate/Private/Framework/Application/SlateUser.cpp:1350-1386
FStrProperty : en-tête UObject/StrProperty.h (inclus par UnrealType.h seulement si UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_7, UnrealType.h:7806-7816 ; la copie 5.8 est en Unreal5_8, Source/LifePlay.Target.cs:12) ; GetPropertyValue_InContainer CoreUObject/Public/UObject/StrProperty.h:1-19, StrProperty.h.inl:27-29, UnrealType.h:1663 ; existe aussi en 5.5 (UE_5.5/.../UObject/StrProperty.h)
FName comparé à const TCHAR* Core/Public/UObject/NameTypes.h:1362, :1413-1417 (précédent du fichier : RowNames[0])
constexpr FLinearColor, operator== Core/Public/Math/Color.h:130, :332 ; précédent moteur Developer/LogVisualizer/Private/SVisualLoggerFilterWidget.h:133
FTSTicker::RemoveTicker sans effet sur une poignée vide Core/Private/Containers/Ticker.cpp:39-58 (Handle.Pin() nul)

5. Modifications par fichier (numéros après modification)

Fichier (EOL) Lignes Modification
Source/LifePlay/LPModInfoSubsystem.h (LF) 17-21 En-tête : 4ᵉ rôle du sous-système (gestionnaire de mods, aucun Blueprint modifié)
idem 31 class UScrollBox;
idem 60-61 bool TickModManager(float DeltaTime);
idem 71-77 RefusedTips, ManagerTickHandle, ManagerList (faible), bManagerListLogged, bWarnedNoUniqueId
Source/LifePlay/LPModInfoSubsystem.cpp (LF) 25 #include "UObject/StrProperty.h"
idem 84-118 LPModInfoUi : noms ModScrollBox / ModManager / ModuleTick, suffixe, teinte RefusedTint (0.75, 0.28, 0.28, 0.9), MarkRefusedRow (teinte, infobulle, suffixe si absent, case désactivée ; faux si déjà marquée)
idem 151-172 Initialize : table RefusedTips (raisons FLPModVerdict::Reasons jointes par « ; »), ticker par image seulement si la table n'est pas vide
idem 178 Deinitialize : retrait du ticker
idem 318-383 TickModManager : liste à l'écran, lignes, UniqueID, marquage, Warning unique si UniqueID absent, ligne Display

Rien d'autre : LPSettingsSubsystem.cpp, LPModGuard.*, Blueprints, Build.cs inchangés (UMG et CoreUObject déjà en dépendance). Correctifs UE4 (LPStringCompat, LPMeshCompat, LPNavigationHelpers…) non touchés.

6. Diff, fins de ligne, contrôles statiques

T9 seul (état T7 copié avant modification dans %USERPROFILE%\AppData\Local\Temp\claude\D--Game-LifePlay-master-5-5\ab8918a1-261f-45b4-904a-678ecfce98f7\scratchpad\t9\avant\, diffs ..\T9_LPModInfoSubsystem.cpp.diff 165 lignes, ..\T9_LPModInfoSubsystem.h.diff 47 lignes) :

git diff --no-index --stat <avant>/LPModInfoSubsystem.cpp Source/LifePlay/LPModInfoSubsystem.cpp   1 file changed, 128 insertions(+)
git diff --no-index --stat <avant>/LPModInfoSubsystem.h   Source/LifePlay/LPModInfoSubsystem.h     1 file changed, 16 insertions(+), 1 deletion(-)

git -C "D:\Game\LifePlay-master 5.8" diff --stat (cumul U7 contre HEAD) :

 Config/DefaultGame.ini                   |   2 +-
 Source/LifePlay/LPHairstyleSubsystem.cpp |  13 ++
 Source/LifePlay/LPHairstyleSubsystem.h   |   2 +
 Source/LifePlay/LPModDailies.cpp         |   7 +
 Source/LifePlay/LPModDailies.h           |   2 +
 Source/LifePlay/LPModInfoSubsystem.cpp   | 332 ++++++++++++++++++++++++++-----
 Source/LifePlay/LPModInfoSubsystem.h     |  36 +++-
 Source/LifePlay/LPSettingsSubsystem.cpp  |   5 +
 Source/LifePlay/LifePlay.cpp             |  15 +-
 9 files changed, 361 insertions(+), 53 deletions(-)

(avant T9 : LPModInfoSubsystem.cpp | 208, .h | 21, total 220+/55− ; seules ces deux lignes changent.) git status --short : 9 M + 2 ?? (LPModGuard.*, T7), inchangé en nombre ; copie 5.5 : vide ; addon 5.8 : M Tools/BuildMod.ps1 (T7).

Fins de ligne relues octet par octet (Python, count(b'\n'), count(b'\r\n'), octets > 127) :

Fichier Avant T9 Après T9 Non-ASCII BOM Fin de fichier
LPModInfoSubsystem.cpp LF 314 / CRLF 0 LF 442 / CRLF 0 0 = 0 non LF
LPModInfoSubsystem.h LF 63 / CRLF 0 LF 78 / CRLF 0 2 = 2 (§ l. 1) non LF

Noms nouveaux uniques dans Source/ (grep -rln "MarkRefusedRow\|TickModManager\|RefusedTint\|NotLoadedSuffix\|ManagerListName" → les 2 fichiers seulement) ; tout dans l'espace de noms nommé LPModInfoUi (pas de collision unity).

7. Journal attendu (jeu cuit, Pocolov 5.5 dans Mods/)

Démarrage, inchangé (T7) : Modules : lpr_hair_pocolov refuse : moteur : conteneur 4 (jeu 5), registre 17 (jeu 24) ; …, puis … non charge : 1 pak(s) demonte(s) …, puis la fenêtre Modules : fenetre d'avertissement, 1 mod(s) refuse(s). Nouveau, une fois par ouverture du gestionnaire :

LogLifePlay: Display: Modules : gestionnaire, 1 mod(s) refuse(s) marque(s)

Aucune ligne au tri (▲/▼) ni aux images suivantes. Ne doivent pas apparaître : Modules : gestionnaire, variable UniqueID absente de ModuleTick_C … (Warning : lignes non marquées) ; … 0 mod(s) … alors que Pocolov est dans la liste (clé UniqueID non reconnue). Sans mod refusé : aucune ligne « gestionnaire ».

8. Plan d'essai (après BUILD par lp-builder et empaquetage ; jeu de référence LifePlay_Build_5.8_U7_P10)

Le jeu P10 est empaqueté : le code T9 n'y est pas. Compilation .\Tools\Build.ps1 -Lot U7, puis empaquetage Development (Tools\BuildDebug.ps1) vers un dossier neuf (ex. LifePlay_Build_5.8_U7_P11) avec le même Mods\lpr_hair_pocolov (cuit 5.5) et le même Content\Modules\lpr_hair_pocolov. Sauvegardes du joueur mises de côté comme en P10.

  1. Lancer ; fenêtre « Mod compatibility warning » → OK (non-régression T7).
  2. Écran titre → Mod Manager. Attendu : « Pocolov Hairstyles (not loaded) », ligne teintée rouge atténué, case grisée dans l'état choisi (cochée ici), auteur inchangé ; les autres lignes inchangées. Capture même cadrage que la capture utilisateur.
  3. Survol de la ligne (nom ou case) : infobulle Not loaded: built with an older engine (format 4, game 5): rebuild the mod for LifePlay 2026.10.2.0 ; le panneau de détail montre toujours le .lpmod (survol Blueprint intact).
  4. Clic sur la case : sans effet. Clic sur le nom : noter si la coche change (point ouvert § 9.6).
  5. ▲/▼ sur Pocolov puis sur une autre ligne : marque conservée, pas de double suffixe, aucune nouvelle ligne de journal.
  6. Confirm, rouvrir : marque présente dès l'ouverture, une nouvelle ligne Display, pas de double suffixe.
  7. Relancer le jeu : Pocolov toujours dans la liste avec le choix laissé (ModEnableds non modifié par le C++).
  8. Journal : compter Modules : gestionnaire (= nombre d'ouvertures) ; aucun Warning « UniqueID absente ».
  9. Non-régression sans mod refusé : Mods\lpr_hair_pocolov déplacé (vers Backup_5.5\U7) → gestionnaire normal, aucune ligne « gestionnaire ». Ne pas lever le contrôle Moteur avec Pocolov 5.5 (plantage T4).

9. Écarts à la fiche et points ouverts

  1. Identification : FLPModGuard::GetVerdicts() au lieu de IsRefused(<id>) (même source, donne aussi les raisons de l'infobulle) ; clé double nom du plugin + MODULE_UNIQUEID (la ligne porte MODULE_UNIQUEID, la garde le nom du plugin ; égaux pour Pocolov, établi § 2).
  2. Infobulle : préfixe « Not loaded: » devant les raisons jointes par « ; » (repli « see the mod compatibility warning » si la liste était vide, cas non attendu).
  3. Teinte appliquée à toute la ligne (UUserWidget::SetColorAndOpacity : texte, case, flèches), pas seulement au texte.
  4. Ligne de journal écrite aussi avec N = 0 à l'ouverture (diagnostic) ; Warning unique ajouté si UniqueID manque.
  5. Ticker dédié par image, enregistré seulement s'il y a un mod refusé ; le ticker 0,5 s existant est inchangé.
  6. Point ouvert : le clic sur le nom (HoverButton, estimé § 2) appelle toujours GI.ToggleMod : le joueur peut encore changer son choix enregistré, et la case désactivée suivrait la liaison. Rien n'est chargé pour autant (garde au démarrage). Options si l'orchestrateur veut l'empêcher : (a) laisser ainsi (choix du joueur, recommandé) ; (b) HoverButton->SetIsEnabled(false) (perte probable du survol qui affiche le .lpmod, à vérifier) ; (c) retirer le délégué Blueprint OnClicked de la ligne (intrusif). Non fait sans décision.
  7. Observation hors périmètre : LPHairstyleSubsystem ajoute un mod refusé à la liste des mods actifs par défaut (MODULE_DEFAULT_ENABLED, journal P10 l. 887) : c'est pourquoi Pocolov apparaît coché.

10. Compte rendu (sk-protocol)

[sk-protocol] Skills présents : sk-protocol, ue-cpp-build, lp-build, lp-ue-compat.

  1. Résultat : réussi (PASS-STATIC proposé, non compilé) ; 2 fichiers modifiés, aucun Blueprint.
  2. Preuves : § 2 (relevés etat/), § 4 (sources moteur 5.8 fichier:ligne).
  3. Chiffres : T9 = +128 (.cpp), +16/−1 (.h) (git diff --no-index --stat) ; EOL LF conservées (442 et 78 lignes, 0 CRLF).
  4. Incertitudes : identité du 2ᵉ événement (HoverButton) et liaison de la case : estimées ; rendu (teinte, infobulle) : à voir en jeu (§ 8) ; compilation non faite.
  5. Écarts : § 9 ; fichiers écrits : D:\Game\LifePlay-master 5.8\Source\LifePlay\LPModInfoSubsystem.cpp, D:\Game\LifePlay-master 5.8\Source\LifePlay\LPModInfoSubsystem.h, ce livrable.
  6. Suite : lp-builder doit compiler la copie 5.8 (.\Tools\Build.ps1 -Lot U7) puis empaqueter pour l'essai § 8, état : code T9 écrit, non compilé, non commité.