L0 : documentation de migration et outillage de test
Docs/Migration : architecture initiale (pipeline donnees -> GI -> evenements/personnages), audit logiciel 5.5, plan de tests, cahier des charges par lots bornes, journal des modifications, registre des erreurs. Tools : CheckIntegrity (T-STAT-02..04), LogStats (compteurs normalises, A/B 4.27/5.5). Empreinte de reference de l'arbre 4.27. Tests : aller-retour Snapshot/Restore verifie par MD5 ; T-STAT-02, 03, 04 au vert ; T-STAT-01 : 1 package UE4 (GI.uasset), traite en L1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
1122e17fa6
commit
39fac16216
10 changed files with 1007 additions and 0 deletions
183
Docs/Migration/01_Architecture_Initiale.md
Normal file
183
Docs/Migration/01_Architecture_Initiale.md
Normal file
|
|
@ -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/<id>/<id>.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/<slot>.sav` | `Save_C` (137 variables) | jour, heure, `GeneratedIndex`, relations, `ActorVars`, `GlobalVariables`, grossesses, IA… | `SaveGame` / `LoadGame` / `NewGame` |
|
||||
| `Content/Saves/<slot>/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/<id>", *.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<Variable>)
|
||||
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/<GeneratedIndex>.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/<slot>/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<string,?>`).
|
||||
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`.
|
||||
174
Docs/Migration/02_Audit_Logiciel.md
Normal file
174
Docs/Migration/02_Audit_Logiciel.md
Normal file
|
|
@ -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 |
|
||||
129
Docs/Migration/03_Plan_Migration_Tests.md
Normal file
129
Docs/Migration/03_Plan_Migration_Tests.md
Normal file
|
|
@ -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\<lot>\` |
|
||||
|
||||
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 <journal>` | 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 <journal 4.27> <journal 5.5>` 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/<lot>_run_<date>.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 -- <chemins>` ou `git revert <commit>` |
|
||||
| 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 <chemin>` |
|
||||
|
||||
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 |
|
||||
134
Docs/Migration/04_Cahier_Des_Charges.md
Normal file
134
Docs/Migration/04_Cahier_Des_Charges.md
Normal file
|
|
@ -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 <tous les fichiers visés>` (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) |
|
||||
26
Docs/Migration/Journal_Modifications.md
Normal file
26
Docs/Migration/Journal_Modifications.md
Normal file
|
|
@ -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\<lot>\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.
|
||||
27
Docs/Migration/README.md
Normal file
27
Docs/Migration/README.md
Normal file
|
|
@ -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.
|
||||
26
Docs/Migration/Registre_Erreurs.md
Normal file
26
Docs/Migration/Registre_Erreurs.md
Normal file
|
|
@ -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 |
|
||||
145
Docs/Migration/etat/L0_ref427.csv
Normal file
145
Docs/Migration/etat/L0_ref427.csv
Normal file
|
|
@ -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"
|
||||
|
87
Tools/CheckIntegrity.ps1
Normal file
87
Tools/CheckIntegrity.ps1
Normal file
|
|
@ -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 }
|
||||
76
Tools/LogStats.ps1
Normal file
76
Tools/LogStats.ps1
Normal file
|
|
@ -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' }
|
||||
Loading…
Reference in a new issue