Saving OBSE arrays into Pluggy INI files

From the Oblivion ConstructionSet Wiki
Jump to navigation Jump to search


Saving arrays in regular files may be useful in many situations, including communicating between mods, manually editing array data and several others.

This article describes how to write OBSE arrays into Pluggy INI files and how to rebuild the original array from that INI file.


Conceptual Review[edit | edit source]

Arrays have a structure similar to our everyday folders and files structure in our hard drives.

An array has a series of entries containing either data or other arrays (which add another level to the array depth), the same way a folder in our HD may contain files and/or other folders (which add another level to the folder structure depth).

An array named MyNPCs may look like this:

["Adoring Fan"]
= = ["Race"] = "WoodElf" 
= = ["Inventory"] 
= = = = [0] 
= = = = = = ["BaseObject"] = 0x0000000F   (Gold)
= = = = = = ["Qty"] = 200
= = = = [1] 
= = = = = = ["BaseObject"] = 0x00026731   (LowerPants06)
= = = = = = ["Qty"] = 1
= = = = [2]
= = = = = = . . . etc

["Jensine"]
= = ["Race"] = "Nord"
= = ["Inventory"] 
= = = = [0] 
= = = = = = ["BaseObject"] = 0x0000000F   (Gold)
= = = = = = ["Qty"] = 555
= = = = [1] 
= = = = = = ["BaseObject"] = 0x0001C82C  (LowerPants04
= = = = = = ["Qty"] = 1
= = = = [2]
= = = = = = . . . etc

An INI file has a similar structure, but limited to only one level deep:

[SectionA]
Key1=Value1
Key2=Value2

[SectionB]
Key1=Value1
Key2=Value2
Key3=Value3


Serializing an array[edit | edit source]

To store a complex array structure as seen above into the simpler structure of an INI file we need to "serialize" the array structure that leads to each piece of data, the same way we serialize a path to a file (C:\Games\Oblivion\Oblivion.exe)

Therefore each block of NPC data in MyNPCs array must be restructured, so it will look like these:

["Adoring Fan"]
= ["Race"] = "WoodElf" 
= ["Inventory_0_BaseObject"] = 0x0000000F  
= ["Inventory_0_Qty"] = 200
= ["Inventory_1_BaseObject"] = 0x00026731 
= ["Inventory_1_Qty"] = 1

["Jensine]
= ["Race"] = "Nord" 
= ["Inventory_0_BaseObject"] = 0x0000000F  
= ["Inventory_0_Qty"] = 555
= ["Inventory_1_BaseObject"] = 0x0001C82C 
= ["Inventory_1_Qty"] = 1

This is accomplished by using the code presented in the User Function ArraySerialize

That function takes one of the branches, like the "Adoring Fan" branch, and turns it into a one dimensional array where each key contains the information to rebuild the original array structure when needed.


Writing the array data[edit | edit source]

Writing the serialized array is just a matter of using regular Pluggy INI functions to remove the existing section, if any, and writing each array entry into a line in the proper section.

The user function ArrayToINIsection does exactly that.

ArraySerialize and ArrayToINIsection could be called, in sequence, every time a script changes some data in one of the NPC entries in the MyNPCs array.

The INI file corresponding to the MyNPCs array would look like this:

[Adoring Fan]
Race = "WoodElf" 
Inventory_0_BaseObject = 0x0000000F  
Inventory_0_Qty = 200
Inventory_1_BaseObject = 0x00026731 
Inventory_1_Qty = 1

[Jensine]
Race = "Nord" 
Inventory_0_BaseObject = 0x0000000F  
Inventory_0_Qty = 555
Inventory_1_BaseObject = 0x0001C82C 
Inventory_1_Qty = 1


Reading the INI data[edit | edit source]

Sooner or later, we will need to read that INI file and rebuild the original MyNPCs array.

Regular Pluggy INI read functions could be used to read each section, the same way the INI write functions were used to write them.

The problem with this approach is that we need to know in advance which keys to read. We would need to, somehow, hardcode the set of possible keys to read. You can do that if your array structure is small and predefined.

But to make it generic and read ANY array structure, we will read the entire INI file and parse it to:

  • Isolate each section
  • In each section, separate each line
  • In each line, identify the key and the value
  • Split each key into its key parts
  • Rebuild the original array structure from the key parts
  • Register each value in the proper array branch

The first three steps are coded in the ArrayFromINIfile function. For each section, it creates a serialized array and 'deserialize' it by calling ArrayDeserialize to execute the three remaining steps.


Conclusion[edit | edit source]

Using the four aforementioned functions (or similar code) we can write and read any array structure to/from INI files.


Known limitations[edit | edit source]

You may need to adapt/adjust the sample code in the functions under certain circumstances:

  • Those functions use some chars ( _ | = [ ] ) to identify and split the data. If any of those chars appears as part of array keys or values, results are unpredictable.
  • The section size, in bytes, is limited to 16K. The INI file itself has no known size limit.


See Also[edit | edit source]