11 KiB
Fiche MAPDL1-E5 — Niveau N3 — Modèle prévu sonnet (agent lp-impl ; escalade lp-impl-max) — Agent lp-impl — Skills sk-protocol, lp-city, lp-lot, ue-cpp-build
MAPDL1-E5 : téléchargement et installation des packs dans le jeu (C6 de MAPDL1-SPEC-05 v3)
GO de Big Boss. Ce lot fait partie de la réalisation approuvée par l'utilisateur, citée : « Oui : SPEC-05 v3 approuvée (S5-1 à S5-5, D10 = téléchargement HTTP dans le jeu avec navigateur en recours, D11 = un zip par pack). Lance la réalisation avec les modèles réduits ; l'hébergeur et le domaine, je les choisis plus tard. »
Hors moteur :
- aucune compilation (E2 bis, sous jeton, plus tard), aucun commandlet, aucun éditeur ;
- aucun appel réseau réel ;
- aucun commit, aucun Blueprint ;
- rien sous
Mods\.
À lire d'abord :
MAPDL1-SPEC-05-v3.md(§ 1 à 4) etMAPDL1-SPEC-05-v2.md(§ 2 : fenêtre, licence, accord, deux boutons) ;MAPDL1-E1-IMPL.mdetMAPDL1-E3-VAL.md;- le code d'E1 :
Source/LifePlay/LPCityMapsSubsystem.h/.cpp; - le modèle de fenêtre :
Source/LifePlay/LPModInfoSubsystem.cpp:375-422(ShowWarning,AddViewportWidgetContent).
0. Avant toute écriture
- Instantané
.\Tools\Snapshot.ps1 -Lot MAPDL1-E5 -Path <chemin>, depuis pwsh, un chemin par appel, pour chaque fichier du § 1. - MD5 avant et après de tous ces fichiers, et MD5 des fichiers de ville de STM1 (
LPCityWater*,LPCityNames*,LPCityHouses.h,LPCityLandmarks.h,LPAssetRegistryHelpers.*) : ils doivent rester inchangés. git status --shortsur les fichiers du § 1.
1. Fichiers (et seulement ceux-là)
| Fichier | État | Contenu |
|---|---|---|
Source/LifePlay/LPCityMapsDownload.h/.cpp |
A | téléchargement, contrôle et pose (§ 2.2 à 2.5), sans dépendance à l'UI |
Source/LifePlay/LPCityMapsWindow.h/.cpp |
A | fenêtre Slate (§ 2.1), sur le modèle de LPModInfoSubsystem::ShowWarning |
Source/LifePlay/LPCityMapsSubsystem.h/.cpp |
M | le clic d'une ligne téléchargeable ouvre la fenêtre au lieu du navigateur ; nouvel état RestartRequired (§ 2.6) |
Source/LifePlay/LifePlay.Build.cs |
M | PrivateDependencyModuleNames : "HTTP", "OpenSSL", "libzip" (commentaire « Lot MAPDL1 (E5) ») |
Content/Data/Licenses/OpenStreetMap_Geodata_License.txt et Content/Data/Licenses/Vinfamy_License.txt |
A | copies à l'octet de Licenses/… (MD5 identiques), pour qu'elles soient livrées dans le pak (le dossier Licenses/ ne l'est pas dans la build) |
Content/Data/LPCityMaps.json |
M | licences.*.fichier devient Data/Licenses/<nom> ; rien d'autre ne change |
Conventions : style des fichiers voisins (commentaires en français sans accents), outil Edit pour modifier, Write pour les fichiers neufs, LF.
2. Contenu
2.1 Fenêtre « City map: » (Slate, en anglais, ordre Z élevé, fermable)
- Informations : ville, version, taille en Mo, hôte de
urls[0](seulement le nom d'hôte), provenance (source), et « Active after the next game launch ». - Licence : les
titredeslicencesde l'entrée. Le bouton « Read the full licence » affiche dans la fenêtre, avec défilement, le texte deFPaths::ProjectContentDir()/<fichier>. Fichier absent : « Licence text not found: ». - Case « I have read and accept the licence of this map », non cochée. Les deux boutons d'action restent désactivés tant qu'elle n'est pas cochée.
- Boutons : « Download only », « Full install », « Cancel ».
- Progression : barre, octets reçus / octets totaux, débit, « Cancel » qui interrompt. Le
.partest gardé pour une reprise. - Messages :
- erreur en clair (« Download failed: … », « SHA-256 mismatch », « Install failed: … ») ;
- réussite « Downloaded: » avec un bouton « Open folder » (
FPlatformProcess::ExploreFolder) ; - réussite « Installed. Restart the game to play . ».
- Recours quand toutes les URL ont échoué : bouton « Open in browser » (
page, sinonurls[0], parFPlatformProcess::LaunchURL), puis surveillance du dossier Téléchargements (§ 2.5), plus un bouton « Choose file… » (§ 2.5). - Une seule fenêtre à la fois ; un seul téléchargement à la fois.
2.2 Téléchargement HTTP (FHttpModule, IHttpRequest)
| Point | Règle |
|---|---|
| Fichier partiel | FPaths::ProjectSavedDir()/Downloads/<pack>/<zip>.part. Écriture en flux par SetResponseBodyReceiveStream (IHttpRequest.h:271), sur un FArchive ouvert en ajout (IFileManager::CreateFileWriter, drapeau d'ajout) |
| Reprise | .part présent de taille t > 0 : SetHeader("Range", "bytes=t-") (IHttpRequest.h:297). Réponse 206 avec un Content-Range qui commence à t : on continue. Réponse 200 : le .part est déplacé dans Saved/Downloads/_rejet/ (horodaté) et le téléchargement repart de zéro, dans un fichier neuf |
| Progression | OnRequestProgress64 (IHttpRequest.h:366) |
| Délais | SetActivityTimeout(30) (IHttpRequest.h:328) ; aucun délai total |
| Essais | 3 par URL, avec 2, 4 puis 8 s d'attente (ticker FTSTicker, sans bloquer le fil de jeu), puis l'URL suivante. Statut hors 200 et 206, ou taille finale différente d'octets : essai suivant |
| Redirections | à vérifier dans les sources du moteur 5.8 : quel client HTTP sert Win64 (Curl, ou WinHttp ; voir Engine/Source/Runtime/Online/HTTP/HTTP.Build.cs et …/Private/Windows/) et s'il suit les redirections (Curl : CURLOPT_FOLLOWLOCATION posé à 1, …/Private/Curl/CurlHttp.cpp:183). Citer fichier:ligne dans l'IMPL. Le journal donne l'URL finale si l'API la fournit (GetEffectiveURL ou équivalent, à vérifier) |
| Sûreté | URL https:// seulement (déjà filtrées par l'index) ; en-tête User-Agent: LifePlay-CityMaps/1.0 ; aucune donnée du joueur envoyée |
| Journal | [LPCity] DOWNLOAD <ville> : <url> statut <n> octets <recus>/<total> (reprise a <t>), et … : echec <raison> |
2.3 Contrôle SHA-256 (OpenSSL, par morceaux)
- Module
OpenSSLdu moteur (Engine/Source/ThirdParty/OpenSSL, 1.1.1t ; E0 Q4).#include "openssl/evp.h"entreTHIRD_PARTY_INCLUDES_STARTetTHIRD_PARTY_INCLUDES_END, puisEVP_MD_CTX_new,EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr),EVP_DigestUpdatepar blocs de 1 Mio lus avecIFileManager::CreateFileReader,EVP_DigestFinal_exetEVP_MD_CTX_free. - Le calcul se fait hors du fil de jeu (
Async(EAsyncExecution::ThreadPool, …)), avec un retour sur le fil de jeu (AsyncTask(ENamedThreads::GameThread, …)). - Comparaison sans tenir compte de la casse avec
sha256de l'index. - En cas d'écart : le fichier est déplacé dans
Saved/Downloads/_rejet/et le jeu passe à l'URL suivante. - Journal :
[LPCity] SHA256 <ville> : <valeur> conforme|ECART.
2.4 « Download only » et « Full install »
- Download only : quand le téléchargement est complet et conforme,
<zip>.partest renommé enSaved/Downloads/<zip>. La ville reste « téléchargeable ». - Un
Saved/Downloads/<zip>déjà présent, de la bonne taille et au bon SHA-256 (recontrôlé), sert directement : aucun nouveau téléchargement. - Full install : la même chose, puis la pose :
- refus dans l'éditeur (
GIsEditor) : « Full install is only available in the packaged game ». La copie de travail ne doit jamais recevoir de pack dansMods\; - ouverture du zip par libzip (
zip_openen lecture seule) et contrôle des membres :- chaque nom commence par
LifePlay/Mods/<pack>/ouLifePlay/Content/Modules/<pack>/, ou vautREADME.txt(ignoré) ; - aucun
.., aucun\, aucun chemin absolu, aucun autre préfixe ; - le membre
LifePlay/Mods/<pack>/<pack>.upluginest présent ; - sinon : refus, et rien n'est posé ;
- chaque nom commence par
- extraction dans
Saved/Downloads/<pack>/_pose/(dossier neuf), puis destinations :FPaths::ProjectDir()+ le chemin du membre sans le préfixeLifePlay/; - une installation existante de ce pack (
Mods/<pack>ouContent/Modules/<pack>) est d'abord déplacée dansSaved/Downloads/_ancien/<pack>-<horodatage>/; Content/Modules/<pack>est posé en premier,Mods/<pack>en dernier, parIFileManager::Move;- retour en arrière si une étape échoue : les déplacements déjà faits sont défaits dans l'ordre inverse, puis l'ancienne installation est remise. Rien n'est jamais supprimé (
_pose/reste, et sert de trace) ; - journal
[LPCity] INSTALL <ville> : <n> fichiers poses (Modules puis Mods), ou… : echec <raison>, retour arriere <ok|ECHEC>.
- refus dans l'éditeur (
2.5 Recours (c), quand toutes les URL échouent
- « Open in browser » :
page, sinonurls[0]. - Surveillance du dossier Téléchargements de Windows, tant que la fenêtre est ouverte, toutes les 2 s :
- le dossier se trouve par
SHGetKnownFolderPath(FOLDERID_Downloads)(sousPLATFORM_WINDOWS, avecWindows/AllowWindowsPlatformTypes.h) ; - un fichier
.zipde taille exactementoctets, au SHA-256 conforme, est copié (le fichier du joueur reste) versSaved/Downloads/<zip>; - ensuite, comme 2.4 (« Download only » ou « Full install » selon le bouton choisi).
- le dossier se trouve par
- « Choose file… » : sélecteur de fichier Win32 (
GetOpenFileNameW,commdlg.h, sousPLATFORM_WINDOWS) ; même contrôle, puis même suite. Si son usage en Shipping pose un problème de liaison, laisser le bouton désactivé avec un commentaire, et le signaler dans l'IMPL.
2.6 Changements dans LPCityMapsSubsystem
ELPCityMapStatereçoitRestartRequired, aprèsUnavailable(l'ordre des valeurs existantes ne change pas).- Une ville passe à
RestartRequiredaprès une pose réussie dans cette session. Dans le menu : texte « Restart required », couleur(0.6, 0.6, 1.0), clic sans effet. Pour le tri, elle compte avec les téléchargeables. ULPCityRowClick::OnClickedouvre la fenêtre (§ 2.1) au lieu deOpenCityPage, qui reste pour le recours.Deinitialize: annule le téléchargement en cours, garde le.partet ferme la fenêtre.
3. Contrôles hors moteur
git diff --statet liste des fichiers ajoutés ; MD5 avant et après ; MD5 des fichiers de STM1 inchangés.- Fins de ligne :
git ls-files --eoldes fichiers modifiés ; 0 CR et pas de BOM dans les fichiers neufs. - Copies de licence : MD5 identiques à
Licenses/…. Test-JsondeLPCityMaps.json.- Lecture critique du code par toi : chemins de pose, retour en arrière, aucun
Delete(GrepDelete), aucun appel réseau dans un chemin d'éditeur au démarrage.
4. Livrable
Docs\Migration\etat\REL\MAPDL1\MAPDL1-E5-IMPL.md :
- en-tête sk-protocol, avec le modèle réellement utilisé ;
- fichiers, MD5, diff résumé ;
- API vérifiées avec fichier:ligne (HTTP, redirections, OpenSSL, libzip, Win32) ;
- choix faits ;
- points à vérifier à la compilation et en jeu ;
- compte rendu.
Budget : 70 tours. En cas de blocage : arrêt et rapport, sans contourner.