PerObjectConfig
"PerObjectConfig" is a class Syntax modifier that was introduced to UnrealScript for UT200x.
The configuration for classes that are declared with the PerObjectConfig will be saved individually for each object of that class to the specified configuration file using the object name (and class name in UnrealEngine2, UnrealEngine1 only uses the object name) as the section name.
This will allow you to have multiple configurations for your class in the same configuration file. It's somewhat the same as using DataObjects, except that this is mean for simple configurations that also have to be edited from outside the game. DataObjects are more designed for saving completed class instances, not for just configuration.
Saving information
For example you have the following class:
class MyClass extends Object PerObjectConfig; var config string var1; var config int var2;
When saving the config of an instance of this object in an UnrealEngine2 game it will be saved as:
[MyClass MyClass] var1= var2=0
Note the section name, the first part before the space is the classes instance name. The second part is the real class name without the package name.
This is ofcourse useless since it will still limited you to a single configuration set for your class. So you have to change the name of the instance of MyClass. Changing the name can only be done when creating the Object.
mci = new(None, "ThisIsMyName") class'MyClass'; mci.SaveConfig();
This will generate the following:
[ThisIsMyName MyClass] var1= var2=0
The name argument in new is a string, this means that the name may contain everything you want. However, there are a couple of limitations, as you can see the space is used as the Instance Name – Class Name delimiter. So obviously you can't use spaces in the name. Another character that breaks this functionallity is the ]
character.
So if you allow people to set the name of the object you have to make sure you limit the available characters, or replace the unallowed characters in the name.
function CreateStorageClass(coerce string objectname) { objectname = repl(objectname, " ", Chr(27)); // replace " " for the ASCII ESC character mci = new(None, objectname) class'MyClass'; }
Note: if you do the following the configuration will be stored in MapName.ini instead of the specified config file (in the class declaration).
mci = new(Level, "ThisIsMyName") class'MyClass'; mci.SaveConfig();
Loading information
The configuration of the class is automatically loaded when it's created. It loads the variables from the section that matches the name.
If the object names arn't defined somewhere, or when you allow users to add additional object instances you won't know what names are available.
For this the following function has been defined in Object:
native static final function array<string> GetPerObjectNames( string ININame, optional string ObjectClass, optional int MaxResults /*1024 if unspecified*/ ); //no extension
- ININame
- the name of the configuration file, as defined in the config(MyConfig) class declration. System and User will be replaced with the correct System and User configuration files. You don't have to include the .ini extention
- ObjectClass
- the name of your per object config class. This is not the fully qualified name only the real class name:
string(MyClass.name)
. If it's ommited the current class name will be used. - MaxResults
- the maximum results you want to have.
This will return a string array containing all the names of objects that have a section. Now all you have to do is load them:
function LoadMyClasses() { local array<MyClass> MyClasses; local array<string> Names; local int i; Names = GetPerObjectNames("System", string(class'MyClass'.name)); for (i = 0; i < Names.length; i++) { MyClasses[MyClasses.length] = new(None, Names[i]) class'MyClass'; } }
Deleting information
Deleting a object configuration from the ini file is easy. For that you only need the instance of that object and class
MyClassInstance.ClearConfig();
Tips & tricks
These where just the basics on how to use PerObjectConfig. Here are a couple of tricks.
Use an object name variable
As said above you have to mangle the objects real name for it to save correctly. This ofcourse isn't user friendly when you want to list the object names. So add an addditional object name variable to the PerObjectConfig that contains the name to show to use user (the one that does contain spaces).
Renaming
You can't rename an object. For that to work you have to create a new object with the new name and copy the data from the old object. then delete the old object from the configuration.
Ofcourse when you use an object name as said above you can simly change that variable.
Diffirent ini files
In the example above we save out config in the System's configuration file. To change the configuration in a different file just use the config(MyConfig) for the class declaration and use "MyConfig" for GetPerObjectNames call.
Keep in mind that most GISPs want to have all the per server configuration in the system file. There's an easy way to give people some control where the configuration is saved.
Use the following approach:
The main MyClass
First we define our main MyClass that will contain all the logic that it might need.
class MyClass extends Object PerObjectConfig config(System); var const string ConfigFile; // config variables and logic defaultproperties { ConfigFile="System" }
As you can see the config will be saved in the System configuration. I also defined a constant string variable and set it's value to "System". This variable will be used to load the configuration. This value must be the same as the value for the config() class declaration element. This variable can't be a config variable because you can't change the value for the config() class element on the fly.
Also using ParseConfig in the class declaration won't work because the main code won't know what config file to use.
A subclass
Now we will define a subclass that uses a diffirent ini file
class MyClassIni extends MyClass config(MyConfig); defaultproperties { ConfigFile="MyConfig" }
Using it
Now we have two classes that save the config in different locations. For this to work you have to define a config variable in your main code (the code that loads these objects), to define what class is used for storage.
var config class<MyClass> StorageClass; function LoadMyClasses() { local array<MyClass> MyClasses; local array<string> Names; local int i; Names = GetPerObjectNames(StorageClass.default.ConfigFile, string(StorageClass.name)); for (i = 0; i < Names.length; i++) { MyClasses[MyClasses.length] = new(None, Names[i]) StorageClass; } } defaultproperties { StorageClass=class'MyPackage.MyClass' }
Note that we use the value of ConfigFile from the storage class as the ini file name to load the variables from. And use the StorageClass to create the class.
Also note that the name of the classname in the GetPerObjectNames depends on the StorageClass. The result section in the ini file will have this as class name, so using different StorageClasses doesn't reuse the configuration entries.