diff --git a/Docs/Migration/01_Architecture_Initiale.md b/Docs/Migration/01_Architecture_Initiale.md new file mode 100644 index 0000000..f003472 --- /dev/null +++ b/Docs/Migration/01_Architecture_Initiale.md @@ -0,0 +1,183 @@ +# 01 — Architecture initiale de LifePlay (référence 4.27, écarts 5.5) + +> Document de référence de la reprise de migration (2026-09-29). +> Source : étude en lecture seule de `D:\Game\LifePlay-master 4.27` (tables de noms, d'imports et +> d'exports des `.uasset`, graphes Blueprint, code C++, journal d'exécution 4.27 Development). +> Complément : `Docs/Architecture/VictoryPlugin_Architecture.md` (C++ et plugins) et +> `Docs/Architecture/Rapport_Session_2026-09-28.md` (bug ouvert). + +--- + +## 1. Vue d'ensemble + +LifePlay est un **moteur de script piloté par des données texte**, écrit presque entièrement en +Blueprint. Il n'y a **ni DataTable, ni JSON, ni XML, ni clé de gameplay dans les `.ini`**. + +``` + Content/Modules/** (fichiers texte : .lpmod .lpstat .lpaction .lpscene .lpai .lpquest + │ .lptalk .lpdesc .lpcharacter .lpworld, tables *.txt) + │ lus à l'exécution, sur disque, hors paquet + ▼ + Plugins/ModdingExtra (C++) LoadTxt · SaveTxt · GetAllFilesFromFolder + │ FFileHelper / IFileManager sur FPaths::ProjectContentDir() + ▼ + Content/BPs/GI.uasset (GameInstance, 606 fonctions, 618 variables, 50 Mo) + │ analyse, tableaux Raws_*, structures, interpréteur du DSL + ├──► ÉVÉNEMENTS CheckForScenes → PlayScene → ReadSceneLine → CallFunction (219 commandes) + ├──► PERSONNAGES GeneratePerson → LoadPreset / Person.RandomizeAll + └──► SAUVEGARDE Save_C, GameSettings_C, CityExpansion_C (USaveGame) + .lpcharacter + ▼ + Content/BPs/Person.uasset (386 fonctions : morphs, peau, cheveux, stats) UI/* (≈100 widgets) + Plugins/StreetMap (280 villes) Source/LifePlay (helpers AssetRegistry, compat Victory) +``` + +Contrainte de packaging **vitale** : `Config/DefaultGame.ini` +`+DirectoriesToAlwaysStageAsNonUFS=(Path="Modules")`. `Modules` doit rester en fichiers nus à côté +de l'exécutable : il est lu par `FFileHelper`, pas par le système de paquets. Les mods de la +communauté reposent sur ce point. + +## 2. Configuration de démarrage + +| Fichier | Clé | Valeur | +|---|---|---| +| `DefaultEngine.ini` | `GameInstanceClass` | `/Game/BPs/GI.GI_C` | +| `DefaultEngine.ini` | `GlobalDefaultGameMode` | `/Game/BPs/GM.GM_C` | +| `DefaultEngine.ini` | `GameDefaultMap` | `/Game/Scenes/CentralLondon.CentralLondon` | +| `DefaultGame.ini` | `DirectoriesToAlwaysStageAsNonUFS` | `Modules` | +| `DefaultGame.ini` | `UsePakFile` | `False` | +| `DefaultInput.ini` | 55 `ActionMappings` (34 actions), 13 `AxisMappings` (6 axes) | consommés par `BPs/PC` uniquement | + +Aucun `GConfig` dans le C++. Les réglages joueur sont dans `Saved/SaveGames/GameSettings.sav`. + +## 3. Couches logicielles + +### 3.1 C++ du projet +| Module | Type | Contenu utile | +|---|---|---| +| `Source/LifePlay` | Runtime | `ULPAssetRegistryHelpers::GetAssetByObjectPath` (nœud pur, utilisé par `GI`, `Person`, `Room`, `UI/VisualMorph`) ; en 5.5 aussi `LPVictoryCompat`, `LPNavigationHelpers` | +| `Source/LifePlayEditorTools` | Editor | commandlets d'analyse et de correction de graphes (`LPDumpFunction`, `LPCheckMeshAssignment`, `LPFix*`, `LPCheckStreetMap`) | + +`ALifePlayGameModeBase` est vide : le vrai mode de jeu est `/Game/BPs/GM`. + +### 3.2 Plugins +| Plugin | Rôle | Fonctions consommées par le contenu | +|---|---|---| +| `ModdingExtra` (Vinfamy, Runtime, `PreLoadingScreen`) | **toute l'entrée/sortie de données** | `LoadTxt` (9 assets), `GetAllFilesFromFolder` (6), `SaveTxt` (4) | +| `StreetMap` (fork Vinfamy) | villes OSM : routes, bâtiments, `SearchByBuildingName` | 292 assets | +| `VictoryBPLibrary` (4.27 seulement) | 2 nœuds : `Victory_LoadTexture2D_FromFile`, `Victory_SaveStringToOSClipboard` | remplacé en 5.5 par `LPVictoryCompat` + `[CoreRedirects]` | + +## 4. Formats de données + +| Motif | Format | Champs | Consommateur (`GI`) | +|---|---|---|---| +| `Modules//.lpmod` | `CLÉ: valeur` | `MODULE_UNIQUEID/NAME/AUTHOR/LINK/DESCRIPTION/REQUIREMENTS` | `removeDeletedMods`, `UI/ModManager` | +| `Modules/ModLauncher.config` | ligne 1 `UseConfigIgnoreAppData:true/false`, puis `UniqueID:IsEnabled` (déduit) | — | `ReadModLauncher` → `ParseConfig` → `ModEnableds`. **Absent du disque dans les deux versions** | +| `*.lpstat` | `CLÉ: valeur` | `STAT_ID, STAT_NAME, PLAYER_ONLY, NPC_ONLY, HIGHER_BETTER, STAT_MIN, STAT_MAX, DAILY_CHANGE, DEFAULT_VALUE` | `PopulateStats` → `StatValue[]` | +| `*.lpaction` | `CLÉ: valeur` | `ACTION_UNIQUEID/NAME, WHERE, WHEN, MINUTES, TIMEOUT_MINUTES, ALSO_TIMEOUT, EFFECTS, CONDITIONS, MOVE_FIRST, SCENE_ALWAYS, ANIMATION` | `PopulateActions` → `ActionDetail[]`, `AmenityAction[]` | +| `*.lpscene` | en-tête `WHAT/WHERE/WHEN/WHO/OTHER`, puis corps DSL | — | `PopulateScenes` → `Scene[]` ; corps relu par `PlayScene` | +| `*.lpai` | corps DSL (5 premières lignes ignorées) | — | `LPAI`, `AI_High/Med`, `UpdateAI` | +| `*.lpquest` | `CLÉ: valeur` | `ID, NAME, DESC, ONCE, CONDITIONS, START` | `PopulateQuests` → `Quest[]` | +| `*.lptalk`, `*.lpdesc` | condition + textes, séparateur `##`, préfixes `*START*`/`*END*` | — | `PopulateTalksAndDescs` | +| `*.lpcharacter` | `CATÉGORIE Param: p% v1, p% v2…` ; plage `lo=>hi` | catégories `INFO, HAIR, SKIN, MORPH, STAT, SCALE, PENIS` | `LoadPreset` → `ReadLine` → `ChanceMinMax` → `GenerateAndApply{Floats,Strings,Bools}` | +| `*.lpworld` | taille de pièce, blocs `*****` (maillage `///` matériaux `///` transformation) | — | `PopulateWorldPresets`, `Room` | +| `Modules/names_{F,M}.txt` | un prénom par ligne | — | `FillNamePool` | +| `Modules/outfits_{M,F}[_work/_sports/_swim].txt` | `;` entre tenues, `,` entre pièces | — | `ReadOutfits` | +| `Modules/uniforms.txt` | lieux, puis listes F et M | — | `readUniforms` | +| `Modules/Clothes4.txt`, `SimplifyMorphs.txt`, `donors.txt` | `Nom: Daz?: Slots: Tag,Nombre` | — | `populateClothes4`, `SimplifyMorphs` | +| `Modules/MorphTags/*.txt` | un morph par ligne, `: tag` optionnel | — | `PopulateAllMorphTags` | +| `Modules/beauty_standards_default.txt` | `tag: poidsA: poidsB` | — | `PopulateBeautyStandardsDefault`, `getRandomEthnicity`, `getRandomAge` | +| `Modules/Pregnancy_Morphs.txt` | `Morph:valeur` | — | `FillPregnancyMorphs` | +| `Saved/SaveGames/GameSettings.sav` | `GameSettings_C` (63 variables) | `PercentMale/Female/IntSame/IntOpp/IntTrans`, `Fantasy*`, `BodyShapeDistribution`, `BeautyStandards_Custom`, `ModEnableds`, volumes… | `LoadSettings` / `SaveSettings` | +| `Saved/SaveGames/.sav` | `Save_C` (137 variables) | jour, heure, `GeneratedIndex`, relations, `ActorVars`, `GlobalVariables`, grossesses, IA… | `SaveGame` / `LoadGame` / `NewGame` | +| `Content/Saves//Characters/N.lpcharacter` | format `.lpcharacter` | personnages générés | `SavePreset`, `DuplicateCharacters` | + +Volumétrie 5.5 (identique à 4.27, 2 051 fichiers) : `vin_Base` 1 394 fichiers dont 752 `.lpscene`, +286 `.lpaction`, 128 `.lpcharacter`, 110 `.lpworld`, 69 `.lpstat` ; 15 autres modules `vin_*`. +36 fichiers de données sont **vides en amont** (34 `.lpscene` de `vin_base/scenes/corruption`, +`strt_white_m.lpcharacter`, `boss_asks_impregnate)cms.lpscene`) : ce n'est pas un défaut du portage. + +Structures Blueprint utilisées par les pipelines (`Content/Structs`, 57 au total) : `Variable`, +`ActorVars`, `ChanceMinMax`, `SMBool`, `ActionDetail`, `Scene`, `Quest`, `StatValue`, `ModEnabled`, +`StringArray`, `FloatArray`, `IntArray`, `PersonData`, `MorphSlider`, `NameFloat`, `Cloth`, `Inventory`. + +## 5. Pipelines + +### 5.1 Démarrage et injection des données +``` +GI.ReceiveInit → UpdateFullScreenMode, AssetReg, minuterie 2 s → DelayedStart +DelayedStart → PC.BeginPlay, StreetMap_Static.BeginPlay, LoadSettings, Make10k +LoadSettings : GameSettings.sav → ~60 variables de GI + → ReadModLauncher (LoadTxt ModLauncher.config) → ParseConfig → ModEnableds + → removeDeletedMods (GetAllFilesFromFolder "Modules" *.lpmod) + → DefaultDistributionIfNeeded (presets male/female → BodyShapeDistribution) + → PopulateRaws +PopulateRaws (pour chaque module activé) + FillNamePool, readUniforms, PopulateAllMorphTags, PopulateBeautyStandardsDefault, FillPregnancyMorphs + GetAllFilesFromFolder("Modules/", *.lpstat|lpaction|lpscene|lptalk|lpdesc|lpquest|lpai) + → LoadTxt → Raws_* (tableaux de chaînes) + → PopulateStats → PopulateActions → PopulateScenes → PopulateQuests → PopulateTalksAndDescs + → PopulateWorldPresets → RemoveNPCOnly → CleanRaws +``` +Également au démarrage, appelant non identifié (voir §7) : `donors`, `Clothes4`, `SimplifyMorphs`, +`outfits_*`. + +### 5.2 Événements (scènes) +``` +Action du joueur : TakeActionWithBuilding / TakeModActionWithBuilding → CheckForScenes + → LoopCheckForScenes → UpdateCheckForScenes (pour chaque Scene) : + CheckSceneForTimeout → CheckConditionsWhen → CheckConditionsWho → CheckConditionsOther → PlayScene +Autres déclencheurs : UpdateAI (.lpai), actions SCENE_ALWAYS, quêtes (StartQuest → TestScene) +PlayScene : LoadTxt(fichier) → GetValidLines → boucle ReadSceneLine + If/Elseif/Else/Endif/While/Random/Sex( traités en ligne ; variables : GI.Variables (Array) + ReadSceneLine → CallFunction (219 commandes) / CallFunctionReturnBool (84 conditions) + fin : DefaultDistribution, destroyAllDummies, clearScenePersons, SceneEnd, Timeout +``` + +### 5.3 Personnages +``` +DSL generatePerson(p1..pn) → GI.GeneratePerson(Presets, Temporary, Relative, MatchRace, VariableToClear) → Person_C + SpawnDummy (réserve de Person_C pré-instanciés, MakeDummyPersons) → BackupCbe → PopulateEachPerson → RandomizeStats + A) presets fournis : pour chaque .lpcharacter dont le nom se termine par le preset → LoadPreset + B) aucun preset : determinePersonVars (Percent*, Fantasy*, MajorityRace, getRandomEthnicity/Age) + → IsMale, Race, Genital, UpdatePlayerMesh, randomizeName, Person.RandomizeAll + → ChooseNPCBodyShape(BodyShapeDistribution) → LoadPreset(corps) → MorphRace + → SavePreset → SaveTxt("Saves/_session/Characters/.lpcharacter") → AddVariable +LoadPreset : LoadTxt → ReadLine → tirage → GenerateAndApplyFloats (morphs, matériaux) + / GenerateAndApplyStrings (maillages, cheveux, textures via GetAssetByObjectPath + GetAsset) + / GenerateAndApplyBools → ResolveConflictingMorphs, Unfat, ShowAppropriateGenital, UpdateProxyMorphs +``` +Tout le hasard passe par `KismetMathLibrary` (`RandomFloat`, `RandomBool`, `RandomInteger`…, +`Array_Shuffle`) : pas de graine, pas de `RandomStream`. + +### 5.4 Sauvegarde +`SaveGame(Name, Index)` : `SaveSettings` + `CreateSaveGameObject(Save_C)` + ~100 variables + +`SaveGameToSlot`. Personnages : `DuplicateCharacters` copie `Saves/_session/Characters` ↔ +`Saves//Characters` (`LoadTxt`/`SaveTxt`). + +## 6. Dépendances moteur des pipelines (points sensibles au portage) + +| Dépendance | Où | Risque 5.5 | +|---|---|---| +| Structures utilisateur avec tableaux (`Variable`) | conteneur de variables du DSL | `Variable.uasset` porte un `DoubleProperty` en 5.5 (conversion LWC) — piste principale du bug ouvert | +| `TMap` dans les `USaveGame` | `Save_C`, `GameSettings_C` | compatibilité des `.sav` existants | +| `GetAssetByObjectPath` + `GetAsset` | chargement de maillages et textures par chemin | API passée à `FSoftObjectPath` ; broches orphelines au portage | +| `SetSkeletalMesh`, `SetMasterPoseComponent`, propriété `SkeletalMesh` | `Person`, `GI`, UI | renommés/dépréciés en 5.1 | +| Composants proxy ajoutés à l'exécution (`AddComponent`) | `Person::NewProxy`, `MorphProxy` | type réel `USkinnedMeshComponent` ≠ `USkeletalMeshComponent` (cause de l'échec de R-03) | +| `FFileHelper`, `IFileManager` sur `ProjectContentDir` | `ModdingExtra` | stable ; exige `Modules` hors paquet | +| `GameplayStatics` SaveGame | `GI` | stable | + +## 7. Inconnues à lever (lot L5) + +1. Appelants de `ReadOutfits`, `populateClothes4`, `PopulateCharGenPage`, `MakeDummyPersons` (probablement `PC`, `MainMenu` ou une minuterie). +2. Format exact de `ModLauncher.config` (déduit, jamais observé sur disque). +3. Types de valeur de `PerksUnlocked`, `VoiceTypes`, `ActionCount` (`Map`). +4. Fin de `GeneratePerson` après `fertility_npc` (conditions de branche vers `ChooseNPCBodyShape`). +5. Fichiers sans chargeur confirmé : `step4_morphs.txt`, `test_output.txt`, `FAQ.txt`, `AllMorphTags.txt`. +6. Contenu binaire de `Default.sav` (un `BodyShapeDistribution` périmé est possible). + +## 8. Écarts 5.5 déjà en place (hérités de la campagne du 2026-09-08) + +VictoryPlugin retiré et remplacé par `LPVictoryCompat` (+ `[CoreRedirects]`) ; `StreetMap` porté +(LWC, R-01, R-02) ; `ModdingExtra` porté ; `Target.cs` en `BuildSettingsVersion.V5` / +`Unreal5_5` ; 8 562 packages resauvegardés en UE5 ; commandlets de correction R-03 à R-06. +État détaillé et défauts : `02_Audit_Logiciel.md`. diff --git a/Docs/Migration/02_Audit_Logiciel.md b/Docs/Migration/02_Audit_Logiciel.md new file mode 100644 index 0000000..8a33461 --- /dev/null +++ b/Docs/Migration/02_Audit_Logiciel.md @@ -0,0 +1,174 @@ +# 02 — Audit logiciel de la cible 5.5 (état au 2026-09-29) + +> Audit en lecture seule de `D:\Game\LifePlay-master 5.5` comparé à `D:\Game\LifePlay-master 4.27`. +> Empreintes de l'état audité : `Docs/Migration/etat/L0_*.csv`, commit git `lot-L0-base`. +> Moteur : UE 5.5.4 (`D:\Game\Launcher\Engine\UE_5.5`). Référence 4.27 : `D:\Game\Launcher\Engine\UE_4.27`. + +--- + +## 1. Synthèse + +| Domaine | Verdict | +|---|---| +| Code C++ du projet (`Source/`, 32 fichiers) | **sain** — aucun fichier tronqué, aucun octet nul, encodage correct, API 5.5 appliquées | +| Plugins (`ModdingExtra`, `StreetMap`) | **sains, portés** — aucun binaire 4.27 restant | +| Configuration (`Config/`) | **saine**, quelques résidus (§4) | +| Données de jeu (`Content/Modules`) | **identiques à 4.27** (2 051/2 051 fichiers) | +| Contenu binaire (`Content/`) | **1 package incohérent : `BPs/GI.uasset`** (§2) ; 4 assets StreetMap à contrôler (§3) | +| Gameplay | **défaut ouvert** : `generatePerson()` sans argument (§6) | +| Contrôle de version | **absent jusqu'au 2026-09-29** — corrigé en L0 (dépôt git local + `Tools/Snapshot.ps1`) | + +Le portage n'est pas « corrompu » au sens large : la corruption se limite à un fichier central, +mais c'est le plus important du jeu (`GI` porte tout l'interpréteur). + +## 2. Défaut principal : `Content/BPs/GI.uasset` + +| Fait | Preuve | +|---|---| +| Seul package au format UE4 sur 8 563 | en-tête `LegacyFileVersion=-7`, UE4 `522` (`Tools/AssetHeaders.ps1`) | +| Identique octet pour octet à la version 4.27 | MD5 `F4550DA5DC05FC005400CDCA2FC123C9` dans les deux arbres | +| Date disque 2026-09-07 14:38 | alors que le journal éditeur du 2026-09-28 enregistre `/Game/BPs/GI` entre 18:44 et 18:45 | +| Conséquence | les corrections 5.5 de `GI` (broches AssetRegistry, etc.) sont absentes du fichier courant | + +**Hypothèse** (non prouvée) : le fichier a été recopié depuis 4.27 après 18:45, pour un essai A/B ; +la session suivante (18:54) a tourné avec lui. + +Versions UE5 de `GI` disponibles (toutes `legacy -8`, UE5 `1013`) : + +| Sauvegarde | Date | MD5 | Contenu | +|---|---|---|---| +| `Saved/Backups/avant-R03-R06/BPs/GI.uasset` | 09-08 13:04 | `B42A3487…` | resave UE5, **avant** R-03 et avant correctif AssetRegistry | +| `Saved/Backups/avant-fix-assetregistry/GI.uasset` | 09-08 13:09 | `4477BF90…` | **avec** R-03, sans correctif AssetRegistry | +| `Saved/Backups/etat-avec-tous-correctifs/GI.uasset` | 09-28 15:35 | `D31615C2…` | **avec** R-03 et correctif AssetRegistry | + +Aucune sauvegarde ne contient l'état visé par le rapport du 28/09 (« R-03 annulé + correctif +AssetRegistry »). Il se reconstruit : `avant-R03-R06` + `LPFixAssetRegistryPins` (lot L1). + +État des autres assets touchés par la campagne R-03…R-06 : + +| Asset | État courant | +|---|---| +| `BPs/Person` | = `avant-R03-R06` (R-03 annulé, conforme au rapport) | +| `BPs/AI`, `BPs/Room`, `UI/CharGen`, `CharGenSlider`, `Cursor`, `Hairstyle`, `Inventory`, `Inventory_Cloth`, `TopRight`, `Scenes/CentralLondon` | ≠ `avant-R03-R06` : **R-03/R-04 encore appliqués** (datés 09-08 13:08–13:13) | +| `UI/StatMenu` | = `avant-R03-R06` (non touché par la campagne) | + +Incohérence à noter : R-03 est annulé sur `Person` mais toujours présent sur 7 widgets et `AI`, +`Room`. Le rapport du 28/09 dit « R-04 annulé avec R-03 (mêmes assets) » : ce n'est vrai que +pour `Person`. + +## 3. Contenu à contrôler + +| Asset | 4.27 | 5.5 | Action | +|---|---:|---:|---| +| `Heavy/StreetMap/Static/CentralLondon.uasset` | 202,0 Mo | 13,6 Mo | comparer routes/bâtiments avec `LPCheckStreetMap` | +| `Heavy/StreetMap/Static/00BathCC.uasset` | 4,2 Mo | 0,4 Mo | idem | +| `Scenes/CentralLondon.umap` | 1,0 Mo | 0,4 Mo | ouverture et contrôle visuel | +| `Heavy/Daz/Bridget/Bridget8FaceMu0.uasset` | 77 Ko | 6 Ko | vérifier la texture | + +`Docs/Architecture/streetmap_5.5.csv` (280/280 villes chargées, 53 050 bâtiments) n'a **pas de +point de comparaison 4.27** : l'exécution sur l'arbre 4.27 reste à faire. + +Autres écarts de contenu, sans conséquence : +- 6 matériaux Substance absents (`Heavy/New/fBlah/.../Grunge`), dossier jamais cuit. +- 8 571 fichiers de taille différente : resave UE5 normal (`Heavy` 8 270, `UI` 195…). + +## 4. Configuration et projet + +| Fichier | Constat | Gravité | Lot | +|---|---|---|---| +| `LifePlay.uproject` | `TargetPlatforms: ["WindowsNoEditor"]` (nom UE4) ; aucune section `Plugins` | moyenne | L2 | +| `Build/` | `WindowsNoEditor`, `LinuxNoEditor` à côté de `Windows` | faible | L2 | +| `DefaultEngine.ini:113-127` | sections auto-générées `AndroidFileServerRuntimeSettings` (avec `SecurityToken`) et `CookerSettings` | faible | L1 | +| `DefaultEngine.ini` `PhysicsSettings` | clés d'apparence PhysX : **à conserver**, vérifiées contre `UPhysicsSettingsCore` 5.5 le 09-08 (R-08) | — | — | +| `DefaultEngine.ini` rendu | aucune clé 5.5 explicite (Lumen, VSM, RHI) : valeurs par défaut du moteur | moyenne | L7 | +| `DefaultGame.ini:19-21,47-48` | 5 clés de nativisation (fonction supprimée en UE5, ignorées) | faible | L7 | +| `DefaultGame.ini:50` | section `McpAutomationBridgeSettings` (outil de développement) | info | — | +| `DefaultInput.ini` | 68 mappings hérités + classes Enhanced Input par défaut | faible (R-07) | L7 | +| `DefaultEditor.ini` | 33 Ko de `SharedProfiles` générés | faible | L1 | +| `Plugins/ModdingExtra/.../ModdingExtraBPLibrary.cpp` | instrumentation `LogLPModdingTrace` (5 391 lignes par session) | moyenne | L3 | +| `Plugins/McpAutomationBridge` | outil éditeur (2 Go, dont 1,8 Go d'`Intermediate`) ; ne doit pas être livré | info | L7 | +| `.mcp.json` | contient un jeton ; ignoré par git | info | — | + +## 5. Matrice d'obsolescence 4.27 → 5.5 + +Légende d'état : ✅ traité en 5.5 · ⚠️ partiel · ⏳ à faire. + +| Élément | Emplacement | Gravité | Spécification 5.5 | État | +|---|---|---|---|---| +| VictoryPlugin (PhysX, APEX) | `Plugins/VictoryPlugin` (4.27) | bloquant | `LPVictoryCompat` (2 fonctions) + `[CoreRedirects]` | ✅ | +| `WhitelistPlatforms`, `EngineVersion "4.27.0"` | `.uplugin` | faible | `PlatformAllowList`, pas d'`EngineVersion` | ✅ | +| `DefaultBuildSettings`, `IncludeOrderVersion` | `*.Target.cs` | moyenne | `V5`, `Unreal5_5` | ✅ | +| Chemins d'inclusion (V5) | `LifePlay.Build.cs`, `ModdingExtra.Build.cs` | haute | `PublicIncludePaths.Add(ModuleDirectory)`, `Path.Combine` | ✅ | +| `GetAssetByObjectPath(FName)`, `GetAssetsByClass(FName)` | C++ + 4 Blueprints | haute | `FSoftObjectPath`, `FTopLevelAssetPath` | ✅ C++ ; ⚠️ broches `GI` (§2) | +| `SavePackage` (ancienne surcharge) | commandlets | haute | `FSavePackageArgs` | ✅ | +| `GetAssetRegistryTags` | `StreetMap` | bloquant (5.6) | `FAssetRegistryTagsContext` | ✅ R-01 | +| LWC (`FVector` double) | `StreetMap`, `Variable.uasset` | haute | `FVector3f`/`FBox3f` pour le rendu ; **structures Blueprint à vérifier** | ✅ C++ ; ⏳ `Variable` | +| Propriété `SkeletalMesh` | 10 Blueprints | moyenne | `GetSkeletalMeshAsset()` **sur `USkeletalMeshComponent` seulement** ; pour les proxies `USkinnedMeshComponent`, `GetSkinnedAsset()` | ⚠️ R-03 à refaire | +| `SetMasterPoseComponent` | `Person` | faible | `SetLeaderPoseComponent` | ✅ redirection moteur | +| `GetRandomPointInNavigableRadius` | `AI`, `Person`, `Room` | faible | `LPNavigationHelpers` (enrobage pur) | ⚠️ annulé sur `Person` | +| Liaisons `On Clicked` orphelines | `UI/TopRight`, `UI/CharGen` | faible | suppression (R-05) | ✅ | +| Échelle nulle `Wall` | `Scenes/CentralLondon` | moyenne (plantage `InverseFast`) | X = 0,1 (R-06) | ✅ | +| Entrées héritées | `DefaultInput.ini`, `BPs/PC` (53 nœuds) | faible | Enhanced Input (R-07) | ⏳ | +| Cascade | 4 systèmes `Heavy/New3/Particles` ; `Person`, `TestPerson`, niveau | moyenne | Niagara, ou conserver si le chargement 5.5 est propre | ⏳ vérifier | +| NvCloth | `BPs/Person`, `BPs/TestStatic` (fabrique référencée, aucun asset de tissu) | faible | fabrique Chaos Cloth | ⏳ vérifier | +| AtmosphericFog | `Scenes/CentralLondon` | faible | `SkyAtmosphere` + `ExponentialHeightFog` | ⏳ | +| Éclairage précalculé | `CentralLondon` + `_BuiltData`, `Room` | moyenne (visuel) | reconstruire l'éclairage | ⏳ | +| Substance | 6 assets `Heavy/New/fBlah` (jamais cuits) | nulle | ignorer | — | +| Nativisation | `DefaultGame.ini` | nulle | supprimer les clés | ⏳ | + +## 6. Défaut fonctionnel ouvert + +Rapport complet : `Docs/Architecture/Rapport_Session_2026-09-28.md`. Résumé : + +- `generatePerson()` **sans argument** produit des personnages incorrects (toujours « Tyrone », + nus, invisibles pendant le dialogue) ; avec des presets, le résultat est correct. +- Indicateur discriminant : `Accessed None` sur un maillage, **0,3 par personnage en 4.27 + contre 16,6 en 5.5**. +- Hypothèses éliminées avec preuve : 14 (données, assets manquants, AssetRegistry, R-03…). +- Piste principale : **variable DSL au tableau vide** (`GI::ReturnStatIfNeeded`, `Float[0]` sur un + tableau de longueur 0), liée à la conversion LWC de `Content/Structs/Variable.uasset`. + +**Piège de méthode établi** : l'éditeur en mode `-game` casse l'affichage des personnages **dans les +deux versions**. Seules des builds empaquetées Development sont comparables. + +## 7. Journal du 2026-09-28 (session PIE 5.5) + +`Saved/Logs/LifePlay.log`, 51 790 lignes, fin propre. Attention : cette session a tourné avec le +`GI` UE4 (§2) ; ses chiffres ne décrivent pas l'état « tous correctifs ». + +| Nombre | Signature | Classement | +|---:|---|---| +| 9 048 | `GetSocketInfoByName(...): No SkeletalMesh for CharacterMesh` sur `Person_C` | présent aussi en 4.27 (80/perso contre 76) → bruit | +| 6 510 | `index N from CallFunc_ParseIntoArray_ReturnValue of length N` dans `GI` | à analyser (L5) | +| 5 391 | `LogLPModdingTrace LoadTxt OK` | instrumentation → L3 | +| 1 297 | `getBeautyValue` `Floats_*` index hors bornes | à analyser (L5) | +| 273 | `Accès à None` `NearVec` dans `Person::standIdle` | à analyser (L5) | +| 257 | `Accès à None` `ContactMenu` dans `UpdateDailyPose` | à analyser (L6) | +| 229 | `CallFunc_Array_Get_Item` à None dans `GI` | à analyser (L5) | +| 153 | `LogBlueprint` : nœud `SkeletalMesh` déprécié (`GI` 52, `Person` 24) | R-03 (L7) | +| 37 | `LogStreaming Failed to read file` (icônes moteur) | cosmétique | +| 25 | `InputMode:UIOnly … Non-Focusable widget` | faible | +| 11 | `SpawnActor failed because no class was specified` | à analyser (L6) | + +Plantages (`Saved/Crashes`, 2026-09-07, pendant le resave de masse) : `BulkData.cpp:1482 +IsUnlocked()` ; `Array.h:783` index 0 sur tableau vide ; `Matrix.h:429 InverseFast` (mur à échelle +nulle, corrigé par R-06). Les deux premiers concernent `Heavy/New2/Furniture/fnt_new100/111` +(resave repris et achevé). + +## 8. Ce qui est supprimable ou à conserver + +| Régénérable (après sauvegarde) | Taille | +|---|---:| +| `Intermediate/` | 5,7 Go | +| `Binaries/` (projet), `Plugins/*/Binaries`, `Plugins/*/Intermediate` | ≈ 3,3 Go | +| `Saved/Cooked/`, `Saved/StagedBuilds/` | 6,3 Go | +| `Saved/Crashes/`, `Saved/Autosaves/`, `Saved/Temp`, `ShaderDebugInfo`, `MaterialStats*` | faible | + +| À conserver | Raison | +|---|---| +| `.claude/`, `.mcp.json`, `.editorconfig`, `.gitignore` | environnement de développement | +| `Saved/Backups/` | seules copies UE5 de `GI` (§2) | +| `Saved/SaveGames/`, `Saved/Config/WindowsEditor`, `Saved/Logs/portage/` | réglages, historique | +| `D:\DDC` | cache dérivé partagé réel (`DerivedDataCache/` du projet est vide) | +| `D:\Game\LifePlay_Build_427_Dev` | **build de référence 4.27 journalisée** | +| Arbre `LifePlay-master 4.27` | référence, jamais modifiée | diff --git a/Docs/Migration/03_Plan_Migration_Tests.md b/Docs/Migration/03_Plan_Migration_Tests.md new file mode 100644 index 0000000..a7daa89 --- /dev/null +++ b/Docs/Migration/03_Plan_Migration_Tests.md @@ -0,0 +1,129 @@ +# 03 — Plan de migration fondé sur les tests + +> Règle : **aucun lot n'est validé sans ses tests de sortie**. Un test de sortie en échec entraîne +> le retour arrière du lot (§5), puis une analyse. Les résultats sont consignés dans +> `Journal_Modifications.md`, les défauts dans `Registre_Erreurs.md`. + +--- + +## 1. Environnement de test + +| Élément | Chemin | +|---|---| +| Moteur 5.5.4 | `D:\Game\Launcher\Engine\UE_5.5` | +| Moteur 4.27 (référence) | `D:\Game\Launcher\Engine\UE_4.27` | +| Projet cible | `D:\Game\LifePlay-master 5.5\LifePlay.uproject` | +| Projet de référence (lecture seule) | `D:\Game\LifePlay-master 4.27\LifePlay.uproject` | +| **Build de référence 4.27 Development (journalisée)** | `D:\Game\LifePlay_Build_427_Dev\WindowsNoEditor\LifePlay` | +| Sauvegardes de lots | `D:\Game\LifePlay_Backup_5.5\\` | + +Raccourcis utilisés ci-dessous : + +```powershell +$UE = 'D:\Game\Launcher\Engine\UE_5.5\Engine' +$Cmd = "$UE\Binaries\Win64\UnrealEditor-Cmd.exe" +$Proj = 'D:\Game\LifePlay-master 5.5\LifePlay.uproject' +``` + +## 2. Règles de mesure (acquises, à ne pas remettre en cause) + +1. **Ne jamais mesurer l'exécution avec `UnrealEditor.exe -game`** : ce mode casse l'affichage des + personnages en 4.27 comme en 5.5 (rapport du 2026-09-28, §5.1). +2. **Comparer des builds empaquetées de même configuration** (Development ; Shipping ne journalise pas). +3. **Vérifier que les deux journaux atteignent le même point** : `index SPAWN > 0` des deux côtés. +4. **Normaliser** les compteurs par le nombre de personnages générés. +5. **Recouper** tout écart catégorique par un second comptage formulé autrement. + +## 3. Catalogue des tests + +### 3.1 Niveau statique (secondes, sans moteur) + +| ID | Vérifie | Commande | Critère | +|---|---|---|---| +| T-STAT-01 | format des packages | `Tools\AssetHeaders.ps1` | 0 package UE4, 0 illisible | +| T-STAT-02 | données de jeu intactes | `Tools\CheckIntegrity.ps1 -Modules` | 2 051 fichiers, MD5 identiques à 4.27 | +| T-STAT-03 | environnement de développement intact | `Tools\CheckIntegrity.ps1 -Env` | `.claude/`, `.mcp.json`, `Saved/Backups` = empreintes L0 | +| T-STAT-04 | référence 4.27 non modifiée | `Tools\CheckIntegrity.ps1 -Ref427` | `Source`, `Config`, `.uproject`, `Content/BPs` 4.27 = empreintes L0 | +| T-STAT-05 | traçabilité | `git status` | arbre propre après commit du lot ; tag `lot-XX-apres` posé | + +### 3.2 Niveau compilation + +| ID | Vérifie | Commande | Critère | +|---|---|---|---| +| T-BUILD-01 | éditeur | `& "$UE\Build\BatchFiles\Build.bat" LifePlayEditor Win64 Development -Project="$Proj" -WaitMutex` | code 0, 0 erreur, 0 nouvel avertissement | +| T-BUILD-02 | jeu | `Build.bat LifePlay Win64 Development -Project="$Proj"` | code 0 | + +### 3.3 Niveau chargement (commandlets, éditeur sans interface) + +| ID | Vérifie | Commande | Critère | +|---|---|---|---| +| T-LOAD-01 | tous les Blueprints | `& $Cmd $Proj -run=CompileAllBlueprints -unattended -nopause` | 0 erreur, 0 Blueprint en échec de chargement | +| T-LOAD-02 | broches orphelines | `& $Cmd $Proj -run=LPCheckMeshAssignment` | 0 broche `bOrphanedPin` | +| T-LOAD-03 | villes | `& $Cmd $Proj -run=LPCheckStreetMap -CSV=Docs/Migration/etat/streetmap.csv` | 280/280 ; totaux = `Docs/Architecture/streetmap_5.5.csv` | +| T-LOAD-04 | démarrage éditeur propre | `Tools\LogStats.ps1 ` | 0 `LogClass: Error`, 0 `Failed to load` sur `/Game/` | +| T-LOAD-05 | cuisson | `& $Cmd $Proj -run=Cook -TargetPlatform=Windows -unattended` | `0 error(s)` | + +### 3.4 Niveau exécution (build empaquetée Development) + +Construction : `RunUAT BuildCookRun -project="$Proj" -platform=Win64 -clientconfig=Development +-build -cook -stage -pak:false -archive -archivedirectory=D:\Game\LifePlay_Build_5.5_V1`. + +| ID | Vérifie | Mesure (`Tools\LogStats.ps1`) | Critère | +|---|---|---|---| +| T-RUN-01 | démarrage et données | lignes `GetAllFilesFromFolder` / `LoadTxt` par module | mêmes comptes que la référence 4.27 (ex. `vin_Base` : 752 `.lpscene`) | +| T-RUN-02 | génération de personnages | `index SPAWN` ; `Accessed None` sur maillage par personnage | ≥ 10 personnages ; ≤ 1,0 par personnage (4.27 : 0,3) | +| T-RUN-03 | personnages distincts | prénoms des `Saves/_session/Characters/*.lpcharacter` | ≥ 8 prénoms différents sur 10 | +| T-RUN-04 | scène, sauvegarde, rechargement | parcours manuel scénarisé (§4) | aucun blocage ; partie rechargée identique | +| T-RUN-05 | stabilité | session de 30 min | aucun dossier nouveau dans `Saved/Crashes` | +| T-LOG-01 | journal exploitable | lignes `LogLifePlay` du démarrage | résumé présent ; démarrage lisible en < 200 lignes hors moteur | + +### 3.5 Non-régression A/B + +Chaque test T-RUN est exécuté sur la build 5.5 **et** sur la référence 4.27 avec le même scénario. +`Tools\LogStats.ps1 -Compare ` produit le tableau normalisé. + +## 4. Scénario d'exécution de référence (T-RUN-04) + +1. Lancer la build, nouvelle partie avec le personnage par défaut. +2. Attendre la fin du chargement (menu principal puis ville `CentralLondon`). +3. Déclencher 3 actions de lieu provoquant des scènes avec PNJ générés (`generatePerson()`). +4. Vérifier à l'écran : PNJ visibles, habillés, prénoms variés. +5. Sauvegarder (emplacement `TestV1`), quitter, relancer, charger `TestV1`. +6. Vérifier : même jour et heure, contacts présents. +7. Copier le journal : `Saved/Logs/LifePlay.log` → `Docs/Migration/etat/_run_.log`. + +## 5. Procédure de retour arrière + +| Portée | Commande | +|---|---| +| Fichiers suivis par git (code, config, docs, Blueprints de `BPs`, `UI`, `Structs`, `Scenes`, `Render`) | `git checkout lot-XX-avant -- ` ou `git revert ` | +| Tout fichier sauvegardé par le lot (y compris `Content/Heavy`) | `Tools\Restore.ps1 -Lot XX` (`-WhatIf` pour simuler) | +| Un seul fichier | `Tools\Restore.ps1 -Lot XX -Only ` | + +Après retour arrière : relancer T-STAT-01 à T-STAT-04 et T-BUILD-01. Consigner l'entrée +`CHG` d'annulation dans le journal. + +## 6. Correspondance risques ↔ tests + +| Risque (audit 02) | Test qui le couvre | +|---|---| +| `GI` au format UE4, broches AssetRegistry perdues | T-STAT-01, T-LOAD-02 | +| Nœuds dépréciés, liaisons perdues par une commandlet | T-LOAD-01, T-LOAD-02 | +| Données StreetMap perdues au resave | T-LOAD-03 | +| `Modules` non livré en fichiers nus | T-RUN-01 | +| Conteneur `Variable` (LWC), `generatePerson()` | T-RUN-02, T-RUN-03 | +| Plantages | T-RUN-05 | +| Journal illisible | T-LOG-01 | +| Environnement de développement abîmé | T-STAT-03 | +| Référence 4.27 abîmée | T-STAT-04 | + +## 7. Outils + +| Script | Rôle | État | +|---|---|---| +| `Tools/Snapshot.ps1` | sauvegarde avant modification, manifeste MD5 | ✅ testé (L0) | +| `Tools/Restore.ps1` | restauration vérifiée, réversible elle-même | ✅ testé (L0) | +| `Tools/AssetHeaders.ps1` | format UE4/UE5 des packages | ✅ | +| `Tools/CheckIntegrity.ps1` | T-STAT-02 à T-STAT-04 | ✅ (L0) | +| `Tools/LogStats.ps1` | compteurs de journal, comparaison A/B | ✅ (L0) | +| Commandlets `LifePlayEditorTools` | `LPCheckMeshAssignment`, `LPCheckStreetMap`, `LPDumpFunction`, `LPFix*` (option `-DryRun`) | existants | diff --git a/Docs/Migration/04_Cahier_Des_Charges.md b/Docs/Migration/04_Cahier_Des_Charges.md new file mode 100644 index 0000000..77e48f0 --- /dev/null +++ b/Docs/Migration/04_Cahier_Des_Charges.md @@ -0,0 +1,134 @@ +# 04 — Cahier des charges : migration itérative par lots bornés + +> Méthode : développement itératif. Chaque lot tient dans **une session IA** (≈ 2 à 3 h), a **un +> objectif mesurable**, des **tests d'entrée et de sortie** (catalogue : `03_Plan_Migration_Tests.md`) +> et une **procédure de retour arrière**. Un lot ne commence qu'après validation du précédent. + +--- + +## 1. Exigences + +### 1.1 V1 — « compile, fonctionne, ne plante pas, journal exploitable » + +| ID | Exigence | Test d'acceptation | +|---|---|---| +| EX-01 | L'éditeur `LifePlayEditor Win64 Development` compile sans erreur | T-BUILD-01 | +| EX-02 | Tous les Blueprints se chargent et se compilent | T-LOAD-01, T-LOAD-02 | +| EX-03 | Tous les packages sont au format UE5 | T-STAT-01 | +| EX-04 | Les données `Modules` sont intactes et chargées comme en 4.27 | T-STAT-02, T-RUN-01 | +| EX-05 | Une build Development empaquetée démarre, génère des personnages distincts et visibles, joue une scène, sauvegarde et recharge | T-RUN-02 à T-RUN-04 | +| EX-06 | Aucun plantage sur une session de 30 minutes | T-RUN-05 | +| EX-07 | Journal efficace : catégorie `LogLifePlay`, résumé de démarrage, erreurs répétitives plafonnées, instrumentation de portage retirée du niveau par défaut | T-LOG-01 | +| EX-08 | Toute modification est tracée et réversible | T-STAT-05 ; essai réel de `Restore.ps1` | +| EX-09 | Environnement de développement et référence 4.27 préservés | T-STAT-03, T-STAT-04 | + +Hors V1, tolérés et inscrits au registre : visuel dégradé (éclairage précalculé, brouillard), +avertissements cosmétiques du moteur, dette R-03/R-07, rendu Cascade. + +### 1.2 V2 et suivantes — corrections par lots soutenables + +Traitement du `Registre_Erreurs.md` **par ordre de fréquence × gravité**, un lot par famille +(≤ 30 assets ou une commandlet), avec non-régression complète des tests V1. + +## 2. Règles de conduite d'un lot + +1. **Entrée** : tests de sortie du lot précédent au vert ; `git status` propre. +2. `git tag lot-XX-avant`. +3. `Tools\Snapshot.ps1 -Lot XX -Path ` (y compris hors git, ex. `Content/Heavy`). +4. Modification. Toute commandlet de correction est d'abord lancée en `-DryRun`, rapport archivé + dans `Docs/Migration/etat/`. +5. Tests de sortie. +6. Vert → entrée `CHG` au journal, commit, `git tag lot-XX-apres`. + Rouge → `Tools\Restore.ps1 -Lot XX` (ou `git checkout lot-XX-avant -- …`), entrée `CHG` d'annulation, + défaut inscrit au registre. +7. Un lot qui dépasse la session est **coupé** : ce qui est validé est commité, le reste redevient + un lot à part. + +## 3. Lots + +### L0 — Filet de sécurité et documentation ✅ (2026-09-29) +- **Objectif** : pouvoir tout annuler et savoir ce qu'on migre. +- **Livrables** : documents 01 à 04, journal, registre ; dépôt git local (tag `lot-L0-base`) ; + `Tools/` (Snapshot, Restore, AssetHeaders, CheckIntegrity, LogStats) ; empreintes L0 ; sauvegarde + `D:\Game\LifePlay_Backup_5.5\L0` (53 fichiers). +- **Sortie** : aller-retour `Snapshot`/`Restore` vérifié par MD5 ; T-STAT-02 à 04 au vert. + +### L1 — Assainissement du contenu et des caches +- **Objectif** : 0 package UE4 ; `GI` dans un état 5.5 connu et documenté ; projet débarrassé des artefacts. +- **Périmètre** : + 1. Reconstituer `GI` « R-03 annulé + correctif AssetRegistry » : restaurer + `Saved/Backups/avant-R03-R06/BPs/GI.uasset`, puis `LPFixAssetRegistryPins -DryRun`, puis réel + (décision D-01, §4). + 2. Rendre R-03/R-04 cohérents sur les autres assets (décision D-02, §4). + 3. Purger les dossiers régénérables (`02_Audit_Logiciel.md` §8), après sauvegarde. + 4. `DefaultEngine.ini` : retirer `AndroidFileServerRuntimeSettings` et `CookerSettings` ; + `DefaultEditor.ini` : vider les `SharedProfiles` générés. +- **Sortie** : T-STAT-01 à 05, T-LOAD-02 (0 broche orpheline), T-LOAD-01. +- **Retour** : `Restore.ps1 -Lot L1` ; les caches purgés se régénèrent seuls. + +### L2 — Compilation propre +- **Objectif** : binaires reconstruits à partir de zéro, projet conforme UE5. +- **Périmètre** : `.uproject` (`TargetPlatforms: ["Windows"]`, section `Plugins` explicite : + `ModdingExtra`, `StreetMap`, `EnhancedInput`, `McpAutomationBridge` limité à l'éditeur) ; + retrait de `Build/WindowsNoEditor` et `Build/LinuxNoEditor` ; régénération des fichiers de projet ; + compilation éditeur et jeu. +- **Sortie** : T-BUILD-01, T-BUILD-02, T-LOAD-04. + +### L3 — Journalisation efficace +- **Objectif** : un journal qui sert au diagnostic. +- **Périmètre** : + - `Source/LifePlay` : catégorie `LogLifePlay` déclarée dans le module ; résumé de démarrage + (version du jeu et du moteur, modules activés, nombre de fichiers par type, échecs `LoadTxt`) ; + - `ModdingExtra` : `LogLPModdingTrace` ramené en `Verbose` (activable par + `-LogCmds="LogLPModdingTrace Verbose"`) ; échec de `LoadTxt` journalisé en `Warning` une seule + fois par fichier ; + - `DefaultEngine.ini` `[Core.Log]` : niveaux par catégorie ; plafonnement des `LogScript` + répétitifs. +- **Sortie** : T-BUILD-01, T-LOG-01 ; A/B : mêmes comptes `GetAllFilesFromFolder` qu'avant. + +### L4 — Chargement stable +- **Objectif** : 0 erreur de chargement et de compilation des Blueprints, cuisson à 0 erreur. +- **Périmètre** : relevé `CompileAllBlueprints` + `LPCheckMeshAssignment` ; une famille de + correction par sous-lot (`LPFixAssetRegistryPins`, `LPFixOrphanBoundEvents`, + `LPFixEditableTextBoxFont`, `LPFixZeroScaleActors`) ; contrôle StreetMap (`LPCheckStreetMap` + sur 4.27 **et** 5.5, comparaison des CSV). +- **Sortie** : T-LOAD-01 à T-LOAD-05. + +### L5 — Données et personnages +- **Objectif** : `generatePerson()` sans argument produit des personnages distincts et habillés. +- **Périmètre** : + 1. `LPDumpFunction` dans les deux versions sur `GeneratePerson`, `determinePersonVars`, + `ChooseNPCBodyShape`, `DefaultDistributionIfNeeded`, `SpawnDummy`, `GenerateAndApplyStrings`, + `ReturnStatIfNeeded` ; diff archivé. + 2. Instrumenter l'**écriture** des variables DSL (`AddVariable`, `SetVariable`) : piste + `Variable.uasset` / LWC. + 3. Correction minimale, puis inconnues de `01_Architecture_Initiale.md` §7. +- **Sortie** : T-RUN-01 à T-RUN-03 sur build Development, A/B avec la référence 4.27. + +### L6 — Session complète → **V1** +- **Objectif** : EX-01 à EX-09 au vert. +- **Périmètre** : build Development `D:\Game\LifePlay_Build_5.5_V1` ; scénario T-RUN-04 ; + session de 30 min ; tri du registre ; étiquette `v1.0`. +- **Sortie** : tous les tests V1. + +### L7+ — Lots post-V1 (un par famille) +Ordre indicatif, à réviser selon le registre : + +| Lot | Famille | Périmètre | +|---|---|---| +| L7a | R-03 refait correctement | `GetSkinnedAsset()` pour les proxies ; 56 nœuds, 10 Blueprints | +| L7b | Erreurs d'exécution fréquentes | `ParseIntoArray`, `getBeautyValue`, `standIdle`, `ContactMenu` | +| L7c | Configuration | clés de nativisation, rendu 5.5 explicite (GI, ombres, RHI) | +| L7d | Visuel | AtmosphericFog → SkyAtmosphere ; reconstruction de l'éclairage | +| L7e | Effets | 4 systèmes Cascade → Niagara (si nécessaire) ; NvCloth → Chaos | +| L7f | Entrées | Enhanced Input (R-07), avec test manuel des 34 commandes | +| L7g | Packaging | build Shipping ; exclusion de `McpAutomationBridge` | + +## 4. Décisions + +| ID | Question | Recommandation | Statut | +|---|---|---|---| +| D-01 | Base de reconstruction de `GI` | `avant-R03-R06` + `LPFixAssetRegistryPins` : reproduit l'état « R-03 annulé + correctif » décrit par le rapport du 28/09. Alternative : repartir du `GI` 4.27 actuel (le moteur le convertira) + même commandlet | à valider (L1) | +| D-02 | R-03/R-04 présents sur `AI`, `Room` et 7 widgets, annulés sur `Person` et `GI` | **conserver en l'état pour la V1** (les widgets ne portent pas de proxies ; `CompileAllBlueprints` passait) ; refaire R-03 proprement en L7a | à valider (L1) | +| D-03 | Mesure d'exécution | builds empaquetées Development uniquement (règle §2 du document 03) | acquis | +| D-04 | Suivi de version | dépôt git local, Blueprints de gameplay inclus, `Content/Heavy` exclu (sauvegardes par lot) | acquis (L0) | diff --git a/Docs/Migration/Journal_Modifications.md b/Docs/Migration/Journal_Modifications.md new file mode 100644 index 0000000..91f3366 --- /dev/null +++ b/Docs/Migration/Journal_Modifications.md @@ -0,0 +1,26 @@ +# Journal des modifications — migration 5.5 + +> Une entrée par modification. Format : identifiant, date, lot, fichiers, raison, empreintes, +> retour arrière. Les empreintes complètes sont dans `D:\Game\LifePlay_Backup_5.5\\manifest.csv` +> et dans l'historique git. + +| ID | Date | Lot | Fichiers | Raison | Avant → après | Retour arrière | +|---|---|---|---|---|---|---| +| CHG-001 | 2026-09-29 | L0 | `.gitignore` | ignorer les fichiers générés (`Build/*/FileOpenOrder`, `Content/Collections`, `Content/Developers`, `.claude/settings.local.json`) | 31 → 38 lignes | retirer le bloc « CHG-001 » | +| CHG-002 | 2026-09-29 | L0 | `.gitattributes` (nouveau) | aucune conversion de fin de ligne : restauration git identique à l'octet | — → créé | supprimer le fichier | +| CHG-003 | 2026-09-29 | L0 | `.git/` (nouveau) | dépôt local, identité locale, `core.autocrlf=false`, `core.longpaths=true` ; commit `de64933`, tag `lot-L0-base` | — → créé | supprimer `.git/` | +| CHG-004 | 2026-09-29 | L0 | `Tools/Snapshot.ps1`, `Restore.ps1`, `AssetHeaders.ps1`, `CheckIntegrity.ps1`, `LogStats.ps1` (nouveaux) | outillage de traçabilité et de test | — → créés | `git rm` | +| CHG-005 | 2026-09-29 | L0 | `Docs/Migration/**` (nouveau) | documentation 01 à 04, journal, registre, empreintes `etat/L0_*` | — → créés | `git rm` | +| CHG-006 | 2026-09-29 | L0 | `D:\Game\LifePlay_Backup_5.5\L0\` (hors projet) | sauvegarde de `.claude`, `.mcp.json`, `LifePlay.uproject`, `Config`, `Saved/Backups`, `Saved/SaveGames`, `Content/BPs` (53 fichiers) | — → créé | sans objet | + +## Vérifications du lot L0 + +| Test | Résultat | +|---|---| +| Aller-retour `Snapshot` → modification → `Restore` (`Config/DefaultEditorSettings.ini` + fichier créé) | ✅ MD5 `85D82E7F…` retrouvé ; fichier créé retiré vers `_retires/` | +| T-STAT-01 | ⚠️ 1 package UE4 (`Content/BPs/GI.uasset`) : défaut connu, traité en L1 | +| T-STAT-02 Modules = 4.27 | ✅ 2 051 fichiers | +| T-STAT-03 environnement = L0 | ✅ 20 fichiers | +| T-STAT-04 arbre 4.27 inchangé | ✅ 144 fichiers (empreinte créée : `etat/L0_ref427.csv`) | + +Aucun fichier du projet n'a été modifié en L0 en dehors de `.gitignore` et des ajouts ci-dessus. diff --git a/Docs/Migration/README.md b/Docs/Migration/README.md new file mode 100644 index 0000000..ad54eff --- /dev/null +++ b/Docs/Migration/README.md @@ -0,0 +1,27 @@ +# Migration LifePlay 4.27 → 5.5 — point d'entrée + +Reprise de la migration commencée le 2026-09-29, après l'échec du premier portage. + +| Document | Contenu | +|---|---| +| [01_Architecture_Initiale.md](01_Architecture_Initiale.md) | fonctionnement de LifePlay : données texte → `ModdingExtra` → interpréteur `GI` → événements et personnages | +| [02_Audit_Logiciel.md](02_Audit_Logiciel.md) | état réel de la cible 5.5, corruption, obsolescence, erreurs mesurées | +| [03_Plan_Migration_Tests.md](03_Plan_Migration_Tests.md) | catalogue des tests, règles de mesure, retour arrière | +| [04_Cahier_Des_Charges.md](04_Cahier_Des_Charges.md) | exigences V1, lots L0 à L7, décisions | +| [Journal_Modifications.md](Journal_Modifications.md) | chaque modification, avec son retour arrière | +| [Registre_Erreurs.md](Registre_Erreurs.md) | erreurs mesurées, priorité, lot cible | +| `etat/` | empreintes et relevés datés par lot | + +Documents antérieurs, toujours valables : `Docs/Architecture/VictoryPlugin_Architecture.md`, +`Docs/Architecture/Rapport_Session_2026-09-28.md`. + +## Démarrer une session de travail + +```powershell +Set-Location 'D:\Game\LifePlay-master 5.5' +git status; git tag --list 'lot-*' # où en est-on +.\Tools\CheckIntegrity.ps1 -Modules -Env -Ref427 # rien n'a bougé à notre insu +.\Tools\AssetHeaders.ps1 # format des packages +``` + +Puis suivre le lot suivant de `04_Cahier_Des_Charges.md` §3, en respectant les règles du §2. diff --git a/Docs/Migration/Registre_Erreurs.md b/Docs/Migration/Registre_Erreurs.md new file mode 100644 index 0000000..241cb24 --- /dev/null +++ b/Docs/Migration/Registre_Erreurs.md @@ -0,0 +1,26 @@ +# Registre des erreurs — migration 5.5 + +> Une ligne par signature d'erreur. Fréquence mesurée avec `Tools\LogStats.ps1` ; source indiquée. +> Priorité = fréquence × gravité. Statut : ouvert · en cours · corrigé (CHG) · accepté (V1). + +| ID | Signature | Source | Fréquence | Gravité | Lot cible | Statut | +|---|---|---|---:|---|---|---| +| ERR-001 | `Content/BPs/GI.uasset` au format UE4, identique à 4.27 | `Tools\AssetHeaders.ps1` | 1 fichier | bloquante | L1 | ouvert | +| ERR-002 | `generatePerson()` sans argument : personnages identiques (« Tyrone »), nus, invisibles ; en PIE 5.5 chaque `index SPAWN` pointe vers `Person_C_0` | rapport 2026-09-28, journal PIE 09-28 | 16,6 `Accessed None` maillage/perso (4.27 : 0,3) | bloquante | L5 | ouvert | +| ERR-003 | `Attempted to access index 0 from array Float_… of length 0` dans `GI::ReturnStatIfNeeded` (variable DSL `Float` vide) | build 5.5 Development | 2 (4.27 : 0) | haute | L5 | ouvert | +| ERR-004 | `index N from CallFunc_ParseIntoArray_ReturnValue of length N` (`GI` EventGraph) | PIE 09-28 | 6 510 | moyenne | L7b | ouvert | +| ERR-005 | `getBeautyValue` : `Floats_*` index hors bornes | PIE 09-28 | 1 297 | moyenne | L7b | ouvert | +| ERR-006 | `Accès à None` `NearVec` dans `Person::standIdle` | PIE 09-28 | 273 | moyenne | L7b | ouvert | +| ERR-007 | `Accès à None` `ContactMenu` dans `UpdateDailyPose` | PIE 09-28 | 257 | moyenne | L7b | ouvert | +| ERR-008 | `CallFunc_Array_Get_Item` à None dans `GI` | PIE 09-28 | 229 | moyenne | L5 | ouvert | +| ERR-009 | `SpawnActor failed because no class was specified` | PIE 09-28 | 11 | moyenne | L6 | ouvert | +| ERR-010 | `LogLPModdingTrace` : instrumentation de portage à chaque `LoadTxt` | tous journaux | ≈ 1 300 à 5 400 / session | faible (bruit) | L3 | ouvert | +| ERR-011 | `GetSocketInfoByName … No SkeletalMesh for CharacterMesh` | tous journaux | 80/perso en 4.27, 76 en 5.5 | bruit (existe en 4.27) | — | accepté | +| ERR-012 | Nœud `SkeletalMesh` déprécié (`GI` 52, `Person` 24) | `LogBlueprint` | 153 | faible (dette) | L7a | ouvert | +| ERR-013 | `Daz/Michael/hairs/other/Pubes05-06` introuvable (assets dans `Daz/Bridget/Hairs/Pubic/`) | journaux 4.27 et 5.5 | 56 / session | faible (existe en 4.27) | L7b | ouvert | +| ERR-014 | `Modules/ModLauncher.config` absent : `LoadTxt ECHEC` | journaux 4.27 et 5.5 | 2 / session | faible (existe en 4.27) | L3 | ouvert | +| ERR-015 | `InputMode:UIOnly … Non-Focusable widget` | PIE 09-28 | 25 | faible | L7b | ouvert | +| ERR-016 | Matériau `FntMat` sans `bUsedWithStaticLighting` → matériau par défaut | rapport 09-28 | — | faible (visuel) | L7d | ouvert | +| ERR-017 | `LogStreaming Failed to read file` (icônes moteur VisionOS, Interchange, Slate) | PIE 09-28 | 37 | cosmétique | — | accepté | +| ERR-018 | Assets StreetMap fortement réduits (`CentralLondon` 202 → 13,6 Mo, `00BathCC`) | comparaison des tailles | 4 fichiers | à qualifier | L4 | ouvert | +| ERR-019 | Plantages du resave de masse : `BulkData IsUnlocked`, `Array.h:783` (`fnt_new100/111`) | `Saved/Crashes` 09-07 | 2 | à surveiller | L4 | ouvert | diff --git a/Docs/Migration/etat/L0_ref427.csv b/Docs/Migration/etat/L0_ref427.csv new file mode 100644 index 0000000..19f34d8 --- /dev/null +++ b/Docs/Migration/etat/L0_ref427.csv @@ -0,0 +1,145 @@ +"Rel","MD5" +"Source\LifePlay.Target.cs","3F3A022247A1F7E27A46DA1954AEBF37" +"Source\LifePlayEditor.Target.cs","369B5B133D15E8914E5BAA643A3FBEEF" +"Source\LifePlay\LifePlay.Build.cs","7472747C2E9EF2FA7F63487B571AB993" +"Source\LifePlay\LifePlay.cpp","25DA65DFF8263530C11CF502CDFD6D48" +"Source\LifePlay\LifePlay.h","7A0D247245283D72A164E62163579D0F" +"Source\LifePlay\LifePlayGameModeBase.cpp","60B2177518E9A678C614549D40E391F1" +"Source\LifePlay\LifePlayGameModeBase.h","3D96F83506A3F9B77A4E75AE18D1B608" +"Source\LifePlay\LPAssetRegistryHelpers.cpp","C0942DA9D8BCA8207AE6BACDA297152D" +"Source\LifePlay\LPAssetRegistryHelpers.h","DA8F72AE7FB4203AF14F01AD2A46A801" +"Source\LifePlayEditorTools\LifePlayEditorTools.Build.cs","54624246A3FA24AD9F78D091E4E31239" +"Source\LifePlayEditorTools\LifePlayEditorTools.cpp","2D8F1D5EB2376E01471CDA3075D6BB39" +"Source\LifePlayEditorTools\LifePlayEditorTools.h","029166EDCA1171777C7D11753EB26135" +"Source\LifePlayEditorTools\LPCheckMeshAssignmentCommandlet.cpp","32982D42379C0F1C8700FA1C4FD068C8" +"Source\LifePlayEditorTools\LPCheckMeshAssignmentCommandlet.h","1669DA2BDECEADB3963767241EEC77F1" +"Source\LifePlayEditorTools\LPDumpFunctionCommandlet.cpp","95911907CFB780F12A488ED3D9FA6087" +"Source\LifePlayEditorTools\LPDumpFunctionCommandlet.h","277583C263A1B713EF29F9B4085E4141" +"Source\LifePlayEditorTools\LPFixAssetRegistryNodesCommandlet.cpp","3492728ED44F8891C9B041680F29238E" +"Source\LifePlayEditorTools\LPFixAssetRegistryNodesCommandlet.h","E7258F871DB7C4EAC79903E3C1F8244B" +"Config\DefaultEditor.ini","E1C06D85AE7B8B032BEF47E42E4C08F9" +"Config\DefaultEditorSettings.ini","85D82E7F468DFD0E2F9CF01B0CE4180F" +"Config\DefaultEngine.ini","F44A563DC0494F0AC28FAD03F1984F20" +"Config\DefaultGame.ini","B228BAC80B86CC2658DFAE63299234F7" +"Config\DefaultInput.ini","6A2FD952EDD1CA690D8116FF9A170B97" +"Saved\StagedBuilds\WindowsNoEditor\LifePlay\LifePlay.uproject","FBFE551A9AAAC792831265D005EB5A1B" +"LifePlay.uproject","FBFE551A9AAAC792831265D005EB5A1B" +"Content\BPs\AI.uasset","341758A98A097201ECDBD4D031191F7E" +"Content\BPs\Birdview.uasset","165BCD38644274554FB9BCE6085A2C34" +"Content\BPs\BridgetBP.uasset","E7652DE8C49302E9BA1ABADB2579D9D0" +"Content\BPs\CameraShake.uasset","5003DF2BCA3D1B6289B6B4D426EE1FF9" +"Content\BPs\CityExpansion.uasset","ED42C5FFE674836DE4C0E37330210A47" +"Content\BPs\Daily_F.uasset","73710EF7953B4B669EB727EA60BF2C5D" +"Content\BPs\Daily.uasset","BE041A5D36D0FE33623F965215823AF7" +"Content\BPs\FirstPerson.uasset","31DA9FC9F35A39A3B6F30C52E094B8B1" +"Content\BPs\FullScreenMode.uasset","2F6302A908C6E289F642DC47DEA712D2" +"Content\BPs\GameSettings.uasset","215A4A275CBABC445582448EDD72F4BF" +"Content\BPs\GI.uasset","F4550DA5DC05FC005400CDCA2FC123C9" +"Content\BPs\GM.uasset","B405F71C079A5E096CB42BE0A82357C8" +"Content\BPs\HISM.uasset","432C25D8E1AB78302629513BF4760664" +"Content\BPs\LightSource.uasset","7199F4425B77F9C482D9DBD830DA7584" +"Content\BPs\MapMarkers.uasset","01E1332B963EA8BF3AFE11A52D2FB713" +"Content\BPs\MapStreets.uasset","FE4A8F0E6DB4B1330EADD28955D9780D" +"Content\BPs\Pawn.uasset","A756ACBFF131BADE059F266313012480" +"Content\BPs\PC.uasset","5AAF881F8CF8C2EB90AEAAA3C34C0823" +"Content\BPs\Person.uasset","A1720BE06E9AC148B119206D097849C0" +"Content\BPs\Room.uasset","8153BEA45D8C4E5AE03CBE275BEEF939" +"Content\BPs\Save.uasset","DCFEDD6DB4741B4653528B076EFCF07F" +"Content\BPs\SecondScreenFloor.uasset","88906942B09A15DD9096EB088B96526D" +"Content\BPs\SkyBox.uasset","AF6433382F8209047CB1DF9419234C69" +"Content\BPs\StreetMap_Static.uasset","EFB4B8C38F2BDC892630D0E3F599DEAC" +"Content\BPs\TestBall.uasset","AAF7E7F14EF130B96858031CCA9442A8" +"Content\BPs\TestPerson.uasset","A7D0895EE3FB64C61C2D81169CE9F77C" +"Content\BPs\TestStatic.uasset","F526A7B176D222DBABBA565B76B4DC2E" +"Content\Structs\Achievement.uasset","C992A741D1506D38FACAC9178405B7C6" +"Content\Structs\AchievementType.uasset","AFD7DAD36FDF33D0599E9B2995E7C117" +"Content\Structs\ActionDetail.uasset","8F4E5F2EBBA4212180124646EE5294F9" +"Content\Structs\ActorVar.uasset","5B7D636A8340BE8443A21204AF785380" +"Content\Structs\ActorVars.uasset","C804191C42CAE581EEF1A38EB12B6FB3" +"Content\Structs\AmenityAction.uasset","05F8DCFF29E0D882546785EE6CE58427" +"Content\Structs\AmenityImg.uasset","75C57518268190762F4F5E12DD621962" +"Content\Structs\AmenityPresets.uasset","920AD3AC53D6B53B2438765C0A258FA9" +"Content\Structs\Anim.uasset","55D571DB19361C4C6C00F478E6C1EAB6" +"Content\Structs\BuildingUntil.uasset","A0359139AE7554C7EA948EDB476E266F" +"Content\Structs\Business.uasset","CB03C29F9DA00F21B0CC3EC083484A76" +"Content\Structs\ChanceMinMax.uasset","76472A6B4CE7F81A202E30A69B213A87" +"Content\Structs\ChancePreset.uasset","AE3933ACCD22D3B6903403A4EF17000E" +"Content\Structs\ChangeOverTime.uasset","AABFBE93F2B23D7C73EEDA4F47FE5F5D" +"Content\Structs\City.uasset","040B6851FAA804764E3B962CE6473D5D" +"Content\Structs\Cloth.uasset","0F7B8DBCA7A12848FE6E4AF8F0D70D01" +"Content\Structs\ConditionDesc.uasset","7E4BD92319F39ADF50DE3273A81C7CD5" +"Content\Structs\ConditionDirtyTalks.uasset","A4BC24710E0CEE35496D971F4899AA8E" +"Content\Structs\Custom.uasset","84DFA926AB8EEF64F3F3436D8FB4D774" +"Content\Structs\DelayedChange.uasset","A78C00A53BD89A4F43ACE2A1C3427F1D" +"Content\Structs\Effect.uasset","0722AE634AA9CFAAA1C307197451D66D" +"Content\Structs\Employee.uasset","5D1AC0B23A3AB2581833EF1C6A3583AD" +"Content\Structs\Favorite.uasset","218FCB072845325780C6CC06BC72EA8D" +"Content\Structs\FloatArray.uasset","C8BF18BDAE94DAC42B89731EA8215C22" +"Content\Structs\IntArray.uasset","F1D0415D5A2C875EACC1B53C3A43845D" +"Content\Structs\IntStrings.uasset","C1446103E0B7413888A5DAAE6A74AC94" +"Content\Structs\Inventory.uasset","DF440732D9443672372666E9163C88E3" +"Content\Structs\Major.uasset","03BF5CE8471BF538E0F45F2308F4D778" +"Content\Structs\MaterialArray.uasset","FA726C338D19F4CDCE4473CD9D8392FC" +"Content\Structs\MeshSexRace.uasset","5A32905F9B6831B71D971E535B2F2EF4" +"Content\Structs\ModEnabled.uasset","3D6A761C3F96D2E60A3DB451CAC475C1" +"Content\Structs\Month.uasset","6BE81162D03F8BF747E1BDACB31D0740" +"Content\Structs\MorphSlider.uasset","BAF2379F2B479AC5BC05608D2DF045D5" +"Content\Structs\NameFloat.uasset","AC384044C4D9650007E66DC6A493F8DC" +"Content\Structs\NameText.uasset","5C05DB9CF63459DD4A76301D935DE65F" +"Content\Structs\Perk.uasset","1E170B6584FFAF2DFEABC8FB3596DCF8" +"Content\Structs\PersonData.uasset","7AF264F35A4AA977D4467CE2D0DFC37C" +"Content\Structs\PlaceBuilding.uasset","81603E3334B4DDD1145A8E052F6FEFC7" +"Content\Structs\Pregnancy.uasset","D277AD5B370DCBF8888F494AB84AD236" +"Content\Structs\Quest.uasset","477C37BD91E794DAF06AD6CB34F76DF3" +"Content\Structs\RelationshipPersons.uasset","9AA652598D14B1DFFB989E2491023687" +"Content\Structs\Room.uasset","A5D95478EFC3F14E0CCEBBEC7D86A510" +"Content\Structs\RoomObject.uasset","85C9A023D3EBF50A3CFD263428789130" +"Content\Structs\RoomObjectMat.uasset","C84815442DDB5802C4E9E3B028925F47" +"Content\Structs\Scene.uasset","3CEA006FB4A0E488A5A4D2C99727EE44" +"Content\Structs\SMBool.uasset","53F589C549AE60BEA88CEDC361CFBF48" +"Content\Structs\SMBools.uasset","DCD0105753EC89059AD90D205C78303F" +"Content\Structs\StatValue.uasset","F642007100252A4DF63BE173E9D8CC8F" +"Content\Structs\StringArray.uasset","272EC06A93808492F928702980A20CC5" +"Content\Structs\StringArrayArray.uasset","2A03802C9E0E52A8503CAA9558D7CF82" +"Content\Structs\StringsString.uasset","F7CC742565391C6E010FF83D224FD2AB" +"Content\Structs\StringString.uasset","5BA071D7F66037B4D35D1A0B0BAD23BF" +"Content\Structs\StringWindowMode.uasset","F7A4FCE6EB9ED6D9463B9655A6E74C8E" +"Content\Structs\Te2dArray.uasset","00000A79F35D50CDC0B43C9CB0AFBFE7" +"Content\Structs\Toy.uasset","6C192BBA32A3042AD5B13A406C552EF7" +"Content\Structs\Toys.uasset","1A546CC2D75C6F60DAE129529E9EFB13" +"Content\Structs\Variable.uasset","27F930AE64B75D9069FE06673CE59DE9" +"Plugins\ModdingExtra\Source\ModdingExtra\ModdingExtra.Build.cs","E12CEE99CFE17C2EAC9D00FDFBEF438A" +"Plugins\ModdingExtra\Source\ModdingExtra\Private\ModdingExtra.cpp","D1EAC7319F5573F8DCCE0B7173CB0C01" +"Plugins\ModdingExtra\Source\ModdingExtra\Private\ModdingExtraBPLibrary.cpp","967F2FCD6AA776129088710AFDCB4556" +"Plugins\ModdingExtra\Source\ModdingExtra\Public\ModdingExtra.h","47F7D5781DE76273412C185B6A0E27D9" +"Plugins\ModdingExtra\Source\ModdingExtra\Public\ModdingExtraBPLibrary.h","891BAA3E8F00576640B408DFF53D4CDE" +"Plugins\StreetMap\Source\StreetMapImporting\OSMFile.cpp","1FD7861E3AE128EC5077FF1A0F28D8CF" +"Plugins\StreetMap\Source\StreetMapImporting\OSMFile.h","A8A50E194FE24066151C8EA2CB2104B2" +"Plugins\StreetMap\Source\StreetMapImporting\StreetMapActorFactory.cpp","7B39C2ED7AED6292DD400928FFBA8E20" +"Plugins\StreetMap\Source\StreetMapImporting\StreetMapActorFactory.h","2A6F6F52A4DBD809701C02F559A86656" +"Plugins\StreetMap\Source\StreetMapImporting\StreetMapAssetTypeActions.cpp","D7A78B55C89CAE513E4BDC92D025C219" +"Plugins\StreetMap\Source\StreetMapImporting\StreetMapAssetTypeActions.h","5FF0655ADADE84E0E02A5E04ABF3F5F0" +"Plugins\StreetMap\Source\StreetMapImporting\StreetMapComponentDetails.cpp","7C1C7E63728B14A784A6D4FFE0F2A625" +"Plugins\StreetMap\Source\StreetMapImporting\StreetMapComponentDetails.h","66A7B34E34B726C6006C46F42A3DAF56" +"Plugins\StreetMap\Source\StreetMapImporting\StreetMapFactory.cpp","50266E954AEB477ACEAD9C6D7370C2D3" +"Plugins\StreetMap\Source\StreetMapImporting\StreetMapFactory.h","D2D2ED8AED5216F164CFAAB627E88EB6" +"Plugins\StreetMap\Source\StreetMapImporting\StreetMapImporting.Build.cs","C0B90E529365F96CF9A7ADFDEB88E584" +"Plugins\StreetMap\Source\StreetMapImporting\StreetMapImporting.cpp","442353C1264DB30524C659E9CB0833F7" +"Plugins\StreetMap\Source\StreetMapImporting\StreetMapImporting.h","9C25569AD99FB40FBBC7453250AAF9E6" +"Plugins\StreetMap\Source\StreetMapImporting\StreetMapReimportFactory.cpp","57CCD631D684AF18D7ABA95AF957953C" +"Plugins\StreetMap\Source\StreetMapImporting\StreetMapReimportFactory.h","649EAE4BD1A58221E7E64BFA61166643" +"Plugins\StreetMap\Source\StreetMapImporting\StreetMapStyle.cpp","F10B466C8E6F8069EB3CA30D0A00FDAF" +"Plugins\StreetMap\Source\StreetMapImporting\StreetMapStyle.h","78438314B341E2DB0E5BE416EB89C963" +"Plugins\StreetMap\Source\StreetMapRuntime\PolygonTools.cpp","106C3C45F3DE97D5770E7B9256122C6D" +"Plugins\StreetMap\Source\StreetMapRuntime\PolygonTools.h","490AA08DBF84E886F3759A3789542B5A" +"Plugins\StreetMap\Source\StreetMapRuntime\StreetMap.cpp","E2FCDD1608893131997E867E0809A513" +"Plugins\StreetMap\Source\StreetMapRuntime\StreetMapActor.cpp","D4774E7614FE8C8DBE89B08EA9FCE3C9" +"Plugins\StreetMap\Source\StreetMapRuntime\StreetMapComponent.cpp","321A5A559A680DD2976471EECC7FC599" +"Plugins\StreetMap\Source\StreetMapRuntime\StreetMapRuntime.Build.cs","8E7ED94537AD5F7467792B4230C3774A" +"Plugins\StreetMap\Source\StreetMapRuntime\StreetMapRuntime.cpp","215FE6D5E8C296B63120AFA942510CE0" +"Plugins\StreetMap\Source\StreetMapRuntime\StreetMapRuntime.h","D6741A48DB3E9E75CC3B1204152CE525" +"Plugins\StreetMap\Source\StreetMapRuntime\StreetMapSceneProxy.cpp","EB90E12EC01E3E9E30571FE291D53632" +"Plugins\StreetMap\Source\StreetMapRuntime\StreetMapSceneProxy.h","A6CCCD605526E65793FBC25A5E0A4CE7" +"Plugins\StreetMap\Source\StreetMapRuntime\Public\StreetMap.h","B4EE4ECCB6A1AB7780249FDBE89CD00F" +"Plugins\StreetMap\Source\StreetMapRuntime\Public\StreetMapActor.h","DF5C3F0A7379A8F8506673809C3F78C2" +"Plugins\StreetMap\Source\StreetMapRuntime\Public\StreetMapComponent.h","9DE4A379EB003FA7CE90C6ABCDE41D8E" diff --git a/Tools/CheckIntegrity.ps1 b/Tools/CheckIntegrity.ps1 new file mode 100644 index 0000000..488ee41 --- /dev/null +++ b/Tools/CheckIntegrity.ps1 @@ -0,0 +1,87 @@ +<# +.SYNOPSIS + Tests statiques d'integrite T-STAT-02 a T-STAT-04 (Docs/Migration/03_Plan_Migration_Tests.md). + +.DESCRIPTION + -Modules : Content/Modules 5.5 identique a 4.27 (liste et MD5). + -Env : environnement de developpement identique au manifeste du lot L0. + -Ref427 : arbre 4.27 inchange depuis l'empreinte de reference. + -InitRef427 : cree l'empreinte de reference 4.27 (a faire une seule fois, en L0). + Code de sortie 1 si un test echoue. + +.EXAMPLE + .\Tools\CheckIntegrity.ps1 -Modules -Env -Ref427 +#> +param( + [switch]$Modules, + [switch]$Env, + [switch]$Ref427, + [switch]$InitRef427, + [string]$ProjectRoot = (Split-Path $PSScriptRoot -Parent), + [string]$Root427 = 'D:\Game\LifePlay-master 4.27', + [string]$BackupRoot = 'D:\Game\LifePlay_Backup_5.5' +) +$ErrorActionPreference = 'Stop' +$refCsv = Join-Path $ProjectRoot 'Docs\Migration\etat\L0_ref427.csv' +$failed = 0 + +function Hash-Tree([string]$Base, [string[]]$Rel) { + foreach ($r in $Rel) { + $p = Join-Path $Base $r + if (-not (Test-Path $p)) { continue } + Get-ChildItem $p -File -Recurse -Force | ForEach-Object { + [pscustomobject]@{ Rel = $_.FullName.Substring($Base.TrimEnd('\').Length + 1); MD5 = (Get-FileHash $_.FullName -Algorithm MD5).Hash } + } + } +} + +function Report([string]$Name, [object[]]$Diffs, [int]$Total) { + if ($Diffs) { + $script:failed++ + "ECHEC $Name : $(@($Diffs).Count) ecart(s) sur $Total" + $Diffs | Select-Object -First 20 | ForEach-Object { " $_" } + } else { "OK $Name : $Total fichier(s) conformes" } +} + +$refSet = @('Source', 'Config', 'LifePlay.uproject', 'Content\BPs', 'Content\Structs', 'Plugins\ModdingExtra\Source', 'Plugins\StreetMap\Source') + +if ($InitRef427) { + if (Test-Path $refCsv) { throw "Empreinte deja presente : $refCsv (supprimer volontairement pour la refaire)" } + Hash-Tree $Root427 $refSet | Export-Csv $refCsv -NoTypeInformation -Encoding UTF8 + "Empreinte 4.27 ecrite : $refCsv" +} + +if ($Modules) { + $a = Hash-Tree $Root427 @('Content\Modules'); $b = Hash-Tree $ProjectRoot @('Content\Modules') + $ha = @{}; $a | ForEach-Object { $ha[$_.Rel] = $_.MD5 } + $hb = @{}; $b | ForEach-Object { $hb[$_.Rel] = $_.MD5 } + $keys = @($ha.Keys) + @($hb.Keys) | Sort-Object -Unique + $d = $keys | Where-Object { $ha[$_] -ne $hb[$_] } | ForEach-Object { if (-not $ha[$_]) { "en plus en 5.5 : $_" } elseif (-not $hb[$_]) { "absent en 5.5 : $_" } else { "different : $_" } } + Report 'T-STAT-02 Modules = 4.27' $d $keys.Count +} + +if ($Env) { + $man = Join-Path $BackupRoot 'L0\manifest.csv' + $rows = Import-Csv $man | Where-Object { $_.Rel -match '^(\.claude\\|\.mcp\.json$|Saved\\Backups\\|Saved\\SaveGames\\)' } + $d = foreach ($r in $rows) { + $p = Join-Path $ProjectRoot $r.Rel + if (-not (Test-Path -LiteralPath $p)) { "absent : $($r.Rel)" } + elseif ((Get-FileHash -LiteralPath $p -Algorithm MD5).Hash -ne $r.MD5) { + # Les .sav changent quand on joue : signales mais non bloquants + if ($r.Rel -like 'Saved\SaveGames\*') { Write-Host " (info) sauvegarde de jeu modifiee : $($r.Rel)" } else { "modifie : $($r.Rel)" } + } + } + Report 'T-STAT-03 environnement = L0' $d @($rows).Count +} + +if ($Ref427) { + if (-not (Test-Path $refCsv)) { throw "Pas d'empreinte 4.27 : lancer -InitRef427 d'abord" } + $ref = Import-Csv $refCsv + $cur = @{}; Hash-Tree $Root427 $refSet | ForEach-Object { $cur[$_.Rel] = $_.MD5 } + $d = @($ref | Where-Object { $cur[$_.Rel] -ne $_.MD5 } | ForEach-Object { "modifie ou absent : $($_.Rel)" }) + $known = @{}; $ref | ForEach-Object { $known[$_.Rel] = 1 } + $d += @($cur.Keys | Where-Object { -not $known[$_] } | ForEach-Object { "nouveau : $_" }) + Report 'T-STAT-04 arbre 4.27 inchange' $d @($ref).Count +} + +if ($failed) { exit 1 } diff --git a/Tools/LogStats.ps1 b/Tools/LogStats.ps1 new file mode 100644 index 0000000..c38e7e8 --- /dev/null +++ b/Tools/LogStats.ps1 @@ -0,0 +1,76 @@ +<# +.SYNOPSIS + Compteurs normalises d'un journal LifePlay, ou comparaison A/B de deux journaux. + +.DESCRIPTION + Reconnait les messages anglais (4.27) et francais (editeur 5.5 localise). + Normalise par le nombre de personnages generes (lignes "index SPAWN"), + selon le protocole du rapport du 2026-09-28 (paragraphe 8). + +.EXAMPLE + .\Tools\LogStats.ps1 Saved\Logs\LifePlay.log + .\Tools\LogStats.ps1 -Compare D:\Game\LifePlay_Build_427_Dev\WindowsNoEditor\LifePlay\Saved\Logs\LifePlay.log, Saved\Logs\LifePlay.log +#> +param( + [Parameter(Position = 0)][string]$Log, + [string[]]$Compare, + [int]$Top = 15 +) +$ErrorActionPreference = 'Stop' + +$reNone = 'Accessed None trying to read property (\w+)|Acc[eè]s [aà] None, tentative de lecture de la propri[eé]t[eé] (\w+)' + +function Get-LogStats([string]$Path) { + $lines = [IO.File]::ReadAllLines((Resolve-Path $Path)) + $spawnLines = $lines -match 'index SPAWN' + $spawnActors = $spawnLines | ForEach-Object { if ($_ -match '\] (Person_C_\d+) index SPAWN') { $Matches[1] } } | Sort-Object -Unique + $noneProps = foreach ($l in $lines) { if ($l -match $reNone) { if ($Matches[1]) { $Matches[1] } else { $Matches[2] } } } + $noneMesh = @($noneProps | Where-Object { $_ -match 'mesh' }).Count + $files = @{} + foreach ($l in ($lines -match "GetAllFilesFromFolder \| '([^']+)' ext='([^']+)' -> (\d+)")) { + if ($l -match "GetAllFilesFromFolder \| '([^']+)' ext='([^']+)' -> (\d+)") { $files["$($Matches[1]) $($Matches[2])"] = [int]$Matches[3] } + } + $n = [math]::Max(1, $spawnLines.Count) + [pscustomobject]@{ + Fichier = $Path + Lignes = $lines.Count + Personnages = $spawnLines.Count + ActeursDistincts = @($spawnActors).Count + AccessedNone = @($noneProps).Count + AccessedNoneMaillage = $noneMesh + NoneMaillageParPerso = [math]::Round($noneMesh / $n, 2) + NoSkeletalMesh = @($lines -match 'No SkeletalMesh').Count + IndexHorsBornes = @($lines -match 'Attempted to access index|Tentative d.acc[eè]s [aà] l.index|from array .* of length').Count + LoadTxtOK = @($lines -match 'LoadTxt OK').Count + LoadTxtEchec = @($lines -match 'LoadTxt (ECHEC|FAIL)').Count + LogClassError = @($lines -match 'LogClass: Error').Count + FailedToLoad = @($lines -match "Failed to load '/Game/").Count + Fatal = @($lines -match 'Fatal error|LogWindows: Error: ===').Count + Erreurs = @($lines -match ': Error: ').Count + Avertissements = @($lines -match ': Warning: ').Count + LogLifePlay = @($lines -match 'LogLifePlay').Count + TraceModding = @($lines -match 'LogLPModdingTrace').Count + _Proprietes = $noneProps | Group-Object | Sort-Object Count -Descending | Select-Object -First $Top Count, Name + _Fichiers = $files + } +} + +function Show([object]$s) { + $s | Select-Object * -ExcludeProperty _* | Format-List + "Acces a None par propriete ($Top premieres) :" + $s._Proprietes | Format-Table -AutoSize +} + +if ($Compare) { + if ($Compare.Count -ne 2) { throw '-Compare attend exactement deux journaux : reference, cible' } + $a = Get-LogStats $Compare[0]; $b = Get-LogStats $Compare[1] + $props = ($a | Select-Object * -ExcludeProperty _*, Fichier).PSObject.Properties.Name + "A = $($Compare[0])`nB = $($Compare[1])`n" + $props | ForEach-Object { [pscustomobject]@{ Mesure = $_; A = $a.$_; B = $b.$_ } } | Format-Table -AutoSize + "Fichiers enumeres (GetAllFilesFromFolder) qui different :" + $keys = @($a._Fichiers.Keys) + @($b._Fichiers.Keys) | Sort-Object -Unique + $diff = $keys | Where-Object { $a._Fichiers[$_] -ne $b._Fichiers[$_] } | ForEach-Object { [pscustomobject]@{ Dossier = $_; A = $a._Fichiers[$_]; B = $b._Fichiers[$_] } } + if ($diff) { $diff | Format-Table -AutoSize } else { " aucun ($($keys.Count) enumerations identiques)" } +} elseif ($Log) { + Show (Get-LogStats $Log) +} else { throw 'Indiquer un journal, ou -Compare reference,cible' }