Legacy:ConfigMaster

From Unreal Wiki, The Unreal Engine Documentation Site
UT2003 :: Object >> Actor >> Info >> Mutator >> ConfigMaster (ConfigManager)

This is a custom class, which is part of the ConfigManager for UT2003.

<uscript line> //----------------------------------------------------------- // ConfigManager.ConfigMaster version 1.8 // Allows for ServerActors & Mutators to add to PlayInfo // // The latest version of ConfigManager is always available at // http://www.organized-evolution.com/ConfigManager/ //-----------------------------------------------------------

class ConfigMaster extends Mutator DependsOn(AutoLoader) config(ConfigMaster);

// If 2184 or earlier, crash the server var int GameVersion;

// Contains previous values of modified IniEntries, unless there is already // a previous value for an IniEntry. When a managed loader is de-activated, // the original value of the IniEntry is restored. var config array<AutoLoader.IniEntry> OriginalValues;

// Holder for properties which aren't needed - used by loaders that get activated at the end of the match var array<Property> IrrelevantProperties;

struct SA { var class<Info> SAClass; var string SAName; var string SADescription; };

struct AL { var class<AutoLoader> AutoLoaderClass; var string AutoLoaderDesc; };

var array<SA> ManagedActors; // Info about Loaders' ActorClasses var array<AL> LoaderClasses; // All Loader Classes found var array<AutoLoader> Loaders; // Active Loaders var array<string> ActiveMutators; // Currently active mutator classes var bool bInitialized; // Initialization var bool bHangRestart; // Don't let server travel yet

var GameEngine GE;

const VERSION = 1.71; const LOGNAME = 'Config Manager'; var const bool DEBUG; var const bool DEBUGPROPS;

// Localization var localized string LoadSuccess; var localized string RequiredVersion; var localized string UpgradeOrDie; var localized string RemovalCancelled;

// Errors var localized string InvalidLoaderClass; var localized string InvalidPI;

event PreBeginPlay() { GameVersion = int(Level.EngineVersion);

log(" -"@LOGNAME@VERSION@LoadSuccess,LOGNAME); if (GameVersion < 2199) { log(RequiredVersion@LOGNAME$".",LOGNAME); log(UpgradeOrDie,LOGNAME); log("",'ConfigManager'); Assert(False); }

GetGameEngine(); }

event PostBeginPlay() { local int i;

if (DEBUG) { log(class@"Beginning initialization",'PostBeginPlay'); log("START OF GAME SERVERACTORS",'PostBeginPlay'); for (i = 0; i < GE.ServerActors.Length; i++) log("ServerActor["$i$"]:"$GE.ServerActors[i],'PostBeginPlay');

log("START OF GAME SERVERPACKAGES",'PostBeginPlay'); for (i = 0; i < GE.ServerPackages.Length; i++) log("ServerPackages["$i$"]:"$GE.ServerPackages[i],'PostBeginPlay');

log("",'PostBeginPlay'); } // Level.Game.AddMutator("ConfigManagerGUI.ConfigManagerGUIMaster");

InitLoaders(); if (DEBUG) log(class@"finished loading all actors and loaders",'PostBeginPlay');

Super.PostBeginPlay(); }

// Sends a list of currently active mutators to all loader classes // Loader classes may want to check if its mutator was loaded without using the loader // (added at command line, etc.) function GetGameEngine() { foreach AllObjects(class'Engine.GameEngine', GE) break; }

function AddMutator(Mutator M) { local int i;

for (i = 0; i < ActiveMutators.Length; i++) if (ActiveMutators[i] ~= string(M.Class)) break;

if (i == ActiveMutators.Length) ActiveMutators[ActiveMutators.Length] = string(M.Class);

if (DEBUG) for (i = 0; i < ActiveMutators.Length; i++) log("ActiveMutators["$i$"]:"@ActiveMutators[i],'AddMutator');

Super.AddMutator(M); }

// Do not show ConfigMaster in server browser as active mutator function GetServerDetails( out GameInfo.ServerResponseLine ServerState ) { }

function InitLoaders() { FindAllLoaders(); CreateLoaders(); }

function FindAllLoaders() { local int i, j; local AL TempAL; local SA TempSA;

local class<AutoLoader> LoaderClass; local class<Info> ServerActorClass; local string LoaderClassName, LoaderClassDescription, ActorClass, ServerActorName, ServerActorDesc;

GetNextIntDesc("ConfigManager.AutoLoader",0,LoaderClassName,LoaderClassDescription); while (LoaderClassName != "") { // Hack to prevent Config Loader from being loaded if (LoaderClassName ~= "ConfigManagerLoader.SampleLoader") { GetNextIntDesc("ConfigManager.AutoLoader",++i,LoaderClassName,LoaderClassDescription); continue; } if (DEBUG) log("Found a new AutoLoader:"@LoaderClassName@LoaderClassDescription,'FindAllLoaders');

LoaderClass = class<AutoLoader>(DynamicLoadObject(LoaderClassName,Class'Class')); if (LoaderClass != None) { if (ShouldAddLoaderClass(LoaderClass)) { TempAL.AutoLoaderClass = LoaderClass; TempAL.AutoLoaderDesc = LoaderClassDescription; LoaderClasses[LoaderClasses.Length] = TempAL; j = -1; while (LoaderClass.static.AddManagedActor(j++, ActorClass, ServerActorName, ServerActorDesc)) { if (ActorClass != "" && ServerActorName != "" && ServerActorDesc != "") { ServerActorClass = class<Info>(DynamicLoadObject(ActorClass,class'Class')); if (ServerActorClass != None) { TempSA.SAClass = ServerActorClass; TempSA.SAName = ServerActorName; TempSA.SADescription = ServerActorDesc;

ManagedActors[ManagedActors.Length] = TempSA; } } } } } else Warn(InvalidLoaderClass@LoaderClassName);

GetNextIntDesc("ConfigManager.AutoLoader",++i, LoaderClassName, LoaderClassDescription); }

return; }

function bool ShouldAddLoaderClass(class<AutoLoader> NewClass) { local int i;

if (DEBUG) log("Loader Class"@NewClass,'ShouldAddLoaderClass');

// Don't add if it's already in the list for (i = 0;i < LoaderClasses.Length; i++) if (LoaderClasses[i].AutoLoaderClass == NewClass) return false;

return true; }

function CreateLoaders() { local int i; local AutoLoader Loader;

if (DEBUG) log("LoaderClasses"@LoaderClasses.Length,'CreateLoaders');

for (i = 0;i<LoaderClasses.Length;i++) { if (ShouldAddLoader(LoaderClasses[i].AutoLoaderClass)) { Loader = AddLoader(LoaderClasses[i].AutoLoaderClass); if (Loader != None) Loaders[Loaders.Length] = Loader; } } }

function bool LoaderNotActive(class<AutoLoader> NewClass) { local int i;

for (i = 0; i < Loaders.Length; i++) if (Loaders[i].Class == NewClass) return false;

return true; }

function bool ShouldAddLoader(class<AutoLoader> NewClass) { local bool bShouldAdd;

bShouldAdd = LoaderNotActive(NewClass) && GE != None;

if (bShouldAdd) bShouldAdd = NewClass.static.CheckStrayActors(GE.GetPropertyText("ServerActors")) || NewClass.static.IsActive();

bShouldAdd = bShouldAdd && NewClass.static.ValidateLoader();

if (DEBUG) log(NewClass@"will be added:"$bShouldAdd,'ShouldAddLoader');

return bShouldAdd; }

function AutoLoader AddLoader(class<AutoLoader> NewClass) { local AutoLoader Loader; if (NewClass == None) return None;

Loader = Spawn(NewClass,Self); if (Loader != None && GE != None) Loader.GE = GE;

if (DEBUG) log("Returning"@Loader,'AddLoader');

return Loader; }

// Make sure to remain as Game.BaseMutator.NextMutator so we will know about every mutator that is added. event Tick(float DeltaTime) { local int i;

if (bInitialized && Level != None && Level.NextURL != "") { if (bHangRestart) Level.NextSwitchCountdown = 4.0;

else if (Loaders.Length > 0) { bHangRestart = True; SetTimer(0.2,False); } }

// Do not replace BaseMutator, or DMMutator will show up in server browser as an active mutator if (Level != None && Level.Game != None && Level.Game.BaseMutator != None) { if (Level.Game.BaseMutator.NextMutator != None) { if (Level.Game.BaseMutator.NextMutator != Self) { // Some other ConfigManager as BaseMutator.NextMutator, but it isn't me???? // Maybe added ConfigManager as a serveractor? // Disable or server will crash if (!bInitialized && Level.Game.BaseMutator.NextMutator.Class == Class) { Destroy(); return; }

// We have been replaced by another mutator wanting // to be the first mutator. if (Level.Game.BaseMutator.NextMutator.NextMutator == Self) { if (NextMutator != None) Level.Game.BaseMutator.NextMutator.NextMutator = NextMutator; else Level.Game.BaseMutator.NextMutator.NextMutator = None; }

NextMutator = Level.Game.BaseMutator.NextMutator; Level.Game.BaseMutator.NextMutator = Self; } }

else Level.Game.BaseMutator.NextMutator = Self; }

if (!bInitialized) { for (i = 0; i < LoaderClasses.Length; i++) { if (LoaderNotActive(LoaderClasses[i].AutoLoaderClass) && LoaderClasses[i].AutoLoaderClass.static.CheckCurrentMutators(GetURLOption("Mutator"))) { if (DEBUG) log("Adding previously non-active loader"@LoaderClasses[i].AutoLoaderClass,'Tick'); Loaders[Loaders.Length] = AddLoader(LoaderClasses[i].AutoLoaderClass); } }

bInitialized = True; } }

event Timer() { Super.Timer(); ApplyLoaderSettings(); }

function array<Property> LoadProperties() { local array<Property> AllProperties; local array<class> RelevantActors; local array<string> RelevantPropNames; local class RelevantClass; local Property P; local int i, j, k;

// Build a array of properties which are relevant to the currently loaded loaders // so that the amount of time it will take each loader to update their settings will // be dramatically reduced - // Typical number of Property objects in the game: 200,000 // Typical number of properties relevant to current loaders: 50


// Start by first getting a list of actors/objects which will be relevant

// All ManagedActors are relevant (Loader's ActorClass) for (i = 0; i < ManagedActors.Length; i++) { for (j = 0; j < RelevantActors.Length; j++) if (RelevantActors[j] == ManagedActors[i].SAClass) break;

if (j < RelevantActors.Length) continue;

RelevantActors[RelevantActors.Length] = ManagedActors[i].SAClass; }

if (DEBUG) log("Loaders"@LoaderClasses.Length,'LoadProperties');

for (i = 0; i < LoaderClasses.Length; i++) { // If ActorClass was already added to list, skip it for (j = 0; j < RelevantActors.Length; j++) if (string(RelevantActors[j]) ~= LoaderClasses[i].AutoLoaderClass.default.ActorClass) break;

if (j == RelevantActors.Length) { if (LoaderClasses[i].AutoLoaderClass.default.ActorClass != "") RelevantClass = class(DynamicLoadObject(LoaderClasses[i].AutoLoaderClass.default.ActorClass,class'Class'));

if (RelevantClass != None) RelevantActors[RelevantActors.Length] = RelevantClass; }

// Begin building a list of property names to mark as relevant // We'll match these names to the Property.Name variable later when we iterate AllObjects for class'Property' for (j = 0; j < LoaderClasses[i].AutoLoaderClass.default.RequiredIniEntries.Length; j++) {

for (k = 0; k < RelevantPropNames.Length; k++) { if (RelevantPropNames[k] == LoaderClasses[i].AutoLoaderClass.default.RequiredIniEntries[j].PropName) break; }

if ( k == RelevantPropNames.Length ) { RelevantPropNames[RelevantPropNames.Length] = LoaderClasses[i].AutoLoaderClass.default.RequiredIniEntries[j].PropName; if (DEBUGPROPS) log("Added new Relevant Property Name:"$RelevantPropNames[k],'LoadProperties'); }

RelevantClass = class(DynamicLoadObject(LoaderClasses[i].AutoLoaderClass.default.RequiredIniEntries[j].ClassFrom,Class'class',True)); if (RelevantClass == None) continue;

// Find out if this entry's associated class is already in the relevant actors list // If not, add it for (k = 0; k < RelevantActors.Length; k++) { if (DEBUGPROPS) log("Compare"@LoaderClasses[i].AutoLoaderClass.default.RequiredIniEntries[j].ClassFrom@"to Relevant Actor"@k$":"@RelevantActors[k],'LoadProperties');

if (RelevantActors[k] == RelevantClass) break; } if (DEBUGPROPS) log("Breaking on"@k$", Total Relevant Actors:"@RelevantActors.Length,'LoadProperties');

if (k < RelevantActors.Length) continue;

RelevantActors[RelevantActors.Length] = RelevantClass; if (DEBUGPROPS) log("Added new relevant actor:"$LoaderClasses[i].AutoLoaderClass.default.RequiredIniEntries[j].ClassFrom,'LoadProperties'); } }

// Finished building relevant actors and relevant names // Iterate AllObjects, looking for Property objects foreach AllObjects(class'Property', P) { RelevantClass = None; // Some property types should be skipped if ( ValidProp(P) ) { if (Class(P.Outer) != None) RelevantClass = Class(P.Outer); if (RelevantClass != None) { for (i = 0; i < RelevantActors.Length; i++) { // The Outer variable for properties is the class that the property is contained in // If this property's Outer is an object that is relevant, add it to the list if (RelevantClass == RelevantActors[i]) { for (j = 0; j < RelevantPropNames.Length; j++) if (RelevantPropNames[j] == string(P.Name)) { if (DEBUGPROPS) log("Adding Initial Relevant Property:"$P.Outer$"."$P.Name,'LoadProperties'); AllProperties[AllProperties.Length] = P; break; }

if (j < RelevantPropNames.Length) break; } } }

// OK, this property's Outer wasn't relevant // Check the property against the relevant name list if (i == RelevantActors.Length) { for (i = 0; i < RelevantPropNames.Length; i++) { // If we find a match, then we should check the relevant objects list again, // in case the relevant object is a superclass of the property's Outer if (RelevantPropNames[i] == string(P.Name)) { if (DEBUGPROPS) log("Compare Property:"@i@RelevantPropNames[i]@"to"@string(P.Name),'LoadProperties');

for (j = 0; j < RelevantActors.Length; j ++) { if (RelevantClass == None) continue;

if (DEBUGPROPS) log("Relevant Actor Check:"@j@RelevantActors[j]@"is child of"@class(P.Outer)@":"$ClassIsChildOf(RelevantActors[j],Class(P.Outer)),'LoadProperties');

if (ClassIsChildOf(RelevantActors[j], RelevantClass)) { if (DEBUGPROPS) log("Adding Additional Relevant Property:"$P.Outer$"."$P.Name,'LoadProperties');

AllProperties[AllProperties.Length] = P; break; } }

if (j < RelevantActors.Length) break; } } } } }

return AllProperties; }

// Update Properties array with newly loaded loaders // No longer used function CheckRelevantProperties(AutoLoader L, out array<Property> Props) { local int i, j; local array<class> Classes, Outers;

local class TempClass; local Property P;

if (DEBUGPROPS) log("Checking relevant properties for new loader"@L,'CheckRelevantProperties');

for (i = 0; i < Props.Length; i++) { TempClass = Class(Props[i].Outer); if (TempClass == None) continue;

for (j = 0; j < Outers.Length; j++) if (TempClass == Outers[j]) break;

if (j < Outers.Length) continue;

Outers[Outers.Length] = TempClass; }

if (L.bIncludeServerActor && L.ActorClass != "") { if (DEBUGPROPS) log("Checking for existence of"@L.ActorClass@"properties",'CheckRelevantProperties');

TempClass = class(DynamicLoadObject(L.ActorClass,class'Class',True)); if (TempClass != None) { for (i = 0; i < Outers.Length; i++) if (TempClass == Outers[i]) break;

if (i == Outers.Length) Classes[Classes.Length] = TempClass;

else if (DEBUGPROPS) log(TempClass@"has already been added to the properties array.",'CheckRelevantProperties'); } }

for (i = 0; i < L.RequiredIniEntries.Length; i++) { if (DEBUGPROPS) log("Checking for existence of relevant class"@L.RequiredIniEntries[i].ClassFrom,'CheckRelevantProperties');

TempClass = class(DynamicLoadObject(L.RequiredIniEntries[i].ClassFrom,class'Class',True)); if (TempClass != None) { for (j = 0; j < Classes.Length; j++) if (Classes[j] == TempClass) break;

if (j < Classes.Length) continue;

for (j = 0; j < Outers.Length; j++) if (Outers[j] == TempClass) break;

if (j < Outers.Length) continue;

Classes[Classes.Length] = TempClass; } else if (DEBUGPROPS) log("Could not load RequiredIniEntry["$i$"].ClassFrom:"@L.RequiredIniEntries[i].ClassFrom,'CheckRelevantProperties'); }

if (DEBUGPROPS && Classes.Length == 0) log("All relevant classes from this loader already existed in properties array",'CheckRelevantProperties');

for (i = 0; i < Classes.Length; i++) { if (DEBUGPROPS) { log(""); log("Adding properties from class"@Classes[i]@"to properties array.",'CheckRelevantProperties'); }

for (j = 0; j < IrrelevantProperties.Length; j++) { P = IrrelevantProperties[j]; TempClass = Class(P.Outer);

if (TempClass == None || TempClass != Classes[i]) continue;

if (DEBUGPROPS) log(" Adding property"@P.Name,'CheckRelevantProperties');

Props[Props.Length] = P; IrrelevantProperties.Remove(j--, 1); } } }

// TODO: Add support for structs final function bool ValidProp(Property P) { return P.Class != class'ObjectProperty' && P.Class != class'DelegateProperty' && P.Class != class'PointerProperty' && P.Class != class'MapProperty' && P.Class != class'StructProperty'; }

// Fills PlayInfo for ServerActors final function CallManagedActorPlayInfo(PlayInfo PI) { local int i, j;

for (i = 0; i < LoaderClasses.Length; i++) { if (DEBUG) log("Checking for LoaderClass"@i@"in playinfo:"$loaderclasses[i].autoloaderclass,'ManagedActorFillPlayInfo');

if (NotInPlayInfo(PI,LoaderClasses[i].AutoLoaderClass)) { if (DEBUG) log("Calling FillPlayInfo() for LoaderClass"@i$":"$loaderclasses[i].autoloaderclass,'ManagedActorFillPlayInfo');

LoaderClasses[i].AutoLoaderClass.static.FillPlayInfo(PI); PI.PopClass(); }

for (j = 0; j < ManagedActors.Length; j++) { if (LoaderClasses[i].AutoLoaderClass.default.ActorClass != string(ManagedActors[j].SAClass)) continue;

if (DEBUG) log("Checking for ManagedActor"@j@"in playinfo:"$ManagedActors[j].SAClass,'ManagedActorFillPlayInfo');

if (LoaderClasses[i].AutoLoaderClass.static.IsActive()) { ManagedActors[j].SAClass.static.FillPlayInfo(PI); PI.PopClass(); } } } }

// Only webadmin calls Mutator.MutatorFillPlayInfo()? function MutatorFillPlayInfo(PlayInfo PI) { if (DEBUG) log("");

if (DEBUG) log("Checking URL Option:"$GetURLOption("Mutator"),'MutatorFillPlayInfo');

if (NextMutator != None) NextMutator.MutatorFillPlayInfo(PI);

CallManagedActorPlayInfo(PI); }

// Allows Loaders to adjust game configuration parameters // Loaders provide info about which ini changes need to be made for the mod to work // This allows other programs (such as Ladder) to only include the ini modifications // which are applicable for the loaded packages // // (Ex: ServerActors, ServerPackages, QueryHandlerClasses, Applications) final function ApplyLoaderSettings() { local int i, Index; local array<Property> CurrentProperties; local class Temp;

// Checking for any loaders that have been enabled since last check // Otherwise, must wait 2 server restarts to apply new loader settings // (One to load loader and apply changes, another for changes to take effect) FindAllLoaders(); CurrentProperties = LoadProperties(); for ( i = 0; i < LoaderClasses.Length; i++) { if (DEBUG) log("LoaderClass"@i$":"@LoaderClasses[i].AutoLoaderClass,'ApplyLoaderSettings');

if (ShouldAddLoader(LoaderClasses[i].AutoLoaderClass) || (LoaderClasses[i].AutoLoaderClass.static.CheckCurrentMutators(Level.NextURL) && LoaderClasses[i].AutoLoaderClass.static.ValidateLoader())) Loaders[Loaders.Length] = AddLoader(LoaderClasses[i].AutoLoaderClass);

else if (LoaderNotActive(LoaderClasses[i].AutoLoaderClass)) AddLoader(LoaderClasses[i].AutoLoaderClass).AcceptRemoval(CurrentProperties); }

if (DEBUGPROPS) { log("*** Relevant Property Listing ***",'ApplyLoaderSettings'); for (i = 0; i < CurrentProperties.Length;i++) { if (Class(CurrentProperties[i].Outer) != None && Temp != Class(CurrentProperties[i].Outer)) { Temp = Class(CurrentProperties[i].Outer); log("",'ApplyLoaderSettings'); log("Relevant properties from class"@Temp@"-",'ApplyLoaderSettings'); } log(" "$currentproperties[i].name,'ApplyLoaderSettings'); } }

while (Index < Loaders.Length) { if (DEBUG) log("Loader"@Index$":"@Loaders[Index],'ApplyLoaderSettings');

if (Loaders[Index].ApplyUpdate()) Loaders[Index].UpdateConfiguration(CurrentProperties);

else if (!Loaders[Index].AcceptRemoval(CurrentProperties)) log(RemovalCancelled@Loaders[Index],'ConfigManager');

Index++; }

Disable('Tick'); if (DEBUG) { log("",'ApplyLoaderSettings'); log("END OF GAME SERVERACTORS",'ApplyLoaderSettings'); for (i = 0; i < GE.ServerActors.Length; i++) log("ServerActor["$i$"]:"$GE.ServerActors[i],'ApplyLoaderSettings');

log("END OF GAME SERVERPACKAGES",'ApplyLoaderSettings'); for (i = 0; i < GE.ServerPackages.Length; i++) log("ServerPackages["$i$"]:"$GE.ServerPackages[i],'ApplyLoaderSettings');

log("",'ApplyLoaderSettings'); } }

function bool NotInPlayInfo(PlayInfo PI, class<Info> NewInfo) { local int i; if (PI == None) { Warn(InvalidPI); return false; }

for (i=0;i<PI.InfoClasses.Length;i++) { if (PI.InfoClasses[i] == NewInfo) return false; }

return true; }

function array<string> GetAllManagedActors() { local int i; local array<string> Arr;

for (i = 0; i < LoaderClasses.Length; i++) Arr = AddS(Arr,LoaderClasses[i].AutoLoaderClass.static.GetManagedActors());

return Arr; }

static final function float GetConfigMasterVersion() { return VERSION; }

// following function copied from wUtils (El_Muerte[TDS]) static final function array<string> AddS(array<string> A, array<string> B) {

 local int i;
 for (i = 0; i < B.length; i++)
 {
   A.length = A.length+1;
   A[A.length-1] = B[i];
 }
 return A;

} </uscript>