LifePlay-Revival/Docs/Migration/etat/REL/STM1/STM1-SPEC-01.md
edujiro5972 56dfcfc3d2 LifePlay UE 5.8 : état de développement au 2026-10-20
Tickets : PUB-20261020-T1

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 17:35:10 +02:00

12 KiB

Fiche STM1-SPEC-01 — Niveau N2 — Modèle prévu opus medium | utilisé claude-opus-5-5 — Agent session « Medium · STM1 » (pas de sous-agent) — Skills sk-protocol, lp-ue-compat (lus en CART-01)

STM1-SPEC-01 : trace en jeu du choix de la ville (F3, option O1) (2026-10-20)

Ordre : Big Boss (local_104ff22d), 2026-10-20. Décision de l'utilisateur citée par Big Boss (session Big Boss, 04:30) : « pour street map on prépare la trace en jeu pour vérifier le pb puis on fournis une buil de développment pour les fixes en cours. La build sera générée une fois que l'on auras complété toutes les opérations ». Contrainte de Big Boss : GI.uasset ne sera révisé qu'une fois, en B2 (décision CG2 de 04:00) ; trace hors GI de préférence. SPEC rédigée sans copie UE ni MCP ; aucun fichier du projet modifié.

Résultat : SPEC prête, trace entièrement hors GI. Elle tient en C++ du module LifePlay : un sous-système neuf qui lit le GI par réflexion, sans l'écrire, et une ligne de journal ajoutée dans LPAssetRegistryHelpers. Elle s'appuie aussi sur les PrintString déjà présents dans MoveCity, qui écrivent au journal en Development. Aucun asset touché, ni Blueprint ni plugin StreetMap. Aucune lecture MCP préalable n'est nécessaire.

1. Ce que la trace doit trancher

D'après STM1-CART-02 § 1 (M1-M5), la carte tombe sur 000Dummy par l'un de ces chemins. Chacun doit laisser une signature distincte :

Chemin Signature attendue dans la trace
C1 : démarrage resté sur la ville factice (AutoLoad(Dummy=true), pas de MoveCity suivant) POSE … Static/000Dummy sans DEMANDE d'une autre ville ensuite
C2 : nom de ville sauvegardé introuvable (GetCityByName vide) SAUVEGARDE ville='X' … AUCUNE correspondance, puis RESOLUTION '/Game/Heavy/StreetMap/' … ECHEC (chemin par defaut de City)
C3 : chemin résolu en échec, puis repli sur Cities[0] RESOLUTION '<chemin ville>' ECHEC, puis LogBlueprintUserMessages … NOT VALID, puis POSE de Cities[0]
C4 : autre cause (ville bien demandée et trouvée, mais mauvais maillage posé) DEMANDE et RESOLUTION OK de la bonne ville, mais POSE d'un autre maillage

2. Forme

  • Journal seulement, rien à l'écran. Catégorie dédiée LogLPCity, verbosité Log, préfixe [LPCity] et une ligne par événement. Visible dans Saved/Logs/LifePlay.log en Development et en PIE. Absente du Shipping : corps sous #if !UE_BUILD_SHIPPING, et journalisation désactivée en Shipping par défaut.
  • Sur changement seulement : chaque valeur suivie n'est écrite que quand elle change. Le coût reste négligeable : une lecture par réflexion toutes les 0,25 s.
  • Toujours active en Development, sans option de ligne de commande. Une commande console LP.CityTrace écrit l'état courant à la demande.
  • Les PrintString / PrintText existants de MoveCity (nom de ville, NOT VALID, Cast To Static Mesh Succeeds) sont déjà écrits dans LogBlueprintUserMessages en Development. Ils s'affichent aussi à l'écran, comme aujourd'hui : on ne les modifie pas (ils sont dans le GI). Preuve : UE_5.8/Engine/Source/Runtime/Engine/Private/KismetSystemLibrary.cpp, PrintString, garde #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) || USE_LOGGING_IN_SHIPPING ; nœuds : etat/ST/STB/dumps/GI__EventGraph.txt:17775 ('NOT VALID', bPrintToLog = 'true'), etat/ST/STE/dumps/GI__EventGraph_P2.txt:16510-16570.

3. Points de mesure et emplacement

T1. Résolution des chemins de ville : Source/LifePlay/LPAssetRegistryHelpers.cpp (modification)

MoveCity résout StreetMapName et StaticMeshName par ULPAssetRegistryHelpers::GetAssetByObjectPath (CART-02 M2, GI__EventGraph_P2.txt:12245-12275). C'est le seul passage obligé de chaque changement de ville : on le trace ici.

  • Si ObjectPath commence par /Game/Heavy/StreetMap : à chaque appel, sans le dédoublonnage actuel (qui ne garde que le premier échec), UE_LOG(LogLPCity, Log, TEXT("[LPCity] RESOLUTION '%s' -> %s%s"), Chemin, OK|ECHEC, Etiquette) avec :
    • Etiquette = (chemin par defaut de City : ville non trouvee) si le chemin finit par / (/Game/Heavy/StreetMap/ ou .../Static/, valeurs par défaut de la structure City, CART-02 M1) ;
    • (ville factice) si le chemin contient 000Dummy ;
    • vide sinon.
  • Les autres chemins (corps, vêtements, coiffures) gardent le comportement actuel, sans changement.
  • L'avertissement GetAssetByObjectPath ECHEC existant (LPAssetRegistryHelpers.cpp:25-36) reste tel quel.

T2. Sous-système ULPCityTraceSubsystem : Source/LifePlay/LPCityTraceSubsystem.h / .cpp (nouveaux)

Un UGameInstanceSubsystem, sur le modèle de LPDebugSubsystem et LPDirectControlSubsystem. Ticker FTSTicker à 0,25 s créé dans Initialize et retiré dans Deinitialize. Lecture par réflexion comme DirectActor (LPDirectControlSubsystem.cpp:148-152) et FScriptArrayHelper (:217). Lecture seule : aucune écriture dans le GI, aucun appel de fonction Blueprint.

Id Valeur lue Chemin de réflexion (noms établis par les dumps) Ligne écrite (au changement)
T2a Liste des villes GI.Cities (tableau de City) une fois, dès que la liste n'est plus vide : [LPCity] CITIES n=<N> [0]='<DisplayName>' sm='<StreetMapName>' mesh='<StaticMeshName>' ; CentralLondon a l'indice <i|absent>
T2b Ville sauvegardée GI.SaveGameInstance → propriété City (lue par ExportTextItem, quel que soit son type) [LPCity] SAUVEGARDE ville='<X>' -> trouvee indice <i> ('<DisplayName>') ou -> AUCUNE correspondance (GetCityByName rendra la City par defaut)
T2c Ville demandée GI.CityToMoveTo (struct City) [LPCity] DEMANDE '<DisplayName>' sm='<StreetMapName>' mesh='<StaticMeshName>'
T2d Données StreetMap posées GI.StreetMapStatic → propriété StreetMap (objet UStreetMap) [LPCity] STREETMAP <chemin de l'objet|None>
T2e Maillage affiché GI.StreetMapStatic → propriété StaticMeshComponent → GetStaticMesh() [LPCity] POSE <chemin du maillage|None> (t=<s depuis le demarrage>)

Règles d'écriture :

  • Les membres de City portent un suffixe de GUID (DisplayName_2_EBDEAF…, StreetMapName_26_C43E02…, StaticMeshName_28_61293D…, etat/portage55/L6f/L6f_dump_GI.txt:25637-25647). On les cherche par préfixe (DisplayName_, StreetMapName_, StaticMeshName_), pas par nom complet.
  • T2b reproduit GetCityByName (L6f_dump_GI.txt:25623-25660) : comparaison insensible à la casse (ESearchCase::IgnoreCase) entre la ville sauvegardée et DisplayName converti en chaîne. On ne fait que la constater ; le GI garde sa propre logique.
  • Propriété introuvable (le GI a pu changer depuis les dumps du 9-10 octobre) : une ligne [LPCity] PROPRIETE ABSENTE <classe>.<nom> une seule fois, puis on saute ce point de mesure. La trace se signale elle-même, sans plantage.
  • Commande console LP.CityTrace : écrit d'un coup T2a à T2e, plus GI.Cities.Num().

T3. Catégorie de journal : Source/LifePlay/LifePlay.h / LifePlay.cpp (modification)

LIFEPLAY_API DECLARE_LOG_CATEGORY_EXTERN(LogLPCity, Log, All); à côté de LogLifePlay (LifePlay.h:9), et DEFINE_LOG_CATEGORY(LogLPCity); dans LifePlay.cpp. Une seule définition : pas de DEFINE_LOG_CATEGORY_STATIC répété, qui entrerait en conflit dans un même fichier unity.

4. Pourquoi hors GI, et l'option GI chiffrée

Option Ce qu'elle voit Coût Risque
S1 (retenue par cette SPEC) : C++ (T1 + T2 + T3) toutes les signatures C1-C4 : ville sauvegardée, correspondance, ville demandée, chemins résolus, maillage posé 2 fichiers neufs (~200 lignes), 3 fichiers modifiés (~25 lignes), une compilation de LifePlay faible : lecture seule, sans asset ; se signale si un nom de propriété manque
S2 : plugin StreetMap rien d'utile : le plugin ne connaît ni le GI ni le StaticMeshComponent de la carte (CART-01 § 1) — —
S3 : nœuds PrintString dans le GI (AutoLoad : valeur de Dummy ; GetCityByName : sortie trouvée ou vide ; MoveCity : branches) en plus de S1 : la valeur exacte de Dummy et la branche prise sans déduction ~8-12 nœuds par MCP (lp-mcp-bp), sauvegarde du GI (52,7 Mo), CompileAllBlueprints, VAL ; seulement dans la révision unique B2, sinon une seconde révision du GI moyen : touche le gros Blueprint partagé ; inutile si S1 suffit
S4 : PC.uasset (BeginAutoLoad(Dummy) est un événement du PC, etat/ST/STE/dumps/PC__EventGraph.txt:2762-2766) la valeur de Dummy au démarrage 1-2 nœuds, sauvegarde du PC, VAL faible à moyen ; seulement si S1 laisse C1 ambigu

Les crochets du moteur sur l'exécution Blueprint (FBlueprintCoreDelegates::OnScriptProfilingEvent, UE_5.8/.../CoreUObject/Public/UObject/Script.h:455) exigent des Blueprints instrumentés (profilage éditeur) : ils ne sont pas fiables dans une build cuite (estimé), donc écartés. Le GI dérive de /Script/Engine.GameInstance et non d'une classe C++ du projet (grep -a sur Content/BPs/GI.uasset) : on ne peut pas surcharger ProcessEvent côté projet.

5. Lecture MCP préalable : non nécessaire

Les noms utilisés (Cities, CityToMoveTo, StreetMapStatic, SaveGameInstance, City, StreetMap, StaticMeshComponent, préfixes des membres de City) sont établis par les dumps STB, STE et L6f. S'ils ont changé (CG2, B2), la trace écrit PROPRIETE ABSENTE au lieu de mentir. La lecture MCP de CART-02 § 4 reste utile pour interpréter le résultat (ordre de Cities), pas pour poser la trace.

6. Déroulé proposé (lp-lot), sous le jeton UE quand il sera libre

  1. IMPL (lp-impl, N3) : T3, T1, T2 sous instantané Tools/Snapshot.ps1, entrée CHG, aucun asset.
  2. BUILD (lp-builder) : Tools/Build.ps1, éditeur Development ; 0 erreur, 0 avertissement nouveau.
  3. VAL (lp-validator) : en PIE ou par un commandlet de démarrage, puis grep "\[LPCity\]" Saved/Logs/LifePlay.log. Attendu au minimum : CITIES n=… (au moins une ligne) et POSE …/000Dummy au démarrage ; 0 ligne PROPRIETE ABSENTE ; rien de nouveau à l'écran ; build Shipping sans symbole LPCityTrace (corps exclu). Diff relu : aucune écriture par réflexion.
  4. Livraison dans la build Development commune, générée après toutes les opérations en cours (décision de l'utilisateur).
  5. L'utilisateur joue jusqu'au symptôme et transmet le journal. Lecture : la signature C1-C4 du § 1 désigne le correctif (SPEC suivante).

7. Critères d'acceptation

# Critère Preuve attendue
A1 Aucun fichier Content\ ni Plugins\ modifié git status --short -- Content Plugins vide
A2 Compilation Development sans erreur ni avertissement nouveau résumé Tools/Build.ps1
A3 Lignes [LPCity] présentes en Development : CITIES et POSE au minimum grep -c "\[LPCity\]" ≥ 2 sur un journal PIE
A4 Rien de nouveau à l'écran essai visuel ou absence d'appel à AddOnScreenDebugMessage dans le diff
A5 Absent du Shipping #if !UE_BUILD_SHIPPING autour du corps, relu dans le diff
A6 Lecture seule du GI diff : seulement GetObjectPropertyValue, ContainerPtrToValuePtr en lecture, ExportTextItem

8. Incertitudes, écarts, fichiers

  • Incertain : le type exact de Save.City (chaîne ou texte). ExportTextItem couvre les deux. Il reste aussi à confirmer que CityToMoveTo est bien posé à chaque MoveCity (VariableSet_4974, GI__EventGraph_P2.txt:12289-12294, sur deux branches seulement). T1 et T2e couvrent le cas où T2c manque un changement.
  • Non mesuré : rien (SPEC). Aucun fichier du projet modifié.
  • Fichiers écrits : D:\Game\LifePlay-master 5.8\Docs\Migration\etat\REL\STM1\STM1-SPEC-01.md (A) ; STM1-TACHES.md (M).

Tours : ≈ 9 / 40 (déclaré ; FicheStats.py fait foi).

À verser : lp-mcp ou lp-commandlets — en Development, les PrintString/PrintText des Blueprints écrivent dans LogBlueprintUserMessages (garde !(SHIPPING||TEST)) : un graphe déjà bavard se trace par le journal, sans toucher au Blueprint.

Suite : Big Boss doit ouvrir l'IMPL STM1 (T1-T3, C++ seul) dans la file du jeton UE, avant la build Development commune. État : SPEC close, aucun fichier du projet modifié.