Cogito, ergo sum
Legacy:Config Vars And .Ini Files
Often it is desireable to preserve the output of a program after it has terminated. Other times, it may be desirable to be able to read external files for user settings, etcetera. Games, of course, are no different. Unfortunately, UnrealScripts file system functions are somewhat limited. There are no file streams or other sorts of low-level file interaction, but you can usually still do what you want within the constraints of the file system functions that are availible.
Write-Only and Read-Write Operations
There are several reasons why one might want to write to the hard drive from within UnrealScript. The most common, of course, is for logging and debugging, but data is also often written to the hard drive for later recovery by some reading function. There are three known ways to write data to the hard drive: the log file, config variables/ini files, and the savepackage suite of functions.
Config Variables and .Ini Files
.Ini files are the closest to a two way (read/write) operation that Unrealscript can perform. .Ini files are read when the class they are associated with is first loaded. After that, they can only be written to, but the values from their reading remains in memory. .Ini files are very closely tied to config variables, and they work by changing the default properties of those variables. For instance, if you have a string that is a config variable, and you change it's value in the .Ini file, it's default value for that string will have updated when that class' package is next loaded. This is a very good method of having settings persist on something that has only one instance.
Writing to an .ini file is a two-step process, but it is simple to do. First, you must set the value of the variables you wish to write to disk. Usually if you are using .ini files to create persistant settings this will likely already be done. Once that is done, simply have your class call either the native final SaveConfig() or native static final StaticSaveConfig(), defined in Object. SaveConfig() will write the contents of all the config variables in the instance of the class you call it from to the .Ini file assigned to that class. This defaults to User.Ini, but can be changed in the class declaration. (See Class Syntax) StaticSaveConfig() is similar to SaveConfig(), but instead saves the default values of the config variables to disk.
Note that every subclass will have it's own version of the config variables stored in the .Ini file. If you want all subclasses to share the same persistent value, you should declare your variable as globalconfig instead of config. See Variable Syntax.
Also bear in mind that due to the nature of config variables, they will rarely be the same on both server and client. The server also will not automatically replicate it's config variables, unless they are replicated variables, in which case they will be replicated when they change or when a relevant actor replication takes place. See Replication.
There appears to be a limit on the amount of data that can be read from or written to the .Ini file, though it appears to be fairly great. Anything over about a kilobyte of data (such as a large struct) stored in a single variable may not be handled properly.
Note also that there is an interesting quirk when saving structs in this way. Members of the struct, will be stored, but members of the struct declared as transient will not be stored. However, not only will they not be stored, but they will be reset to their initialization values when you call SaveConfig() or StaticSaveConfig(). You should back this information up before saving if you do not want it to be lost during the save.
You can save the entire world context via the savegame console command. The syntax is simple:
Where the number is the number of the saved world state. The "number" of the saved world state determines it's filename on disk, and is required to later restore the world state.
The restore the world state, you "load" it just as you would load a level. Instead of indicating a level name, however, simply load the level:
Saving and loading does not work in UT2003, but is an engine feature and should work in other Unreal Engine titles, including UT2004.
Read-only operations may not sound as useful, but can in some ways be even more useful for certain applications. These are often referred to as INT files, though there is more to them than they are usually given credit for. There are two main ways to use INT files:
Behaving very much like an .Ini file, any string variable may be declared as localized in the same way as a variable could be declared as a config variable. A localized variable will be loaded from the INT file when the package is first loaded into memory. However, localized strings are tied into the lanugage preference setting in the Unreal Engine, so the INT file is not always used. INT is the international version of the localized information files. There are numerous other files with different extensions, and the extension indicates which language the file is intended for. If your Unreal Engine is set up for french, the FRT file will be used instead, etc. The INT file is always used as a fallback if there is no file for your language or if the file for your language of choice does not contain a value for a localized string. See Localization.
You can read lots of stuff from these and parse it out to get whatever information you need. See INT File.
Foxpaw: This page should probrably be renamed to something more generic about saving and loading data, since it's the page with all the info about various forms of persistent data.
Sweavo: I agree, and the ini file and savepackage stuff should have a page each (especially while we can't make links to internal anchors)
Fyfe: DataObject and INT File already have their own pages. I suggest stripping out the sections of DataObject and INT File, then move Save Games to it's own page. Each page can then link back to each other in the related topics section.
AJRAD: This may sound a bit stupid to you, but how do you decide where configs are stored (client or server)? Because I've seen clientside inis obviously (e.g. user.ini), but whenever I make config variable they always save on the server only.
Seditious: Test for whether you're on the server or client and only run code that calls SaveConfig() on the client, unless you need the class to govern things that the admin will want to configure on the server. Just put things that absolutely must be clientside in blocks that start with if (Level.NetMode != NM_DedicatedServer). See Legacy:NetMode.
Category:Legacy Refactor Me – Contains more info than the page title describes.