LifePlay-Revival/Docs/Migration/08_Guide_Developpeur.md
edujiro5972 2744242609 Protocole de conversion d'une coiffure (13_Protocole_Coiffure.md) et outils HairImportFbx, HairMaterials
Protocole rejoue de bout en bout sur Pocolov 17 : resultat identique.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 18:16:09 +02:00

238 lines
14 KiB
Markdown

# 08 — Guide du développeur (LifePlay UE 5.5)
> Pour reprendre le projet : installer, compiler, empaqueter, diagnostiquer et corriger sans casser
> la parité avec 4.27. Architecture : `07_Architecture_5.5.md`. Commandes prêtes à copier :
> `09_Commandes_Utiles.md`. Méthode de travail obligatoire : `10_Protocole_Operations.md`.
---
## 1. Environnement
| Élément | Valeur |
|---|---|
| Moteur | Unreal Engine **5.5.4** (Launcher) : `D:\Game\Launcher\Engine\UE_5.5` |
| Compilateur | Visual Studio 2022 (`D:\Game\VS2022`), MSVC 14.38, SDK Windows 10.0.22621 |
| Projet | `D:\Game\LifePlay-master 5.5\LifePlay.uproject` |
| Référence (lecture seule, jamais modifiée) | `D:\Game\LifePlay-master 4.27` + build `D:\Game\LifePlay_Build_427_Dev` |
| Sauvegardes de lots | `D:\Game\LifePlay_Backup_5.5\<lot>\` (hors dépôt) |
| Cache de données dérivées | `D:\DDC` (à conserver : évite des heures de recompilation de shaders) |
| Dépôt public | `github.com/edujiro5972/LifePlay-Revival` (branche `main` ; `ue5.5-v1.1` = V1.1) |
Python 3 est utile pour `Tools/DiffRemplacementNoeuds.py`. PowerShell 7 pour les scripts `Tools/*.ps1`.
## 2. Arborescence
| Chemin | Contenu | Versionné |
|---|---|---|
| `Source/LifePlay` | runtime : compatibilité 4.27, sous-systèmes | oui |
| `Source/LifePlayEditorTools` | commandlets (éditeur) | oui |
| `Plugins/ModdingExtra`, `Plugins/StreetMap` | plugins du jeu (sources) | oui |
| `Plugins/McpAutomationBridge` | pilotage MCP de l'éditeur | **non** (outil local, jeton) |
| `Config/` | `.ini` du projet | oui |
| `Content/BPs`, `UI`, `Structs`, `Scenes`, `Render`, `Characters` | Blueprints et cartes de gameplay | oui |
| `Content/Heavy` | maillages, textures, villes (plusieurs Go) | **non** (archive 7z de publication) |
| `Content/Modules` | données texte du jeu (DSL, presets) | oui |
| `Docs/Migration` | cette documentation, journal, registre, relevés `etat/` | oui |
| `Tools/` | scripts de lot, de mesure et de diff | oui |
| `Saved/Logs/portage` | journaux de parties et de commandlets archivés | non |
| `.mcp.json`, `.claude/` | configuration locale d'agent (jeton) | **jamais** |
### 2.1 Carte de `Content/Heavy` et dossiers à ne pas déplacer
Les noms de dossiers (`New`, `New2`…) viennent de l'auteur et ne disent rien de leur contenu. **Ils ne sont pas
renommés** (audit O7, `11_Audit_Optimisation.md` §16) : le jeu y construit des chemins à partir de noms lus dans les
données, et les mods en dépendent.
| Dossier | Contenu |
|---|---|
| `Heavy/Clothes4` | vêtements (940 maillages et leurs matériaux), désignés par nom dans `Modules/Clothes4.txt` |
| `Heavy/New2` | `Furniture` (meubles des `.lpworld`), `Anims2`, `Daily` (animations), `Sound`, `Hairs`, `BDSM`, `Beasts`, `Buildings` (carte de la ville) |
| `Heavy/Daz` | corps `Bridget` (femme) et `Michael` (homme) avec cheveux et pilosité, `Anims`, `Clothes` |
| `Heavy/New3` | `UI` (icônes, dont celles des morphs), `Anims`, `Hairs`, `Tattoos`, `Characters/Tanlines` |
| `Heavy/New4` | `Anims`, `Hairs`, `Misc`, `Tentacles` |
| `Heavy/Backgrounds` | images de fond |
| `Heavy/StreetMap` | 280 villes (`StreetMap`) et leurs maillages (`Static`) |
| `Heavy/Characters`, `New`, `New5` | squelette, 37 icônes, 1 animation |
**Ne jamais déplacer ni renommer** ces dossiers. Leurs préfixes sont écrits en texte dans les Blueprints :
- `New2/Furniture` (`Room`) ;
- `Clothes4` (`GI`) ;
- `StreetMap` et `StreetMap/Static` (`GI`, `UI/CityMenu`) ;
- `New3/Tattoos` (`GI`) ;
- `New3/Characters/Tanlines` (`Person`) ;
- `Daz/Bridget/Hairs/Pubic` et `Daz/Michael/hairs/other` (`GI`, `Person`) ;
- `New3/UI` (`UI/VisualMorph`) ;
- `Daz/Clothes` (`UI/Inventory_Cloth`).
`Content/Modules` cite aussi 17 chemins complets de `New2` et `New3`.
Pour chercher par thème plutôt que par dossier, utiliser les collections `LifePlay_*` du Content Browser (panneau
Collections, section locale) : animations, vêtements, meubles, cheveux, icônes, villes, sons… La collection rouge
`LifePlay_Chemins_Fixes` liste les assets à ne jamais déplacer. Après ajout d'assets, les régénérer avec
`Tools/BuildCollections.py` (lot O7d, `11_Audit_Optimisation.md` §16.5).
Coiffures et pilosité : listes décrites par les fichiers `Modules/**/*.lphair` (base : `vin_Base/Hairstyles/vin_Base.lphair`) ;
ajouter une coiffure : [`13_Protocole_Coiffure.md`](13_Protocole_Coiffure.md).
`Content/Saves` reçoit les sauvegardes des joueurs : il doit exister, mais reste vide dans le dépôt et l'archive. Les
parties de test de l'éditeur ont été déplacées vers `D:\Game\LifePlay_Backup_5.5\O7\Content_Saves` (lot O7a).
## 3. Compiler
```powershell
$UE = 'D:\Game\Launcher\Engine\UE_5.5\Engine'
$Proj = 'D:\Game\LifePlay-master 5.5\LifePlay.uproject'
& "$UE\Build\BatchFiles\Build.bat" LifePlayEditor Win64 Development -Project="$Proj" -WaitMutex
```
- **Fermer l'éditeur avant** : avec Live Coding actif, UBT refuse de compiler
(« Unable to build while Live Coding is active »).
- Le module d'outils est compilé avec `bUseUnity=false` (des fichiers concaténés entreraient en
collision) : une inclusion manquante se voit immédiatement.
- Critère : 0 erreur, aucun nouvel avertissement.
## 4. Empaqueter
```powershell
& "$UE\Build\BatchFiles\RunUAT.bat" BuildCookRun -project="$Proj" -platform=Win64 `
-clientconfig=Development -build -cook -iterate -stage -archive `
-archivedirectory=D:\Game\LifePlay_Build_5.5_<nom> -unattended -utf8output -nop4
```
- **Pas de `-pak`** : comme la version de l'auteur (`UsePakFile=False`), le jeu est livré en fichiers
nus ; `Modules` doit rester modifiable par les joueurs et les mods.
- `-clientconfig=Shipping` pour une version distribuable (ne journalise pas) ; `Development` pour
toute mesure.
- Contrôle T-PKG-01 : ≥ 8 555 `.uasset` sous `Windows/LifePlay/Content` (8 561 attendus).
- Le résultat est dans `<archivedirectory>\Windows\LifePlay.exe`.
Builds conservées (2026-10-02) :
- `LifePlay_Build_427_Dev` : référence 4.27 journalisée ;
- `LifePlay_Build_5.5_Shipping` : V1.1, version publiée précédente ;
- `LifePlay_Build_5.5_Shipping_V1.2` : V1.2, distribution ;
- `LifePlay_Build_5.5_Dev_V1.2` : Development de la V1.2, référence pour les comparaisons ;
- `LifePlay_Build_5.5_ERR038` : en test.
Les builds intermédiaires supprimées ont leurs journaux, mesures et parties sauvegardées dans
`D:\Game\LifePlay_Backup_5.5\builds_supprimees\` ; elles se reconstruisent depuis leur tag git.
## 5. Commandlets (`Source/LifePlayEditorTools`)
Lancement commun : `UnrealEditor-Cmd.exe "<projet>" -run=<Nom> <options> -unattended -nopause -nosplash`
(ou `Tools\RunCommandlet.ps1`, qui archive le journal). L'éditeur graphique doit être **fermé** pour
une commandlet qui écrit des assets.
### 5.1 Analyse (lecture seule)
| Commandlet | Options | Usage |
|---|---|---|
| `LPDumpFunction` | `-BP=<nom> [-Fn=<fonction>] [-Pins] [-Exec]` | graphe d'une fonction Blueprint ; identique sur 4.27 et 5.5 pour comparer |
| `LPDumpAssets` | `-List=<fichier>` ou `-Dirs=/Game/A,/Game/B` ; `-Out=<fichier>` | photographie complète de paquets (propriétés non par défaut, broches et liaisons) pour diff avant/après |
| `LPDumpComponents` | `-BP=<nom>` ou `-Map=<carte> -Filter=<texte>` ; `[-All]` | composants et propriétés modifiées ; révèle les changements de valeurs par défaut |
| `LPDumpWidgetTree` | `-BP=<widget>` ou `-BP=*` | arbre UMG et propriétés de slot |
| `LPDumpCDO` | `-Class=/Game/BPs/GI.GI_C -Out=<f> -Props=A,B` | valeurs par défaut d'une classe (tableaux et maps) |
| `LPDumpSave` | `-File=<.sav> -Out=<f> [-Props=A,B]` | contenu d'une sauvegarde |
| `LPCheckMeshAssignment` | — | nœuds d'affectation de maillage et broches orphelines (T-LOAD-02) |
| `LPCheckStreetMap` | `[-CSV=<f>] [-Path=/Game/…] [-Verbose]` | contenu des 280 villes |
| `LPCheckMeshes` | `-Path=/Game/… -CSV=<f>` | LOD, sommets, triangles, dimensions des maillages statiques |
| `LPTestStringCompat` | — | compare `LPStringCompat` à une transcription de `FString::Find` 4.27 |
### 5.2 Correction de graphes (toujours `-DryRun` d'abord)
| Commandlet | Correctif | Cible |
|---|---|---|
| `LPFixAssetRegistryNodes` | CX-B00 | `GetAssetByObjectPath` → version pure |
| `LPFixAssetRegistryPins` | CX-B01 | `GetAssetsByClass` : classe perdue |
| `LPFixEditableTextBoxFont` | CX-B02 | broche `Font` → `TextStyle.Font` |
| `LPFixOrphanBoundEvents` | CX-B04 | événements `On Clicked` sans widget |
| `LPFixParseIntoArray` | CX-B08 | `ParseIntoArray` → `LPStringCompat` |
| `LPFixButtonPadding` | CX-B09 | marges `UButton` → valeurs UE4 |
| `LPFixSkeletalMeshGet` | CX-B10 | `Get SkeletalMesh` → `LPMeshCompat` |
| `LPFixNavRandomPoint` | CX-B11 | `GetRandomPointInNavigableRadius` → helper pur |
| `LPFixStringSearch` | CX-B12 | `Contains`/`Split`/`FindSubstring` → `LPStringCompat` |
| `LPFixDeprecatedNodes` | (R-03/R-04 d'origine) | **ne plus utiliser** |
Toutes réappliquées à l'état actuel, elles ne trouvent plus rien (idempotentes).
### 5.3 Cartes et paquets
| Commandlet | Options | Usage |
|---|---|---|
| `LPFixZeroScaleActors` | `[-Fix "-Scale=0.1"]` | composantes d'échelle nulles (CX-B03) ; **guillemets obligatoires** sous PowerShell |
| `LPConvertAtmosphericFog` | `-Map=<carte> [-DryRun]` | `AtmosphericFog` → `SkyAtmosphere` (L7d) |
| `LPFixSceneCapture` | `-Map -Actor -From "-Offset=x,y,z" [-DryRun]` | racine et position d'une `SceneCapture2D` (L7j) |
| `LPResavePackages` | `-List=<fichier> [-DryRun]` | réenregistrement UE5 sans modification (CX-B07) |
## 6. Écrire un correctif
### 6.1 Choisir la forme
| Situation | Forme | Exemple |
|---|---|---|
| Une fonction moteur appelée par des Blueprints a changé de comportement | fonction C++ de compatibilité (mêmes broches) **+** commandlet de rebranchement | `LPStringCompat` + `LPFixStringSearch` |
| Une fonction moteur est devenue impure | enrobage pur | `LPNavigationHelpers` |
| Un défaut visible, sans changement de Blueprint souhaité | `UGameInstanceSubsystem` + `FTSTicker`, lecture des propriétés de `GI` par réflexion | `LPOutdoorRoomSubsystem`, `LPSecondScreenSubsystem` |
| Une valeur par défaut du moteur a changé | commandlet qui réécrit **uniquement** les composantes égales au nouveau défaut | `LPFixButtonPadding` |
| Une carte mal construite | commandlet `-Map=` avec vérification et sauvegarde conditionnelle | `LPFixSceneCapture` |
Préférer le sous-système quand c'est possible : aucun asset modifié, retour arrière = retirer deux
fichiers.
### 6.2 Commandlet de rebranchement : exigences
Modèle : `LPFixNavRandomPointCommandlet.cpp` (puis `LPFixStringSearch`, sa généralisation).
1. Trouver les nœuds par classe et fonction exactes ; compter (le `-DryRun` doit donner le nombre
attendu).
2. Relever avant modification, pour chaque broche : liaisons et valeur par défaut.
3. Créer le nouveau nœud au même emplacement, reporter **broche par broche, par nom**.
4. Comparer après : tout écart, broche sans équivalent, cible `self` reliée ou nœud impur → nœud
laissé en l'état, **Blueprint non sauvegardé**.
5. Recompiler puis sauvegarder les seuls Blueprints entièrement corrects.
Contrôle indépendant : `LPDumpAssets` avant/après puis
`python Tools/DiffRemplacementNoeuds.py avant.txt apres.txt <profil>` (profils `L7a`, `L7b`,
`CX-B12` ; ajouter un profil pour un nouveau correctif). Le diff ne doit montrer **que** les nœuds
remplacés.
### 6.3 Sous-système : modèle
```cpp
void UMonSubsystem::Initialize(FSubsystemCollectionBase& C)
{ Super::Initialize(C); TickHandle = FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateUObject(this, &UMonSubsystem::Tick)); }
void UMonSubsystem::Deinitialize() { FTSTicker::GetCoreTicker().RemoveTicker(TickHandle); Super::Deinitialize(); }
```
- Lire une variable Blueprint de `GI` : `FindPropertyByName` + `CastField<FObjectPropertyBase>`.
- Rechercher un acteur de carte par `GetFName()` : les étiquettes d'acteur n'existent pas en Shipping.
- Ne jamais défaire un état que le sous-système n'a pas lui-même posé (voir `HiddenCeiling`).
- Ne pas utiliser `LogLifePlay.GetCategoryName()` : en Shipping la catégorie est un
`FNoLoggingCategory`.
## 7. Diagnostiquer
1. **Le défaut existe-t-il en 4.27 ? dans le build précédent ?** Demander avant toute analyse
(`10_Protocole_Operations.md` §3).
2. Mesurer sur une build **Development empaquetée**, jamais avec `UnrealEditor.exe -game`.
3. Comparer 4.27 et 5.5 sur un **parcours identique** (nouvelle partie, vitesse normale, mêmes lieux)
avec `Tools\LogStats.ps1 -Compare`.
4. Pour un état d'exécution (positions, variables), utiliser les options `-LPDump*` et `-LPTrace*`
(`09_Commandes_Utiles.md` §4) dans un fichier `.bat` placé à côté de l'exécutable, que
l'utilisateur lance à la place de `LifePlay.exe`.
5. Pour un graphe : `LPDumpFunction` sur les deux arbres, puis diff.
6. Pour un écart de comportement du moteur : lire les sources moteur 4.27 et 5.5 sur les cas limites ;
en faire un test (`LPTestStringCompat`).
Inspection en direct : avec l'éditeur ouvert et le serveur MCP lancé (`McpAutomationBridge`, port 3000),
l'agent peut lire acteurs et propriétés de la carte. Usage en lecture seule recommandé ; toute
modification passe par une commandlet versionnée.
## 8. Publier
- Compte GitHub `edujiro5972` (vérifier `gh auth status` : un autre compte est aussi connecté).
- Identité de commit : `edujiro5972 <336072401+edujiro5972@users.noreply.github.com>`.
- **Jamais publiés** : adresse e-mail personnelle, `.mcp.json`, `.claude/`, `Plugins/McpAutomationBridge`,
tout `SecurityToken`, `Content/Heavy`, binaires, `*.png`, `*.7z`, `*.mp4` (règles du `.gitignore`
d'origine ; pas de LFS).
- Version complète : archive 7z des sources et du contenu (`D:\Game\LifePlay_Publication`), avec
empreinte SHA-256 publiée dans le README.
- Tags : `v1.0`, `v1.1` ; un tag `<lot>-valide` par lot validé en jeu.