I love the smell of UnrealEd crashing in the morning. – tarquin

Legacy:ConfigMaster

From Unreal Wiki, The Unreal Engine Documentation Site

Revision as of 22:02, 18 November 2007 by Sweavo (Talk)
(diff) ← Older revision | Current revision (diff) | Newer revision → (diff)
Jump to: navigation, search
UT2003 :: Object >> Actor >> Info >> Mutator >> ConfigMaster (ConfigManager)

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

  1. //-----------------------------------------------------------
    
  2. // ConfigManager.ConfigMaster version 1.8
    
  3. // Allows for ServerActors & Mutators to add to PlayInfo
    
  4. //
    
  5. // The latest version of ConfigManager is always available at
    
  6. // http://www.organized-evolution.com/ConfigManager/
    
  7. //-----------------------------------------------------------
    
  8.  
    
  9. class ConfigMaster extends Mutator DependsOn(AutoLoader) config(ConfigMaster);
    
  10.  
    
  11. // If 2184 or earlier, crash the server
    
  12. var int						GameVersion;
    
  13.  
    
  14. // Contains previous values of modified IniEntries, unless there is already
    
  15. // a previous value for an IniEntry.  When a managed loader is de-activated,
    
  16. // the original value of the IniEntry is restored.
    
  17. var config array<AutoLoader.IniEntry>	OriginalValues;
    
  18.  
    
  19. // Holder for properties which aren't needed - used by loaders that get activated at the end of the match
    
  20. var array<Property>			IrrelevantProperties;
    
  21.  
    
  22. struct SA
    
  23. {
    
  24. 	var class<Info>			SAClass;
    
  25. 	var string				SAName;
    
  26. 	var string				SADescription;
    
  27. };
    
  28.  
    
  29. struct AL
    
  30. {
    
  31. 	var class<AutoLoader>	AutoLoaderClass;
    
  32. 	var string				AutoLoaderDesc;
    
  33. };
    
  34.  
    
  35. var array<SA>				ManagedActors;		// Info about Loaders' ActorClasses
    
  36. var array<AL>				LoaderClasses;		// All Loader Classes found
    
  37. var array<AutoLoader>		Loaders;			// Active Loaders
    
  38. var array<string>			ActiveMutators;		// Currently active mutator classes
    
  39. var bool					bInitialized;		// Initialization
    
  40. var bool					bHangRestart;		// Don't let server travel yet
    
  41.  
    
  42. var GameEngine				GE;
    
  43.  
    
  44. const VERSION = 1.71;
    
  45. const LOGNAME = 'Config Manager';
    
  46. var const bool	DEBUG;
    
  47. var const bool 	DEBUGPROPS;
    
  48.  
    
  49. // Localization
    
  50. var localized string LoadSuccess;
    
  51. var localized string RequiredVersion;
    
  52. var localized string UpgradeOrDie;
    
  53. var localized string RemovalCancelled;
    
  54.  
    
  55. // Errors
    
  56. var localized string InvalidLoaderClass;
    
  57. var localized string InvalidPI;
    
  58.  
    
  59. event PreBeginPlay()
    
  60. {
    
  61. 	GameVersion = int(Level.EngineVersion);
    
  62.  
    
  63. 	log(" -"@LOGNAME@VERSION@LoadSuccess,LOGNAME);
    
  64. 	if (GameVersion < 2199)
    
  65. 	{
    
  66. 		log(RequiredVersion@LOGNAME$".",LOGNAME);
    
  67. 		log(UpgradeOrDie,LOGNAME);
    
  68. 		log("",'ConfigManager');
    
  69. 		Assert(False);
    
  70. 	}
    
  71.  
    
  72. 	GetGameEngine();
    
  73. }
    
  74.  
    
  75. event PostBeginPlay()
    
  76. {
    
  77. 	local int i;
    
  78.  
    
  79. 	if (DEBUG)
    
  80. 	{
    
  81. 		log(class@"Beginning initialization",'PostBeginPlay');
    
  82. 		log("START OF GAME SERVERACTORS",'PostBeginPlay');
    
  83. 		for (i = 0; i < GE.ServerActors.Length; i++)
    
  84. 			log("ServerActor["$i$"]:"$GE.ServerActors[i],'PostBeginPlay');
    
  85.  
    
  86. 		log("START OF GAME SERVERPACKAGES",'PostBeginPlay');
    
  87. 		for (i = 0; i < GE.ServerPackages.Length; i++)
    
  88. 			log("ServerPackages["$i$"]:"$GE.ServerPackages[i],'PostBeginPlay');
    
  89.  
    
  90. 		log("",'PostBeginPlay');
    
  91. 	}
    
  92. //	Level.Game.AddMutator("ConfigManagerGUI.ConfigManagerGUIMaster");
    
  93.  
    
  94. 	InitLoaders();
    
  95. 	if (DEBUG)
    
  96. 		log(class@"finished loading all actors and loaders",'PostBeginPlay');
    
  97.  
    
  98. 	Super.PostBeginPlay();
    
  99. }
    
  100.  
    
  101. // Sends a list of currently active mutators to all loader classes
    
  102. // Loader classes may want to check if its mutator was loaded without using the loader
    
  103. // (added at command line, etc.)
    
  104. function GetGameEngine()
    
  105. {
    
  106. 	foreach AllObjects(class'Engine.GameEngine', GE)
    
  107. 		break;
    
  108. }
    
  109.  
    
  110. function AddMutator(Mutator M)
    
  111. {
    
  112. 	local int i;
    
  113.  
    
  114. 	for (i = 0; i < ActiveMutators.Length; i++)
    
  115. 		if (ActiveMutators[i] ~= string(M.Class))
    
  116. 			break;
    
  117.  
    
  118. 	if (i == ActiveMutators.Length)
    
  119. 		ActiveMutators[ActiveMutators.Length] = string(M.Class);
    
  120.  
    
  121. 	if (DEBUG)
    
  122. 		for (i = 0; i < ActiveMutators.Length; i++)
    
  123. 			log("ActiveMutators["$i$"]:"@ActiveMutators[i],'AddMutator');
    
  124.  
    
  125. 	Super.AddMutator(M);
    
  126. }
    
  127.  
    
  128. // Do not show ConfigMaster in server browser as active mutator
    
  129. function GetServerDetails( out GameInfo.ServerResponseLine ServerState )
    
  130. {
    
  131. }
    
  132.  
    
  133. function InitLoaders()
    
  134. {
    
  135. 	FindAllLoaders();
    
  136. 	CreateLoaders();
    
  137. }
    
  138.  
    
  139. function FindAllLoaders()
    
  140. {
    
  141. 	local int i, j;
    
  142. 	local AL TempAL;
    
  143. 	local SA TempSA;
    
  144.  
    
  145. 	local class<AutoLoader>	LoaderClass;
    
  146. 	local class<Info>		ServerActorClass;
    
  147. 	local string			LoaderClassName, LoaderClassDescription,
    
  148. 				 			ActorClass, ServerActorName, ServerActorDesc;
    
  149.  
    
  150. 	GetNextIntDesc("ConfigManager.AutoLoader",0,LoaderClassName,LoaderClassDescription);
    
  151. 	while (LoaderClassName != "")
    
  152. 	{
    
  153. 		// Hack to prevent Config Loader from being loaded
    
  154. 		if (LoaderClassName ~= "ConfigManagerLoader.SampleLoader")
    
  155. 		{
    
  156. 			GetNextIntDesc("ConfigManager.AutoLoader",++i,LoaderClassName,LoaderClassDescription);
    
  157. 			continue;
    
  158. 		}
    
  159. 		if (DEBUG)
    
  160. 			log("Found a new AutoLoader:"@LoaderClassName@LoaderClassDescription,'FindAllLoaders');
    
  161.  
    
  162. 		LoaderClass = class<AutoLoader>(DynamicLoadObject(LoaderClassName,Class'Class'));
    
  163. 		if (LoaderClass != None)
    
  164. 		{
    
  165. 			if (ShouldAddLoaderClass(LoaderClass))
    
  166. 			{
    
  167. 				TempAL.AutoLoaderClass = LoaderClass;
    
  168. 				TempAL.AutoLoaderDesc = LoaderClassDescription;
    
  169. 				LoaderClasses[LoaderClasses.Length] = TempAL;
    
  170. 				j = -1;
    
  171. 				while (LoaderClass.static.AddManagedActor(j++, ActorClass, ServerActorName, ServerActorDesc))
    
  172. 				{
    
  173. 					if (ActorClass != "" && ServerActorName != "" && ServerActorDesc != "")
    
  174. 					{
    
  175. 						ServerActorClass = class<Info>(DynamicLoadObject(ActorClass,class'Class'));
    
  176. 						if (ServerActorClass != None)
    
  177. 						{
    
  178. 							TempSA.SAClass = ServerActorClass;
    
  179. 							TempSA.SAName = ServerActorName;
    
  180. 							TempSA.SADescription = ServerActorDesc;
    
  181.  
    
  182. 							ManagedActors[ManagedActors.Length] = TempSA;
    
  183. 						}
    
  184. 					}
    
  185. 				}
    
  186. 			}
    
  187. 		}
    
  188. 		else Warn(InvalidLoaderClass@LoaderClassName);
    
  189.  
    
  190. 		GetNextIntDesc("ConfigManager.AutoLoader",++i, LoaderClassName, LoaderClassDescription);
    
  191. 	}
    
  192.  
    
  193. 	return;
    
  194. }
    
  195.  
    
  196. function bool ShouldAddLoaderClass(class<AutoLoader> NewClass)
    
  197. {
    
  198. 	local int i;
    
  199.  
    
  200. 	if (DEBUG)
    
  201. 		log("Loader Class"@NewClass,'ShouldAddLoaderClass');
    
  202.  
    
  203. 	// Don't add if it's already in the list
    
  204. 	for (i = 0;i < LoaderClasses.Length; i++)
    
  205. 		if (LoaderClasses[i].AutoLoaderClass == NewClass)
    
  206. 			return false;
    
  207.  
    
  208. 	return true;
    
  209. }
    
  210.  
    
  211. function CreateLoaders()
    
  212. {
    
  213. 	local int i;
    
  214. 	local AutoLoader Loader;
    
  215.  
    
  216. 	if (DEBUG)
    
  217. 		log("LoaderClasses"@LoaderClasses.Length,'CreateLoaders');
    
  218.  
    
  219. 	for (i = 0;i<LoaderClasses.Length;i++)
    
  220. 	{
    
  221. 		if (ShouldAddLoader(LoaderClasses[i].AutoLoaderClass))
    
  222. 		{
    
  223. 			Loader = AddLoader(LoaderClasses[i].AutoLoaderClass);
    
  224. 			if (Loader != None)
    
  225. 				Loaders[Loaders.Length] = Loader;
    
  226. 		}
    
  227. 	}
    
  228. }
    
  229.  
    
  230. function bool LoaderNotActive(class<AutoLoader> NewClass)
    
  231. {
    
  232. 	local int i;
    
  233.  
    
  234. 	for (i = 0; i < Loaders.Length; i++)
    
  235. 		if (Loaders[i].Class == NewClass)
    
  236. 			return false;
    
  237.  
    
  238. 	return true;
    
  239. }
    
  240.  
    
  241. function bool ShouldAddLoader(class<AutoLoader> NewClass)
    
  242. {
    
  243. 	local bool bShouldAdd;
    
  244.  
    
  245. 	bShouldAdd = LoaderNotActive(NewClass) && GE != None;
    
  246.  
    
  247. 	if (bShouldAdd)
    
  248. 		bShouldAdd = NewClass.static.CheckStrayActors(GE.GetPropertyText("ServerActors")) || NewClass.static.IsActive();
    
  249.  
    
  250. 	bShouldAdd = bShouldAdd && NewClass.static.ValidateLoader();
    
  251.  
    
  252. 	if (DEBUG)
    
  253. 		log(NewClass@"will be added:"$bShouldAdd,'ShouldAddLoader');
    
  254.  
    
  255. 	return bShouldAdd;
    
  256. }
    
  257.  
    
  258. function AutoLoader AddLoader(class<AutoLoader> NewClass)
    
  259. {
    
  260. 	local AutoLoader Loader;
    
  261. 	if (NewClass == None) return None;
    
  262.  
    
  263. 	Loader = Spawn(NewClass,Self);
    
  264. 	if (Loader != None && GE != None)
    
  265. 		Loader.GE = GE;
    
  266.  
    
  267. 	if (DEBUG)
    
  268. 		log("Returning"@Loader,'AddLoader');
    
  269.  
    
  270. 	return Loader;
    
  271. }
    
  272.  
    
  273. // Make sure to remain as Game.BaseMutator.NextMutator so we will know about every mutator that is added.
    
  274. event Tick(float DeltaTime)
    
  275. {
    
  276. 	local int i;
    
  277.  
    
  278. 	if (bInitialized && Level != None && Level.NextURL != "")
    
  279. 	{
    
  280. 		if (bHangRestart)
    
  281. 			Level.NextSwitchCountdown = 4.0;
    
  282.  
    
  283. 		else if (Loaders.Length > 0)
    
  284. 		{
    
  285. 			bHangRestart = True;
    
  286. 			SetTimer(0.2,False);
    
  287. 		}
    
  288. 	}
    
  289.  
    
  290. 	// Do not replace BaseMutator, or DMMutator will show up in server browser as an active mutator
    
  291. 	if (Level != None && Level.Game != None && Level.Game.BaseMutator != None)
    
  292. 	{
    
  293. 		if (Level.Game.BaseMutator.NextMutator != None)
    
  294. 		{
    
  295. 			if (Level.Game.BaseMutator.NextMutator != Self)
    
  296. 			{
    
  297. 			// Some other ConfigManager as BaseMutator.NextMutator, but it isn't me????
    
  298. 			// Maybe added ConfigManager as a serveractor?
    
  299. 			// Disable or server will crash
    
  300. 				if (!bInitialized && Level.Game.BaseMutator.NextMutator.Class == Class)
    
  301. 				{
    
  302. 					Destroy();
    
  303. 					return;
    
  304. 				}
    
  305.  
    
  306. 				// We have been replaced by another mutator wanting
    
  307. 				// to be the first mutator.
    
  308. 				if (Level.Game.BaseMutator.NextMutator.NextMutator == Self)
    
  309. 				{
    
  310. 					if (NextMutator != None)
    
  311. 						Level.Game.BaseMutator.NextMutator.NextMutator = NextMutator;
    
  312. 					else Level.Game.BaseMutator.NextMutator.NextMutator = None;
    
  313. 				}
    
  314.  
    
  315. 				NextMutator = Level.Game.BaseMutator.NextMutator;
    
  316. 				Level.Game.BaseMutator.NextMutator = Self;
    
  317. 			}
    
  318. 		}
    
  319.  
    
  320. 		else Level.Game.BaseMutator.NextMutator = Self;
    
  321. 	}
    
  322.  
    
  323. 	if (!bInitialized)
    
  324. 	{
    
  325. 		for (i = 0; i < LoaderClasses.Length; i++)
    
  326. 		{
    
  327. 			if (LoaderNotActive(LoaderClasses[i].AutoLoaderClass) && LoaderClasses[i].AutoLoaderClass.static.CheckCurrentMutators(GetURLOption("Mutator")))
    
  328. 			{
    
  329. 				if (DEBUG)
    
  330. 					log("Adding previously non-active loader"@LoaderClasses[i].AutoLoaderClass,'Tick');
    
  331. 				Loaders[Loaders.Length] = AddLoader(LoaderClasses[i].AutoLoaderClass);
    
  332. 			}
    
  333. 		}
    
  334.  
    
  335. 		bInitialized = True;
    
  336. 	}
    
  337. }
    
  338.  
    
  339. event Timer()
    
  340. {
    
  341. 	Super.Timer();
    
  342. 	ApplyLoaderSettings();
    
  343. }
    
  344.  
    
  345. function array<Property> LoadProperties()
    
  346. {
    
  347. 	local array<Property>	AllProperties;
    
  348. 	local array<class>		RelevantActors;
    
  349. 	local array<string>		RelevantPropNames;
    
  350. 	local class				RelevantClass;
    
  351. 	local Property P;
    
  352. 	local int i, j, k;
    
  353.  
    
  354. 	// Build a array of properties which are relevant to the currently loaded loaders
    
  355. 	// so that the amount of time it will take each loader to update their settings will
    
  356. 	// be dramatically reduced -
    
  357. 	// Typical number of Property objects in the game: 200,000
    
  358. 	// Typical number of properties relevant to current loaders: 50
    
  359.  
    
  360.  
    
  361. 	// Start by first getting a list of actors/objects which will be relevant
    
  362.  
    
  363. 	// All ManagedActors are relevant (Loader's ActorClass)
    
  364. 	for (i = 0; i < ManagedActors.Length; i++)
    
  365. 	{
    
  366. 		for (j = 0; j < RelevantActors.Length; j++)
    
  367. 			if (RelevantActors[j] == ManagedActors[i].SAClass)
    
  368. 				break;
    
  369.  
    
  370. 		if (j < RelevantActors.Length)
    
  371. 			continue;
    
  372.  
    
  373. 		RelevantActors[RelevantActors.Length] = ManagedActors[i].SAClass;
    
  374. 	}
    
  375.  
    
  376. 	if (DEBUG)
    
  377. 		log("Loaders"@LoaderClasses.Length,'LoadProperties');
    
  378.  
    
  379. 	for (i = 0; i < LoaderClasses.Length; i++)
    
  380. 	{
    
  381. 		// If ActorClass was already added to list, skip it
    
  382. 		for (j = 0; j < RelevantActors.Length; j++)
    
  383. 			if (string(RelevantActors[j]) ~= LoaderClasses[i].AutoLoaderClass.default.ActorClass)
    
  384. 				break;
    
  385.  
    
  386. 		if (j == RelevantActors.Length)
    
  387. 		{
    
  388. 			if (LoaderClasses[i].AutoLoaderClass.default.ActorClass != "")
    
  389. 				RelevantClass = class(DynamicLoadObject(LoaderClasses[i].AutoLoaderClass.default.ActorClass,class'Class'));
    
  390.  
    
  391. 			if (RelevantClass != None)
    
  392. 				RelevantActors[RelevantActors.Length] = RelevantClass;
    
  393. 		}
    
  394.  
    
  395. 		// Begin building a list of property names to mark as relevant
    
  396. 		// We'll match these names to the Property.Name variable later when we iterate AllObjects for class'Property'
    
  397. 		for (j = 0; j < LoaderClasses[i].AutoLoaderClass.default.RequiredIniEntries.Length; j++)
    
  398. 		{
    
  399.  
    
  400. 			for (k = 0; k < RelevantPropNames.Length; k++)
    
  401. 			{
    
  402. 				if (RelevantPropNames[k] == LoaderClasses[i].AutoLoaderClass.default.RequiredIniEntries[j].PropName)
    
  403. 					break;
    
  404. 			}
    
  405.  
    
  406. 			if ( k == RelevantPropNames.Length )
    
  407. 			{
    
  408. 				RelevantPropNames[RelevantPropNames.Length] = LoaderClasses[i].AutoLoaderClass.default.RequiredIniEntries[j].PropName;
    
  409. 				if (DEBUGPROPS)
    
  410. 					log("Added new Relevant Property Name:"$RelevantPropNames[k],'LoadProperties');
    
  411. 			}
    
  412.  
    
  413. 			RelevantClass = class(DynamicLoadObject(LoaderClasses[i].AutoLoaderClass.default.RequiredIniEntries[j].ClassFrom,Class'class',True));
    
  414. 			if (RelevantClass == None) continue;
    
  415.  
    
  416. 			// Find out if this entry's associated class is already in the relevant actors list
    
  417. 			// If not, add it
    
  418. 			for (k = 0; k < RelevantActors.Length; k++)
    
  419. 			{
    
  420. 				if (DEBUGPROPS)
    
  421. 					log("Compare"@LoaderClasses[i].AutoLoaderClass.default.RequiredIniEntries[j].ClassFrom@"to Relevant Actor"@k$":"@RelevantActors[k],'LoadProperties');
    
  422.  
    
  423. 				if (RelevantActors[k] == RelevantClass)
    
  424. 					break;
    
  425. 			}
    
  426. 			if (DEBUGPROPS)
    
  427. 				log("Breaking on"@k$", Total Relevant Actors:"@RelevantActors.Length,'LoadProperties');
    
  428.  
    
  429. 			if (k < RelevantActors.Length)
    
  430. 				continue;
    
  431.  
    
  432. 			RelevantActors[RelevantActors.Length] = RelevantClass;
    
  433. 			if (DEBUGPROPS)
    
  434. 				log("Added new relevant actor:"$LoaderClasses[i].AutoLoaderClass.default.RequiredIniEntries[j].ClassFrom,'LoadProperties');
    
  435. 		}
    
  436. 	}
    
  437.  
    
  438. 	// Finished building relevant actors and relevant names
    
  439. 	// Iterate AllObjects, looking for Property objects
    
  440. 	foreach AllObjects(class'Property', P)
    
  441. 	{
    
  442. 		RelevantClass = None;
    
  443. 		// Some property types should be skipped
    
  444. 		if ( ValidProp(P) )
    
  445. 		{
    
  446. 			if (Class(P.Outer) != None) RelevantClass = Class(P.Outer);
    
  447. 			if (RelevantClass != None)
    
  448. 			{
    
  449. 				for (i = 0; i < RelevantActors.Length; i++)
    
  450. 			 	{
    
  451. 			 		// The Outer variable for properties is the class that the property is contained in
    
  452. 			 		// If this property's Outer is an object that is relevant, add it to the list
    
  453. 			 		if (RelevantClass == RelevantActors[i])
    
  454. 			 		{
    
  455. 			 			for (j = 0; j < RelevantPropNames.Length; j++)
    
  456. 			 				if (RelevantPropNames[j] == string(P.Name))
    
  457. 			 				{
    
  458. 			 					if (DEBUGPROPS)
    
  459. 			 						log("Adding Initial Relevant Property:"$P.Outer$"."$P.Name,'LoadProperties');
    
  460. 			 					AllProperties[AllProperties.Length] = P;
    
  461. 			 					break;
    
  462. 			 				}
    
  463.  
    
  464. 			 			if (j < RelevantPropNames.Length)
    
  465. 			 				break;
    
  466. 			 		}
    
  467. 			 	}
    
  468. 			}
    
  469.  
    
  470. 			// OK, this property's Outer wasn't relevant
    
  471. 			// Check the property against the relevant name list
    
  472. 		 	if (i == RelevantActors.Length)
    
  473. 		 	{
    
  474. 		 		for (i = 0; i < RelevantPropNames.Length; i++)
    
  475. 		 		{
    
  476. 				// If we find a match, then we should check the relevant objects list again,
    
  477. 				// in case the relevant object is a superclass of the property's Outer
    
  478. 		 			if (RelevantPropNames[i] == string(P.Name))
    
  479. 		 			{
    
  480. 						if (DEBUGPROPS)
    
  481. 							log("Compare Property:"@i@RelevantPropNames[i]@"to"@string(P.Name),'LoadProperties');
    
  482.  
    
  483. 		 				for (j = 0; j < RelevantActors.Length; j ++)
    
  484. 		 				{
    
  485. 		 					if (RelevantClass == None) continue;
    
  486.  
    
  487. 							if (DEBUGPROPS)
    
  488. 								log("Relevant Actor Check:"@j@RelevantActors[j]@"is child of"@class(P.Outer)@":"$ClassIsChildOf(RelevantActors[j],Class(P.Outer)),'LoadProperties');
    
  489.  
    
  490. 		 					if (ClassIsChildOf(RelevantActors[j], RelevantClass))
    
  491. 		 					{
    
  492. 		 						if (DEBUGPROPS)
    
  493. 		 							log("Adding Additional Relevant Property:"$P.Outer$"."$P.Name,'LoadProperties');
    
  494.  
    
  495. 		 						AllProperties[AllProperties.Length] = P;
    
  496. 		 						break;
    
  497. 		 					}
    
  498. 		 				}
    
  499.  
    
  500. 		 				if (j < RelevantActors.Length)
    
  501. 		 					break;
    
  502. 		 			}
    
  503. 		 		}
    
  504. 		 	}
    
  505. 		}
    
  506. 	}
    
  507.  
    
  508. 	return AllProperties;
    
  509. }
    
  510.  
    
  511. // Update Properties array with newly loaded loaders
    
  512. // No longer used
    
  513. function CheckRelevantProperties(AutoLoader L, out array<Property> Props)
    
  514. {
    
  515. 	local int i, j;
    
  516. 	local array<class> Classes, Outers;
    
  517.  
    
  518. 	local class TempClass;
    
  519. 	local Property P;
    
  520.  
    
  521. 	if (DEBUGPROPS) log("Checking relevant properties for new loader"@L,'CheckRelevantProperties');
    
  522.  
    
  523. 	for (i = 0; i < Props.Length; i++)
    
  524. 	{
    
  525. 		TempClass = Class(Props[i].Outer);
    
  526. 		if (TempClass == None) continue;
    
  527.  
    
  528. 		for (j = 0; j < Outers.Length; j++)
    
  529. 			if (TempClass == Outers[j])
    
  530. 				break;
    
  531.  
    
  532. 		if (j < Outers.Length) continue;
    
  533.  
    
  534. 		Outers[Outers.Length] = TempClass;
    
  535. 	}
    
  536.  
    
  537. 	if (L.bIncludeServerActor && L.ActorClass != "")
    
  538. 	{
    
  539. 		if (DEBUGPROPS) log("Checking for existence of"@L.ActorClass@"properties",'CheckRelevantProperties');
    
  540.  
    
  541. 		TempClass = class(DynamicLoadObject(L.ActorClass,class'Class',True));
    
  542. 		if (TempClass != None)
    
  543. 		{
    
  544. 			for (i = 0; i < Outers.Length; i++)
    
  545. 				if (TempClass == Outers[i])
    
  546. 					break;
    
  547.  
    
  548. 			if (i == Outers.Length)
    
  549. 				Classes[Classes.Length] = TempClass;
    
  550.  
    
  551. 			else if (DEBUGPROPS)
    
  552. 				log(TempClass@"has already been added to the properties array.",'CheckRelevantProperties');
    
  553. 		}
    
  554. 	}
    
  555.  
    
  556. 	for (i = 0; i < L.RequiredIniEntries.Length; i++)
    
  557. 	{
    
  558. 		if (DEBUGPROPS) log("Checking for existence of relevant class"@L.RequiredIniEntries[i].ClassFrom,'CheckRelevantProperties');
    
  559.  
    
  560. 		TempClass = class(DynamicLoadObject(L.RequiredIniEntries[i].ClassFrom,class'Class',True));
    
  561. 		if (TempClass != None)
    
  562. 		{
    
  563. 			for (j = 0; j < Classes.Length; j++)
    
  564. 				if (Classes[j] == TempClass) break;
    
  565.  
    
  566. 			if (j < Classes.Length) continue;
    
  567.  
    
  568. 			for (j = 0; j < Outers.Length; j++)
    
  569. 				if (Outers[j] == TempClass) break;
    
  570.  
    
  571. 			if (j < Outers.Length) continue;
    
  572.  
    
  573. 			Classes[Classes.Length] = TempClass;
    
  574. 		}
    
  575. 		else if (DEBUGPROPS)
    
  576. 			log("Could not load RequiredIniEntry["$i$"].ClassFrom:"@L.RequiredIniEntries[i].ClassFrom,'CheckRelevantProperties');
    
  577. 	}
    
  578.  
    
  579. 	if (DEBUGPROPS && Classes.Length == 0)
    
  580. 		log("All relevant classes from this loader already existed in properties array",'CheckRelevantProperties');
    
  581.  
    
  582. 	for (i = 0; i < Classes.Length; i++)
    
  583. 	{
    
  584. 		if (DEBUGPROPS)
    
  585. 		{
    
  586. 			log("");
    
  587. 			log("Adding properties from class"@Classes[i]@"to properties array.",'CheckRelevantProperties');
    
  588. 		}
    
  589.  
    
  590. 		for (j = 0; j < IrrelevantProperties.Length; j++)
    
  591. 		{
    
  592. 			P = IrrelevantProperties[j];
    
  593. 			TempClass = Class(P.Outer);
    
  594.  
    
  595. 			if (TempClass == None || TempClass != Classes[i]) continue;
    
  596.  
    
  597. 			if (DEBUGPROPS) log("    Adding property"@P.Name,'CheckRelevantProperties');
    
  598.  
    
  599. 			Props[Props.Length] = P;
    
  600. 			IrrelevantProperties.Remove(j--, 1);
    
  601. 		}
    
  602. 	}
    
  603. }
    
  604.  
    
  605. // TODO: Add support for structs
    
  606. final function bool ValidProp(Property P)
    
  607. {
    
  608. 	return P.Class != class'ObjectProperty' &&
    
  609. 		   P.Class != class'DelegateProperty' &&
    
  610. 		   P.Class != class'PointerProperty' &&
    
  611. 		   P.Class != class'MapProperty' &&
    
  612. 		   P.Class != class'StructProperty';
    
  613. }
    
  614.  
    
  615. // Fills PlayInfo for ServerActors
    
  616. final function CallManagedActorPlayInfo(PlayInfo PI)
    
  617. {
    
  618. 	local int i, j;
    
  619.  
    
  620. 	for (i = 0; i < LoaderClasses.Length; i++)
    
  621. 	{
    
  622. 		if (DEBUG)
    
  623. 			log("Checking for LoaderClass"@i@"in playinfo:"$loaderclasses[i].autoloaderclass,'ManagedActorFillPlayInfo');
    
  624.  
    
  625. 		if (NotInPlayInfo(PI,LoaderClasses[i].AutoLoaderClass))
    
  626. 		{
    
  627. 			if (DEBUG)
    
  628. 				log("Calling FillPlayInfo() for LoaderClass"@i$":"$loaderclasses[i].autoloaderclass,'ManagedActorFillPlayInfo');
    
  629.  
    
  630. 			LoaderClasses[i].AutoLoaderClass.static.FillPlayInfo(PI);
    
  631. 			PI.PopClass();
    
  632. 		}
    
  633.  
    
  634. 		for (j = 0; j < ManagedActors.Length; j++)
    
  635. 		{
    
  636. 			if (LoaderClasses[i].AutoLoaderClass.default.ActorClass != string(ManagedActors[j].SAClass))
    
  637. 				continue;
    
  638.  
    
  639. 			if (DEBUG)
    
  640. 				log("Checking for ManagedActor"@j@"in playinfo:"$ManagedActors[j].SAClass,'ManagedActorFillPlayInfo');
    
  641.  
    
  642. 			if (LoaderClasses[i].AutoLoaderClass.static.IsActive())
    
  643. 			{
    
  644. 				ManagedActors[j].SAClass.static.FillPlayInfo(PI);
    
  645. 				PI.PopClass();
    
  646. 			}
    
  647. 		}
    
  648. 	}
    
  649. }
    
  650.  
    
  651. // Only webadmin calls Mutator.MutatorFillPlayInfo()?
    
  652. function MutatorFillPlayInfo(PlayInfo PI)
    
  653. {
    
  654. 	if (DEBUG)
    
  655. 		log("");
    
  656.  
    
  657. 	if (DEBUG)
    
  658. 		log("Checking URL Option:"$GetURLOption("Mutator"),'MutatorFillPlayInfo');
    
  659.  
    
  660. 	if (NextMutator != None)
    
  661. 		NextMutator.MutatorFillPlayInfo(PI);
    
  662.  
    
  663. 	CallManagedActorPlayInfo(PI);
    
  664. }
    
  665.  
    
  666. // Allows Loaders to adjust game configuration parameters
    
  667. // Loaders provide info about which ini changes need to be made for the mod to work
    
  668. // This allows other programs (such as Ladder) to only include the ini modifications
    
  669. // which are applicable for the loaded packages
    
  670. //
    
  671. // (Ex: ServerActors, ServerPackages, QueryHandlerClasses, Applications)
    
  672. final function ApplyLoaderSettings()
    
  673. {
    
  674. 	local int 				i, Index;
    
  675. 	local array<Property>	CurrentProperties;
    
  676. 	local class Temp;
    
  677.  
    
  678. 	// Checking for any loaders that have been enabled since last check
    
  679. 	// Otherwise, must wait 2 server restarts to apply new loader settings
    
  680. 	// (One to load loader and apply changes, another for changes to take effect)
    
  681. 	FindAllLoaders();
    
  682. 	CurrentProperties = LoadProperties();
    
  683. 	for ( i = 0; i < LoaderClasses.Length; i++)
    
  684. 	{
    
  685. 		if (DEBUG)
    
  686. 			log("LoaderClass"@i$":"@LoaderClasses[i].AutoLoaderClass,'ApplyLoaderSettings');
    
  687.  
    
  688. 		if (ShouldAddLoader(LoaderClasses[i].AutoLoaderClass) || (LoaderClasses[i].AutoLoaderClass.static.CheckCurrentMutators(Level.NextURL) && LoaderClasses[i].AutoLoaderClass.static.ValidateLoader()))
    
  689. 			Loaders[Loaders.Length] = AddLoader(LoaderClasses[i].AutoLoaderClass);
    
  690.  
    
  691. 		else if (LoaderNotActive(LoaderClasses[i].AutoLoaderClass))
    
  692. 			AddLoader(LoaderClasses[i].AutoLoaderClass).AcceptRemoval(CurrentProperties);
    
  693. 	}
    
  694.  
    
  695. 	if (DEBUGPROPS)
    
  696. 	{
    
  697. 		log("*** Relevant Property Listing ***",'ApplyLoaderSettings');
    
  698. 		for (i = 0; i < CurrentProperties.Length;i++)
    
  699. 		{
    
  700. 			if (Class(CurrentProperties[i].Outer) != None && Temp != Class(CurrentProperties[i].Outer))
    
  701. 			{
    
  702. 				Temp = Class(CurrentProperties[i].Outer);
    
  703. 				log("",'ApplyLoaderSettings');
    
  704. 				log("Relevant properties from class"@Temp@"-",'ApplyLoaderSettings');
    
  705. 			}
    
  706. 			log("    "$currentproperties[i].name,'ApplyLoaderSettings');
    
  707. 		}
    
  708. 	}
    
  709.  
    
  710. 	while (Index < Loaders.Length)
    
  711. 	{
    
  712. 		if (DEBUG)
    
  713. 			log("Loader"@Index$":"@Loaders[Index],'ApplyLoaderSettings');
    
  714.  
    
  715. 		if (Loaders[Index].ApplyUpdate())
    
  716. 			Loaders[Index].UpdateConfiguration(CurrentProperties);
    
  717.  
    
  718. 		else if (!Loaders[Index].AcceptRemoval(CurrentProperties))
    
  719. 			log(RemovalCancelled@Loaders[Index],'ConfigManager');
    
  720.  
    
  721. 		Index++;
    
  722. 	}
    
  723.  
    
  724. 	Disable('Tick');
    
  725. 	if (DEBUG)
    
  726. 	{
    
  727. 		log("",'ApplyLoaderSettings');
    
  728. 		log("END OF GAME SERVERACTORS",'ApplyLoaderSettings');
    
  729. 		for (i = 0; i < GE.ServerActors.Length; i++)
    
  730. 			log("ServerActor["$i$"]:"$GE.ServerActors[i],'ApplyLoaderSettings');
    
  731.  
    
  732. 		log("END OF GAME SERVERPACKAGES",'ApplyLoaderSettings');
    
  733. 		for (i = 0; i < GE.ServerPackages.Length; i++)
    
  734. 			log("ServerPackages["$i$"]:"$GE.ServerPackages[i],'ApplyLoaderSettings');
    
  735.  
    
  736. 		log("",'ApplyLoaderSettings');
    
  737. 	}
    
  738. }
    
  739.  
    
  740. function bool NotInPlayInfo(PlayInfo PI, class<Info> NewInfo)
    
  741. {
    
  742. 	local int i;
    
  743. 	if (PI == None)
    
  744. 	{
    
  745. 		Warn(InvalidPI);
    
  746. 		return false;
    
  747. 	}
    
  748.  
    
  749. 	for (i=0;i<PI.InfoClasses.Length;i++)
    
  750. 	{
    
  751. 		if (PI.InfoClasses[i] == NewInfo)
    
  752. 			return false;
    
  753. 	}
    
  754.  
    
  755. 	return true;
    
  756. }
    
  757.  
    
  758. function array<string> GetAllManagedActors()
    
  759. {
    
  760. 	local int i;
    
  761. 	local array<string> Arr;
    
  762.  
    
  763. 	for (i = 0; i < LoaderClasses.Length; i++)
    
  764. 		Arr = AddS(Arr,LoaderClasses[i].AutoLoaderClass.static.GetManagedActors());
    
  765.  
    
  766. 	return Arr;
    
  767. }
    
  768.  
    
  769. static final function float GetConfigMasterVersion()
    
  770. {
    
  771. 	return VERSION;
    
  772. }
    
  773.  
    
  774. // following function copied from wUtils (El_Muerte[TDS])
    
  775. static final function array<string> AddS(array<string> A, array<string> B)
    
  776. {
    
  777.   local int i;
    
  778.   for (i = 0; i < B.length; i++)
    
  779.   {
    
  780.     A.length = A.length+1;
    
  781.     A[A.length-1] = B[i];
    
  782.   }
    
  783.   return A;
    
  784. }