LifePlay-Revival/Docs/Migration/07_Architecture_5.5.md

186 lines
13 KiB
Markdown
Raw Normal View History

# 07 — Architecture de LifePlay en UE 5.5 (état final de la migration)
> Complète `01_Architecture_Initiale.md`, qui décrit le fonctionnement hérité de 4.27 (données texte,
> `ModdingExtra`, interpréteur du DSL dans `GI`). Ce document décrit ce que la migration a ajouté ou
> appris : la couche de compatibilité C++, les sous-systèmes, les différences de comportement du
> moteur et le fonctionnement de la scène (studio, pièces, écran d'appel), mesurés en jeu.
> État au 2026-10-02 : V1.1 publiée, lots L7a à L7l validés.
---
## 1. Vue d'ensemble
```
Content/Modules/** (texte, hors paquet) inchangé depuis 4.27 (2 051 fichiers, MD5 identiques)
│
Plugins/ModdingExtra LoadTxt / SaveTxt / GetAllFilesFromFolder (porté UE5, trace en Verbose)
│
Content/BPs/GI ── interpréteur du DSL, événements, personnages, sauvegarde (Blueprints 4.27,
│ Person, Room, AI, UI/* resauvegardés UE5)
│
│ appels Blueprint redirigés vers la couche de compatibilité (nœuds rebranchés par commandlet)
▼
Source/LifePlay ── bibliothèques de compatibilité (comportement 4.27 garanti)
│ LPStringCompat · LPMeshCompat · LPNavigationHelpers
│ LPAssetRegistryHelpers · LPVictoryCompat
│
└── sous-systèmes d'instance de jeu (aucun Blueprint modifié)
LPSessionLog (journal, diagnostic) · LPSecondScreen (caméra d'appel)
LPOutdoorRoom (plafond des lieux extérieurs)
Source/LifePlayEditorTools ── commandlets d'analyse et de correction (éditeur uniquement)
Plugins/StreetMap (280 villes, porté LWC) Plugins/McpAutomationBridge (éditeur uniquement)
```
Principe directeur : **les Blueprints de gameplay restent ceux de 4.27**. Chaque écart de comportement
du moteur est corrigé soit en rebranchant des nœuds vers une fonction C++ qui reproduit le comportement
4.27 (corrections « CX-B »), soit par un sous-système C++ qui agit à l'exécution sans toucher aux
assets.
## 2. Modules C++
### 2.1 `Source/LifePlay` (runtime, livré avec le jeu)
| Classe | Type | Rôle | Introduit par |
|---|---|---|---|
| `ULPAssetRegistryHelpers` | bibliothèque Blueprint | `GetAssetByObjectPath` en nœud **pur** (le moteur l'a rendu impur) ; `GetAssetsByClassName`, `GetAssetObjectPath` (paramètre `FName` → `FTopLevelAssetPath`) | portage 4.27 ; CX-B01 |
| `ULPVictoryCompat` | bibliothèque Blueprint | les 2 nœuds du Victory Plugin réellement utilisés (`LoadTexture2D_FromFile`, `SaveStringToOSClipboard`) ; `[CoreRedirects]` dans `DefaultEngine.ini` | CX-C06 |
| `ULPStringCompat` | bibliothèque Blueprint | `ParseIntoArray`, `Contains`, `Split`, `FindSubstring`, `FindUE4` avec la sémantique **UE 4.27** (§4) | CX-B08, CX-B12 |
| `ULPMeshCompat` | bibliothèque Blueprint | `GetSkeletalMesh(Component)` = `Cast<USkeletalMesh>(GetSkinnedAsset())`, valable pour tout `USkinnedMeshComponent` (les proxys de `Person` n'en sont pas des `USkeletalMeshComponent`) | CX-B10 |
| `ULPNavigationHelpers` | bibliothèque Blueprint | `GetRandomLocationInNavigableRadius` en nœud **pur** (le remplaçant moteur est impur) | CX-B11 |
| `ULPSessionLogSubsystem` | `UGameInstanceSubsystem` | résumé de démarrage, bilan de session dédoublonné, outils de diagnostic sur option de ligne de commande (§5) | L3, L5, L7i, L7l |
| `ULPSecondScreenSubsystem` | `UGameInstanceSubsystem` | à chaque image, cadre la caméra `SecondScreen` sur le visage du contact affiché (`GI.SecondScreenPerson`) | L7j (ERR-031) |
| `ULPOutdoorRoomSubsystem` | `UGameInstanceSubsystem` | masque le plafond `WallT` de la pièce quand l'échelle Z de sa racine est < 0,05 (lieux extérieurs) | L7l (ERR-036) |
| `ALifePlayGameModeBase` | — | vide ; le vrai mode de jeu est `/Game/BPs/GM` | 4.27 |
Dépendances (`LifePlay.Build.cs`) : publiques `Core`, `CoreUObject`, `Engine`, `InputCore`,
`AssetRegistry`, `NavigationSystem` ; privées `ImageWrapper`, `ApplicationCore`, `EngineSettings`.
Structure plate (pas de sous-dossier `Public/`) : `PublicIncludePaths.Add(ModuleDirectory)`.
### 2.2 `Source/LifePlayEditorTools` (éditeur uniquement)
24 commandlets, en trois familles (catalogue et usages : `08_Guide_Developpeur.md` §5) :
- **analyse en lecture seule** : `LPDumpFunction`, `LPDumpAssets`, `LPDumpComponents`,
`LPDumpWidgetTree`, `LPDumpCDO`, `LPDumpSave`, `LPCheckMeshAssignment`, `LPCheckStreetMap`,
`LPCheckMeshes`, `LPTestStringCompat` ;
- **correction de graphes** (rebranchement de nœuds, contrôle broche par broche intégré, `-DryRun`) :
`LPFixAssetRegistryNodes`, `LPFixAssetRegistryPins`, `LPFixEditableTextBoxFont`,
`LPFixOrphanBoundEvents`, `LPFixParseIntoArray`, `LPFixButtonPadding`, `LPFixSkeletalMeshGet`,
`LPFixNavRandomPoint`, `LPFixStringSearch` ;
- **correction de cartes ou de paquets** : `LPFixZeroScaleActors`, `LPConvertAtmosphericFog`,
`LPFixSceneCapture`, `LPResavePackages`.
`LPFixDeprecatedNodes` (R-03/R-04 d'origine) est conservé pour l'historique mais **ne doit plus
être utilisé** : sa variante R-03 aggrave ERR-002 (CX-B05 rejeté), sa variante R-04 est remplacée par
`LPFixNavRandomPoint`.
### 2.3 Plugins
| Plugin | Cible | Remarque |
|---|---|---|
| `ModdingExtra` | runtime | entrée/sortie des données ; trace d'appel en catégorie `LogModdingExtra` (`Verbose`) |
| `StreetMap` | runtime | porté LWC ; 280 villes vérifiées identiques à 4.27 (L7h) |
| `EnhancedInput` | runtime | système d'entrée actif ; exécute les 34 actions héritées de `DefaultInput.ini` |
| `McpAutomationBridge` | **éditeur uniquement** (`TargetAllowList: Editor`) | pilotage de l'éditeur par serveur MCP ; jamais publié (contient un jeton) |
| `AndroidFileServer` | désactivé | réécrivait un `SecurityToken` dans `DefaultEngine.ini` (ERR-023) |
## 3. Configuration (écarts à 4.27)
| Fichier | Clé | Valeur | Raison |
|---|---|---|---|
| `DefaultGame.ini` | `+DirectoriesToAlwaysCook=(Path="/Game")` | — | assets chargés par chemin texte : sans cela, 3 257 paquets cuits au lieu de 8 561 (ERR-026) |
| `DefaultGame.ini` | `DirectoriesToAlwaysStageAsNonUFS=Modules`, `UsePakFile=False` | inchangés | `Modules` en fichiers nus, comme la version de l'auteur |
| `DefaultGame.ini` | clés de nativisation | retirées | inexistantes en UE5 (L7c) |
| `DefaultEngine.ini` | `r.DynamicGlobalIlluminationMethod=0`, `r.ReflectionMethod=2`, `r.Shadow.Virtual.Enable=0` | explicites | rendu identique à celui validé, indépendant des valeurs par défaut du moteur (L7c) |
| `DefaultEngine.ini` | `DefaultGraphicsRHI_DX12` | explicite | idem |
| `DefaultEngine.ini` | `r.AntiAliasingMethod=2` (TAA) | explicite (`r.DefaultFeature.AntiAliasing` est ignorée par UE5) | supprime le scintillement à l'approche des personnages (ERR-032, L6a) |
| `DefaultEngine.ini` | `[CoreRedirects]` Victory → `LPVictoryCompat` | — | chargement de `GI`, `MainMenu`, `Inventory`… |
| `DefaultEngine.ini` | 4 clés PhysX | retirées | PhysX n'existe plus (Chaos) |
| `LifePlay.uproject` | `TargetPlatforms: ["Windows"]`, plugins explicites | — | L2 |
## 4. Différences de comportement du moteur découvertes (UE 4.27 → 5.5)
Aucune n'est signalée par le compilateur : un graphe identique donne un résultat différent. Elles
expliquent l'essentiel des défauts de la migration.
| # | API | UE 4.27 | UE 5.5 | Effet dans LifePlay | Correction |
|---|---|---|---|---|---|
| 1 | `IAssetRegistry::GetAssetsByClass` | paramètre `FName ClassName` | `FTopLevelAssetPath` ; la valeur est **perdue** à la montée de version | aucun corps, vêtement, coiffure énumérable : personnages identiques (ERR-002) | CX-B01 |
| 2 | `FString::ParseIntoArray("")` | `[]` | `[""]` ; séparateur insensible à la casse | `generatePerson()` charge les 141 presets : personnages invisibles (ERR-027) | CX-B08 |
| 3 | `FString::Find("", IgnoreCase, FromStart)` | `INDEX_NONE` | `0` | `Contains(x, "")` vrai : filtres de morphs sans effet (ERR-005), erreurs en cascade (ERR-006/007) | CX-B12 |
| 4 | style par défaut de `UButton` | marge 2,2,2,2 (`FCoreStyle`) | 12,1.5,12,1.5 (`FUMGCoreStyle`) | les assets 4.27 ne stockent pas la valeur par défaut : barre de temps décalée (ERR-034) | CX-B09 |
| 5 | `USkinnedMeshComponent::SkeletalMesh` | propriété | dépréciée ; `GetSkeletalMeshAsset()` n'existe que sur `USkeletalMeshComponent` | un remplacement naïf renvoie `None` sur les proxys (CX-B05 rejeté) | CX-B10 |
| 6 | `GetAssetByObjectPath`, `K2_GetRandomLocationInNavigableRadius` | purs | impurs | un rebranchement naïf ajoute des broches d'exécution non reliées : nœud élagué | helpers purs |
| 7 | `FEditableTextBoxStyle::Font` | champ | `TextStyle.Font` | broche orpheline : cuisson en échec (ERR-021) | CX-B02 |
| 8 | `AAtmosphericFog` | classe active | dépréciée, convertie en `SkyAtmosphere` au chargement | aucun changement visible | L7d (remplacement explicite) |
| 9 | Shipping (`NO_LOGGING`) | — | les catégories de journal deviennent `FNoLoggingCategory` sans `GetCategoryName` | compilation Shipping en échec | `FName` constant (L7g) |
Leçon générale : **une propriété sérialisée en delta prend silencieusement la nouvelle valeur par
défaut du moteur** (#4), et **une fonction de chaîne peut changer de sémantique sur les cas limites**
(#2, #3). Comparer les sources du moteur 4.27 et 5.5 sur ces cas avant de conclure.
## 5. Journalisation et diagnostic (`ULPSessionLogSubsystem`)
Le sous-système n'altère aucun message existant (les comparaisons A/B avec 4.27 en dépendent). Il
ajoute :
- au démarrage : `===== LifePlay : demarrage =====` (versions, modules, fichiers par type, échecs
`LoadTxt`) ;
- à la fermeture ou par la commande console `LifePlay.LogSummary` : `===== LifePlay : bilan de
session` (volume par catégorie, signatures d'erreurs dédoublonnées) ;
- des outils activés par la ligne de commande, tous inactifs par défaut (liste dans
`09_Commandes_Utiles.md` §4) : variables de `GI` au démarrage et à la fin (`-LPDumpVars`),
trace des exceptions de script avec variables locales et cadres appelants (`-LPTraceScriptEx`…),
relevé de chemins d'objets sur un motif du journal (`-LPDumpOnLog`) ou périodique
(`-LPDumpEvery`).
Un chemin de relevé part de l'instance de jeu et suit les propriétés objet ou structure :
`Room.WallT.RelativeLocation`, `PlayerCharacter.CapsuleComponent.CapsuleHalfHeight`… C'est ce qui a
permis de mesurer la cause réelle d'ERR-036 (le plafond), là où l'analyse statique des données
désignait à tort une dalle de neige.
## 6. Scène, pièces et écran d'appel (mesurés en jeu)
### 6.1 Studio unique
Tous les lieux (bâtiments, extérieurs) sont construits par **un seul acteur `Room_C_0`** placé dans un
studio, en (−3 131 543 ; −14 967 213 ; −115) de `CentralLondon`. Pendant une visite, la ville
(`StreetMapStatic`) est masquée.
### 6.2 Pièce et échelle `.lpworld`
- La racine de `Room` (cube, matériau `FntWall`) prend l'**échelle de la première ligne du `.lpworld`**.
- Les meubles sont positionnés et dimensionnés relativement à cette racine : leurs hauteurs sont donc
multipliées par l'échelle Z.
- Échelles Z déclarées : 81 lieux à 0,2, 5 à 0,3, 1 à 0,4, et **0,01 pour les 7 lieux extérieurs**
(`beach`, `forest`, `mountain`, `park`, `pool`, `river`, `street`).
- Le plafond `WallT` (Z relatif 2 040, sans collision) suit l'échelle : 4,08 m en intérieur, mais
18 à 20 cm au-dessus du sol en extérieur, où il masquait pieds et pieds de meubles (ERR-036,
défaut d'origine 4.27). `ULPOutdoorRoomSubsystem` le masque en extérieur et le rend en intérieur.
### 6.3 Écran d'appel (second écran)
- `GI::Show` place le contact sur son emplacement de scène décalé de −10 000 000 en Y, sur la copie
de scène `SecondScreenFloor`.
- La caméra `SceneCapture2D` `SecondScreen` rend vers `Render/SecondScreen`, affiché par
`UI/Scene::FaceRender`.
- Dans la carte 4.27 d'origine, cette caméra n'avait pas de racine et filmait le ciel (ERR-031,
défaut d'origine). L7j lui a donné une racine (`LPFixSceneCapture`), et
`ULPSecondScreenSubsystem` la cadre à chaque image : 80 cm devant l'os `head` du contact, champ de
30°.
### 6.4 Ciel
`BP_Sky_Sphere` (matériau `M_Sky_Panning_Clouds2`), lumière directionnelle `Sun`, `SkyLight` à
cubemap, `SkyAtmosphere` (ex-`AtmosphericFog`, Z −100 000, `PlanetTopAtComponentTransform`). Le soleil
ne suit pas l'heure : la nuit reste claire en extérieur, **comme en 4.27**. Un grand disque blanc à
l'horizon existe déjà avant L7d (origine non étudiée).
### 6.5 Variables du DSL
`GI::GetVariable` traite à part les noms spéciaux (`Player`, `Ptr`, `Interacting`, `CurrentCompanion`,
`A1` à `A5`) par un `SwitchString`. La variable `AI` est un `AIDummy`. Les variables `Person` vides
signalées en jeu (ERR-003) existent au même taux en 4.27.
## 7. Ce qui reste hérité tel quel
Effets Cascade (4 systèmes, pris en charge par UE 5.5), entrées héritées exécutées par Enhanced Input,
éclairage dynamique sans précalcul. Défauts d'origine 4.27 conservés : ERR-030 (habillage), ERR-037
(Quick dress), nuit claire, disque blanc. Voir `Registre_Erreurs.md`.