I search for solutions in this order: Past Code, Unreal Source, Wiki, BUF, groups.yahoo, google, screaming at monitor. – RegularX

Legacy:ConfigMaster

From Unreal Wiki, The Unreal Engine Documentation Site
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>			SA${1}< ${3} >
  25. 	var string				SAName;
  26. 	var string				SADescription;
  27. };
  28.  
  29. struct AL
  30. {
  31. 	var class<AutoLoader>	AutoLoader${1}< ${3} >
  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 InvalidLoader${1}< ${3} >
  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>	Loader${1}< ${3} >
  146. 	local class<Info>		ServerActor${1}< ${3} >
  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 = Loader${1}< ${3} >
  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 = ServerActor${1}< ${3} >
  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				Relevant${1}< ${3} >
  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].SA${1}< ${3} >
  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] = Relevant${1}< ${3} >
  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] = Relevant${1}< ${3} >
  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 Temp${1}< ${3} >
  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] = Temp${1}< ${3} >
  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] = Temp${1}< ${3} >
  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] = Temp${1}< ${3} >
  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. }