Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Warning! Experimental! No guarantees on functionality! Use at your own risk!!!!!
- (Not so much on this one. I have used it and it actually functions very well, but still potentially unstable.)
- */
- #include "AsyncPluginLoader.h"
- #include "Misc/FileHelper.h"
- #include "Misc/Paths.h"
- #include "Async/Async.h"
- void UAsyncPluginLoader::LoadPluginFileAsync(const FString& FilePath, const FOnPluginFileLoaded& OnLoaded)
- {
- FString FileExtension = FPaths::GetExtension(FilePath);
- if (FileExtension != TEXT("esm") && FileExtension != TEXT("esp"))
- {
- UE_LOG(LogTemp, Warning, TEXT("Invalid file extension for plugin: %s (expected .esm or .esp)"), *FilePath);
- AsyncTask(ENamedThreads::GameThread, [OnLoaded]()
- {
- OnLoaded.ExecuteIfBound(false, TArray<uint8>());
- });
- return;
- }
- AsyncTask(ENamedThreads::AnyThread, [FilePath, OnLoaded]()
- {
- TArray<uint8> FileData;
- bool bSuccess = FFileHelper::LoadFileToArray(FileData, *FilePath);
- AsyncTask(ENamedThreads::GameThread, [FileData, bSuccess, FilePath, OnLoaded]()
- {
- if (bSuccess)
- {
- UE_LOG(LogTemp, Log, TEXT("Successfully loaded plugin file: %s"), *FilePath);
- OnLoaded.ExecuteIfBound(true, FileData);
- }
- else
- {
- UE_LOG(LogTemp, Warning, TEXT("Failed to load plugin file: %s"), *FilePath);
- OnLoaded.ExecuteIfBound(false, TArray<uint8>());
- }
- });
- });
- }
- void UAsyncPluginLoader::ParseESMRecords(const TArray<uint8>& FileBytes, TArray<FESMRecord>& OutRecords)
- {
- FMemoryReader Ar(FileBytes, true);
- while (!Ar.AtEnd())
- {
- FESMRecord Record;
- Ar << Record.RecordType; // 4 bytes for type (e.g., "LAND")
- int32 RecordSize;
- Ar << RecordSize; // 4 bytes for size
- // Parse the FormID (4 bytes) and flags (4 bytes) from the header
- int32 FormIDValue;
- Ar << FormIDValue; // 4 bytes for FormID
- FFormID FormID(FormIDValue);
- Record.FormIDs.Add(FormID);
- // Skip the remaining 4 bytes (flags)
- Ar.Seek(Ar.Tell() + 4);
- // Read the record's data (subrecords)
- int64 RecordEnd = Ar.Tell() + RecordSize;
- Record.RecordData.SetNum(RecordSize);
- Ar.Serialize(Record.RecordData.GetData(), RecordSize);
- // Pre-parse subrecords for LAND and other records
- ParseESMSubrecords(Record.RecordData, Record.Subrecords, Record.FormIDs, Record); // Pass the current Record
- OutRecords.Add(Record);
- Ar.Seek(RecordEnd);
- }
- }
- void UAsyncPluginLoader::ParseESMSubrecords(const TArray<uint8>& RecordData, TArray<FESMSubrecord>& OutSubrecords, TArray<FFormID>& OutFormIDs, FESMRecord& CurrentRecord)
- {
- FMemoryReader Ar(RecordData, true);
- while (!Ar.AtEnd())
- {
- FESMSubrecord Subrecord;
- Ar << Subrecord.SubrecordType; // 4 bytes for type (e.g., "NAME")
- int32 SubrecordSize;
- Ar << SubrecordSize; // 4 bytes for size
- Subrecord.SubrecordData.SetNum(SubrecordSize);
- Ar.Serialize(Subrecord.SubrecordData.GetData(), SubrecordSize);
- // Check for NAME subrecord to store as EditorID
- if (Subrecord.SubrecordType == TEXT("NAME"))
- {
- FString Name = FString(SubrecordSize, (char*)Subrecord.SubrecordData.GetData());
- CurrentRecord.EditorID = Name; // Set directly on the current record
- }
- OutSubrecords.Add(Subrecord);
- }
- }
- bool UAsyncPluginLoader::ExtractHeightData(const FESMRecord& Record, FESMHeightData& OutHeightData)
- {
- if (Record.RecordType != TEXT("LAND"))
- {
- return false;
- }
- for (const FESMSubrecord& Subrecord : Record.Subrecords)
- {
- if (Subrecord.SubrecordType == TEXT("VHGT"))
- {
- FMemoryReader Ar(Subrecord.SubrecordData, true);
- Ar << OutHeightData.BaseHeight;
- OutHeightData.Heights.SetNum(4225); // 65x65 grid
- for (int32 i = 0; i < 4225; i++)
- {
- int8 HeightOffset;
- Ar << HeightOffset;
- OutHeightData.Heights[i] = OutHeightData.BaseHeight + (HeightOffset * 8.0f);
- }
- return true;
- }
- }
- return false;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement