// Portage UE 5.5 - voir LPDumpSaveCommandlet.h #include "LPDumpSaveCommandlet.h" #include "GameFramework/SaveGame.h" #include "Kismet/GameplayStatics.h" #include "Misc/FileHelper.h" #include "UObject/UnrealType.h" DEFINE_LOG_CATEGORY_STATIC(LogLPDumpSave, Log, All); ULPDumpSaveCommandlet::ULPDumpSaveCommandlet() { IsClient = false; IsServer = false; IsEditor = true; LogToConsole = true; } int32 ULPDumpSaveCommandlet::Main(const FString& Params) { TArray Tokens, Switches; TMap ParamsMap; ParseCommandLine(*Params, Tokens, Switches, ParamsMap); const FString File = ParamsMap.FindRef(TEXT("File")); const FString Out = ParamsMap.FindRef(TEXT("Out")); TArray Wanted; ParamsMap.FindRef(TEXT("Props")).ParseIntoArray(Wanted, TEXT(","), true); if (File.IsEmpty() || Out.IsEmpty()) { UE_LOG(LogLPDumpSave, Error, TEXT("Usage : -File= -Out= [-Props=Nom1,Nom2]")); return 1; } TArray Bytes; if (!FFileHelper::LoadFileToArray(Bytes, *File)) { UE_LOG(LogLPDumpSave, Error, TEXT("Lecture impossible : %s"), *File); return 1; } USaveGame* Save = UGameplayStatics::LoadGameFromMemory(Bytes); if (!Save) { UE_LOG(LogLPDumpSave, Error, TEXT("Sauvegarde illisible : %s"), *File); return 1; } TArray Lines; Lines.Add(FString::Printf(TEXT("##### %s [%s]"), *File, *Save->GetClass()->GetPathName())); for (TFieldIterator It(Save->GetClass()); It; ++It) { const FProperty* Prop = *It; if (Prop->GetOwnerClass() && !Prop->GetOwnerClass()->IsChildOf(USaveGame::StaticClass())) { continue; } if (Prop->GetOwnerClass() == USaveGame::StaticClass()) { continue; } const FString Name = Prop->GetName(); if (Wanted.Num() > 0 && !Wanted.ContainsByPredicate([&](const FString& W) { return Name.StartsWith(W); })) { continue; } const void* Value = Prop->ContainerPtrToValuePtr(Save); if (const FArrayProperty* ArrayProp = CastField(Prop)) { FScriptArrayHelper Helper(ArrayProp, Value); Lines.Add(FString::Printf(TEXT("%s [%s] : %d element(s)"), *Name, *ArrayProp->Inner->GetCPPType(), Helper.Num())); for (int32 i = 0; i < Helper.Num(); ++i) { FString Text; ArrayProp->Inner->ExportTextItem_Direct(Text, Helper.GetRawPtr(i), nullptr, Save, PPF_None); Lines.Add(FString::Printf(TEXT(" %s[%d] = %s"), *Name, i, *Text)); } } else { FString Text; Prop->ExportTextItem_Direct(Text, Value, nullptr, Save, PPF_None); Lines.Add(FString::Printf(TEXT("%s [%s] = %s"), *Name, *Prop->GetCPPType(), *Text)); } } if (!FFileHelper::SaveStringArrayToFile(Lines, *Out, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM)) { UE_LOG(LogLPDumpSave, Error, TEXT("Ecriture impossible : %s"), *Out); return 1; } UE_LOG(LogLPDumpSave, Warning, TEXT("=== %s : %d ligne(s) -> %s ==="), *File, Lines.Num(), *Out); return 0; }