Advertisement
malice936

FormIDHelper.cpp

Apr 13th, 2025
226
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.10 KB | Gaming | 0 0
  1. // Include the header for UFormIDHelper, which declares the class and its static functions.
  2. // Ensures the implementations in this file match the declared interface.
  3. #include "FormIDHelper.h"
  4.  
  5. // Include the header for FFormID, which defines the struct used by these functions.
  6. // Provides access to the Value member for bit manipulation and comparisons.
  7. #include "FormID.h"
  8.  
  9. // Include for FPaths, used in NormalizePluginName for file path operations.
  10. #include "Misc/Paths.h"
  11.  
  12. // Include for IFileManager, used in ValidatePluginFiles to check file existence.
  13. #include "HAL/FileManager.h"
  14.  
  15. // Implementation of ToString, a static function of UFormIDHelper.
  16. // Converts a FormID to a hexadecimal string representation, e.g., "0x00000001".
  17. // Used for debugging, logging, or displaying FormIDs in a human-readable format in Blueprints or C++.
  18. FString UFormIDHelper::ToString(const FFormID& FormID)
  19. {
  20.     // Use FString::Printf to format the FormID's Value as an 8-digit hexadecimal number.
  21.     // TEXT("0x%08X") ensures a "0x" prefix and zero-padding for consistency (e.g., "0x00000001").
  22.     // Cast Value to uint32 to match the unsigned format specifier %X, avoiding warnings.
  23.     return FString::Printf(TEXT("0x%08X"), static_cast<uint32>(FormID.Value));
  24. }
  25.  
  26. // Implementation of Equals, a static function of UFormIDHelper.
  27. // Compares two FormIDs to determine if they are equal.
  28. // Useful in Blueprints or C++ for validation, branching, or data comparison.
  29. bool UFormIDHelper::Equals(const FFormID& A, const FFormID& B)
  30. {
  31.     // Compare the Value members of both FormIDs.
  32.     // Returns true if they are equal, false otherwise, making it a pure operation with no side effects.
  33.     return A.Value == B.Value;
  34. }
  35.  
  36. // Implementation of IsValid, a static function of UFormIDHelper.
  37. // Checks if a FormID is valid, where a valid FormID has a non-zero Value.
  38. // Essential for ensuring FormIDs refer to actual records before processing in Blueprints or C++.
  39. bool UFormIDHelper::IsValid(const FFormID& FormID)
  40. {
  41.     // Return true if the FormID's Value is non-zero, indicating a valid record.
  42.     // A Value of 0 is typically considered invalid in Bethesda game file formats.
  43.     // This is a pure operation, as it only reads the Value and performs a comparison.
  44.     return FormID.Value != 0;
  45. }
  46.  
  47. // Implementation of GetPluginIndex, a static function of UFormIDHelper.
  48. // Extracts the plugin index from a standard (non-ESL) FormID.
  49. // The plugin index, stored in the first byte (bits 24-31), identifies the plugin file (.ESP or .ESM).
  50. int32 UFormIDHelper::GetPluginIndex(const FFormID& FormID)
  51. {
  52.     // Shift the FormID's Value right by 24 bits to isolate the top byte (bits 24-31).
  53.     // Apply a bitmask (0xFF) to ensure only the last 8 bits are considered, extracting the plugin index.
  54.     // Cast Value to uint32 for unsigned bit operations to avoid signed arithmetic warnings.
  55.     // Returns the index as an int32, a pure operation that only reads the Value.
  56.     return (static_cast<uint32>(FormID.Value) >> 24) & 0xFF;
  57. }
  58.  
  59. // Implementation of GetRecordIndex, a static function of UFormIDHelper.
  60. // Extracts the record index from a standard (non-ESL) FormID.
  61. // The record index, stored in the last 3 bytes (bits 0-23), identifies a specific record within the plugin.
  62. int32 UFormIDHelper::GetRecordIndex(const FFormID& FormID)
  63. {
  64.     // Apply a bitmask (0xFFFFFF) to isolate the last 24 bits (bits 0-23) of the FormID's Value.
  65.     // Cast Value to uint32 for unsigned bit operations to avoid signed arithmetic warnings.
  66.     // Returns the record index as an int32, a pure operation with no side effects.
  67.     return static_cast<uint32>(FormID.Value) & 0xFFFFFF;
  68. }
  69.  
  70. // Implementation of IsESL, a static function of UFormIDHelper.
  71. // Determines if a FormID belongs to an ESL (Elder Scrolls Light) plugin.
  72. // ESL plugins, used in Skyrim Special Edition and Fallout 4, have a top byte of 0xFE.
  73. bool UFormIDHelper::IsESL(const FFormID& FormID)
  74. {
  75.     // Shift the FormID's Value right by 24 bits to isolate the top byte (bits 24-31).
  76.     // Compare it to 0xFE to check if it indicates an ESL plugin.
  77.     // Cast Value to uint32 for unsigned bit operations to avoid signed arithmetic warnings.
  78.     // Returns true if the top byte is 0xFE, false otherwise, in a pure and safe operation.
  79.     return (static_cast<uint32>(FormID.Value) >> 24) == 0xFE;
  80. }
  81.  
  82. // Implementation of GetESLIndex, a static function of UFormIDHelper.
  83. // Retrieves the ESL index from a FormID if it belongs to an ESL plugin.
  84. // The ESL index, stored in bits 12-23, represents the plugin's position in the load order.
  85. int32 UFormIDHelper::GetESLIndex(const FFormID& FormID)
  86. {
  87.     // Check if the FormID is an ESL using IsESL to ensure correct processing.
  88.     if (IsESL(FormID))
  89.     {
  90.         // Shift the Value right by 12 bits to align bits 12-23 with the lower bits.
  91.         // Apply a bitmask (0xFFF) to isolate these 12 bits, extracting the ESL index.
  92.         // Cast Value to uint32 for unsigned bit operations to avoid signed arithmetic warnings.
  93.         // Return the index as an int32, a pure operation that only reads the Value.
  94.         return (static_cast<uint32>(FormID.Value) >> 12) & 0xFFF;
  95.     }
  96.     // If the FormID is not an ESL, return -1 to indicate the ESL index is not applicable.
  97.     // Ensures consistent behavior for non-ESL FormIDs.
  98.     return -1;
  99. }
  100.  
  101. // Implementation of GetESLRecordIndex, a static function of UFormIDHelper.
  102. // Retrieves the record index from a FormID if it belongs to an ESL plugin.
  103. // The record index, stored in bits 0-11, identifies a specific record within the ESL plugin.
  104. int32 UFormIDHelper::GetESLRecordIndex(const FFormID& FormID)
  105. {
  106.     // Check if the FormID is an ESL using IsESL to validate the FormID type.
  107.     if (IsESL(FormID))
  108.     {
  109.         // Apply a bitmask (0xFFF) to isolate the last 12 bits (bits 0-11) of the Value.
  110.         // Cast Value to uint32 for unsigned bit operations to avoid signed arithmetic warnings.
  111.         // Return the record index as an int32, a pure operation with no side effects.
  112.         return static_cast<uint32>(FormID.Value) & 0xFFF;
  113.     }
  114.     // If the FormID is not an ESL, return -1 to indicate the ESL record index is not applicable.
  115.     // Maintains consistency in return values for non-ESL FormIDs.
  116.     return -1;
  117. }
  118.  
  119. // Implementation of CreateExtendedFormID, a static function of UFormIDHelper.
  120. // Creates an FExtendedFormID instance with the given parent plugin name, masters, and raw FormID value.
  121. // Normalizes plugin names and validates the existence of plugin files.
  122. FExtendedFormID UFormIDHelper::CreateExtendedFormID(const FString& InParentPluginName, const TArray<FString>& InMasters, int32 InRawId)
  123. {
  124.     FExtendedFormID ExtendedFormID;
  125.     ExtendedFormID.FormID = FFormID(InRawId);
  126.     ExtendedFormID.ParentPluginName = NormalizePluginName(InParentPluginName);
  127.     ExtendedFormID.Masters.Reserve(InMasters.Num());
  128.     for (const FString& Master : InMasters)
  129.     {
  130.         ExtendedFormID.Masters.Add(NormalizePluginName(Master));
  131.     }
  132.     ValidatePluginFiles(ExtendedFormID);
  133.     return ExtendedFormID;
  134. }
  135.  
  136. // Implementation of NormalizePluginName, a static function of UFormIDHelper.
  137. // Normalizes a plugin name to a full file path, adding ".esp" if no extension is present.
  138. // Ensures consistent handling of plugin file paths across different systems.
  139. FString UFormIDHelper::NormalizePluginName(const FString& PluginName)
  140. {
  141.     FString Normalized = PluginName;
  142.     FPaths::NormalizeFilename(Normalized);
  143.     if (!Normalized.Contains(TEXT(".")))
  144.     {
  145.         Normalized += TEXT(".esp");
  146.     }
  147.     return FPaths::ConvertRelativePathToFull(FPaths::ProjectContentDir() / Normalized);
  148. }
  149.  
  150. // Implementation of ValidatePluginFiles, a static function of UFormIDHelper.
  151. // Checks if the plugin files specified in the FExtendedFormID exist on disk.
  152. // Logs warnings for any missing files and returns true if all files are found, false otherwise.
  153. bool UFormIDHelper::ValidatePluginFiles(const FExtendedFormID& ExtendedFormID)
  154. {
  155.     IFileManager& FileManager = IFileManager::Get();
  156.     bool bAllValid = true;
  157.     if (!ExtendedFormID.ParentPluginName.IsEmpty() && !FileManager.FileExists(*ExtendedFormID.ParentPluginName))
  158.     {
  159.         UE_LOG(LogTemp, Warning, TEXT("Parent plugin file does not exist: %s"), *ExtendedFormID.ParentPluginName);
  160.         bAllValid = false;
  161.     }
  162.     for (const FString& Master : ExtendedFormID.Masters)
  163.     {
  164.         if (!Master.IsEmpty() && !FileManager.FileExists(*Master))
  165.         {
  166.             UE_LOG(LogTemp, Warning, TEXT("Master plugin file does not exist: %s"), *Master);
  167.             bAllValid = false;
  168.         }
  169.     }
  170.     return bAllValid;
  171. }
  172.  
  173. // Implementation of IsValidPluginExtension, a static function of UFormIDHelper.
  174. // Determines if a plugin name has a valid file extension for Bethesda game plugins.
  175. // Valid extensions are .esm, .esp, and .esl (case-insensitive).
  176. bool UFormIDHelper::IsValidPluginExtension(const FString& PluginName)
  177. {
  178.     return PluginName.EndsWith(TEXT(".esm"), ESearchCase::IgnoreCase) ||
  179.            PluginName.EndsWith(TEXT(".esp"), ESearchCase::IgnoreCase) ||
  180.            PluginName.EndsWith(TEXT(".esl"), ESearchCase::IgnoreCase);
  181. }
  182.  
  183. // Implementation of GetObjectIndex, a static function of UFormIDHelper.
  184. // Retrieves the record index within the plugin for the given FExtendedFormID.
  185. // Handles both standard and ESL FormIDs appropriately.
  186. int32 UFormIDHelper::GetObjectIndex(const FExtendedFormID& ExtendedFormID)
  187. {
  188.     if (IsESL(ExtendedFormID.FormID))
  189.     {
  190.         return GetESLRecordIndex(ExtendedFormID.FormID);
  191.     }
  192.     return GetRecordIndex(ExtendedFormID.FormID);
  193. }
  194.  
  195. // Implementation of GetPluginName, a static function of UFormIDHelper.
  196. // Determines the plugin file path associated with the FExtendedFormID's FormID.
  197. // Considers the mod index and master dependencies to select the correct plugin.
  198. FString UFormIDHelper::GetPluginName(const FExtendedFormID& ExtendedFormID)
  199. {
  200.     int32 ModIndex = GetPluginIndex(ExtendedFormID.FormID);
  201.     if (ExtendedFormID.Masters.Num() > 0)
  202.     {
  203.         if (ModIndex == 0)
  204.         {
  205.             return ExtendedFormID.Masters[0];
  206.         }
  207.         else if (ModIndex < ExtendedFormID.Masters.Num())
  208.         {
  209.             return ExtendedFormID.Masters[ModIndex];
  210.         }
  211.     }
  212.     return ExtendedFormID.ParentPluginName;
  213. }
  214.  
  215. // Implementation of GetAllPluginNames, a static function of UFormIDHelper.
  216. // Collects all plugin file paths (parent and masters) associated with the FExtendedFormID.
  217. // Useful for operations requiring the full set of dependent plugins.
  218. TArray<FString> UFormIDHelper::GetAllPluginNames(const FExtendedFormID& ExtendedFormID)
  219. {
  220.     TArray<FString> AllPlugins;
  221.     AllPlugins.Add(ExtendedFormID.ParentPluginName);
  222.     AllPlugins.Append(ExtendedFormID.Masters);
  223.     return AllPlugins;
  224. }
  225.  
  226. // Implementation of HasMaster, a static function of UFormIDHelper.
  227. // Checks if a specific plugin is listed as a master dependency in the FExtendedFormID.
  228. // Normalizes the master name for consistent comparison.
  229. bool UFormIDHelper::HasMaster(const FExtendedFormID& ExtendedFormID, const FString& MasterName)
  230. {
  231.     FString NormalizedMaster = NormalizePluginName(MasterName);
  232.     return ExtendedFormID.Masters.Contains(NormalizedMaster);
  233. }
  234.  
  235. // Implementation of GetPluginLoadOrderIndex, a static function of UFormIDHelper.
  236. // Estimates the load order index for the plugin based on the number of master dependencies.
  237. // A higher number of masters typically indicates a later load order.
  238. int32 UFormIDHelper::GetPluginLoadOrderIndex(const FExtendedFormID& ExtendedFormID)
  239. {
  240.     return ExtendedFormID.Masters.Num();
  241. }
  242.  
  243. // Implementation of IsLessThan, a static function of UFormIDHelper.
  244. // Compares two FExtendedFormIDs based on their plugin names (case-insensitive) and object indices.
  245. // Used for sorting or ordering FormIDs in collections.
  246. bool UFormIDHelper::IsLessThan(const FExtendedFormID& A, const FExtendedFormID& B)
  247. {
  248.     FString PluginA = GetPluginName(A).ToLower();
  249.     FString PluginB = GetPluginName(B).ToLower();
  250.     if (PluginA != PluginB)
  251.     {
  252.         return PluginA < PluginB;
  253.     }
  254.     return GetObjectIndex(A) < GetObjectIndex(B);
  255. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement