| Home Page | Recent Changes

AutoLoader

UT2003 :: Actor >> Info >> AutoLoader (Package: ConfigManager)

Here's an /example on how to use this class

00001  //-----------------------------------------------------------
00002  //  ConfigManager.AutoLoader
00003  //
00004  //  This class has two functions:
00005  //  1. Perform all required ini changes needed for your mod.  Will also UNDO
00006  //     any changes made to the ini if your mod is deactivated.
00007  //     Additional benefit of auto-installation of your mutator on a dedicated
00008  //     server (to enable set bEnableMyLoader=True in defaultproperties)
00009  //
00010  //  2.  Pass FillPlayInfo() calls to mutators which are not part of the game's
00011  //      mutator list (such as mutators which only require ServerActors= lines in ini)
00012  //
00013  //-----------------------------------------------------------
00014  class AutoLoader extends Info
00015      abstract;
00016  
00017  // Quick note about debugging - By setting DEBUG=True in defaultproperties of your
00018  // AutoLoader subclass when compiling, you can receive large amounts of debug data.
00019  // However, you will quickly encounter the 1024 byte limit if you use ucc.exe to
00020  // start the testing server.  By starting a server using the "ut2003 -server" command,
00021  // you will bypass this limit, since ut2003.exe does not have these limitations.
00022  
00023  var const bool DEBUG;
00024  var const bool DEBUGPROPS;
00025  
00026  var ConfigMaster                Manager;            // Pointer to ConfigMaster mutator
00027  var string                      InteractionClass;   // Not yet implemented
00028  
00029  //=======================================
00030  //  Loading ServerActors
00031  //=======================================
00032  // Pointer to GameEngine
00033  var GameEngine                  GE;
00034  
00035  // This loader includes a server-side only mutator or server actor
00036  // that will not be part of the mutator chain (will receive FillPlayInfo() calls)
00037  var() bool                      bIncludeServerActor;
00038  
00039  // Classname of the ServerActor this loader loads
00040  //  Same value as what would otherwise be your mod's
00041  //  ServerActors= line in the .ini file.
00042  var() string ActorClass;
00043  
00044  // Friendly Name of the Server Actor class
00045  //  Used by webadmin/adminmenu as the name of the server actor
00046  var() localized string          FriendlyName;
00047  var() localized string          ActorDescription;
00048  
00049  // Lock this loader to a certain version (or higher) of your mod
00050  var() string            RequiredVersion;    // Required version of actor
00051  var() localized string  VersionWarning;     // Message to write to server log if version not enough
00052  var() localized string  DownloadMsg;        // Message to write to log
00053  
00054  //=======================================
00055  //  Automatic configuration changes
00056  //=======================================
00057  // A single ini change
00058  struct IniEntry
00059  {
00060      var() string ClassFrom; // Class which contains the setting we want to change
00061      var() string PropName;  // Name of the variable we're trying to change
00062      var() string PropValue; // Value to apply
00063  };
00064  
00065  // Array of ini settings required by this mod
00066  var()   array<IniEntry>                 RequiredIniEntries;
00067  var     array<Property>                 Properties;
00068  
00069  
00070  //###################################################################
00071  //###################################################################
00072  //
00073  //  Public methods - should be subclassed to customize loader's response
00074  
00075  // if return true, loader class will be spawned
00076  static function bool IsActive()
00077  {
00078      return false;
00079  }
00080  
00081  // should be subclassed - set loader to active/will be included next match
00082  static function bool EnableLoader(optional string SpecialActor)
00083  {
00084      return false;
00085  }
00086  
00087  // should be subclassed
00088  static function bool DisableLoader(optional string SpecialActor)
00089  {
00090      return true;
00091  }
00092  
00093  // called on all loader classes - used to activate loader based on active mutators
00094  static function bool CheckCurrentMutators(string URL)
00095  {
00096      return false;
00097  }
00098  
00099  // called on all loader classes which have bIncludeServerActor=True - used to activate loader based on manual ServerActor entry
00100  static function bool CheckStrayActors(string ServerActors)
00101  {
00102      local int i;
00103      local bool bAddMe;
00104  
00105      if (default.bIncludeServerActor)
00106          if (InStr(ServerActors,default.ActorClass) != -1)
00107              bAddMe = EnableLoader();
00108  
00109      for (i = 0; i < default.RequiredIniEntries.Length; i++)
00110          if (!bAddMe && default.RequiredIniEntries[i].ClassFrom ~= "Engine.GameEngine" && default.RequiredIniEntries[i].PropName ~= "ServerActors")
00111              if (InStr(ServerActors,default.RequiredIniEntries[i].PropValue) != -1)
00112                  bAddMe = EnableLoader();
00113  
00114      if (default.DEBUG)
00115      {
00116          log(default.Class@"Received string value:"$ServerActors,'CheckStrayActors');
00117          log(default.Class@"Returning"@bAddMe,'CheckStrayActors');
00118      }
00119      return bAddMe;
00120  }
00121  
00122  // Only managed actors can be added to Ladder profiles
00123  // Normally, only the ActorClass of your loader (if bIncludeServerActor=True) would be need to be managed
00124  static function array<string> GetManagedActors()
00125  {
00126      local int i;
00127      local string A, B, C;
00128      local array<string> ABC;
00129  
00130      i = -1;
00131      while (static.AddManagedActor(i++,A,B,C))
00132          ABC[ABC.Length] = A$","$B$","$C;
00133  
00134      return ABC;
00135  }
00136  
00137  // Managed actors will be passed FillPlayInfo() calls
00138  static function bool AddManagedActor(int Idx, out string ActorClassName, out string ActorName, out string ActorDesc)
00139  {
00140      if (Idx == -1 && default.bIncludeServerActor)
00141      {
00142          ActorClassName = default.ActorClass;
00143          ActorName = default.FriendlyName;
00144          ActorDesc = default.ActorDescription;
00145          return true;
00146      }
00147  
00148      return false;
00149  }
00150  
00151  // Optional hook for version filtering
00152  static function bool MatchesVersion(float ActorVersion, optional bool bExact, optional string NewURL)
00153  {
00154      local float CurrentVersion;
00155      local string LogText;
00156  
00157      if (default.RequiredVersion == "")
00158          return true;
00159  
00160      CurrentVersion = float(default.RequiredVersion);
00161  
00162      // Return false if loader version is higher than actor version
00163      // Return false if loader version is lower than actor version and bExact=True
00164      if ((ActorVersion < CurrentVersion) || (ActorVersion > CurrentVersion && bExact))
00165      {
00166          if (default.VersionWarning != "")
00167          {
00168              LogText = static.ReplaceTag(default.VersionWarning,"%CurVer%",CurrentVersion);
00169              LogText = static.ReplaceTag(LogText,"%ReqVer%",ActorVersion);
00170              log(LogText);
00171          }
00172  
00173          if (NewURL != "")
00174              log(static.ReplaceTag(default.DownloadMsg,"%URL%",NewURL));
00175  
00176          return false;
00177      }
00178  
00179      return true;
00180  }
00181  
00182  // To prevent your loader from causing a server crash, add your checks here
00183  // return false to prevent your loader from being loaded
00184  
00185  // You only need to override this function if bIncludeServerActor=False in your loader,
00186  // or if you have RequiredIniChanges that reference additional custom packages
00187  static function bool ValidateLoader()
00188  {
00189      local class<Info>   MyActor;
00190  
00191      if (default.bIncludeServerActor && default.ActorClass != "")
00192      {
00193          // Specify True for 3rd param in DynamicLoadObject to prevent log spam if MyActor isn't on server
00194          MyActor = class<Info>(DynamicLoadObject(default.ActorClass,class'Class',True));
00195          if (MyActor == None)
00196              return false;
00197      }
00198  
00199      return true;
00200  }
00201  
00202  // Hook for loader to cancel external removal request, or effect any specialized ini changes to make before removal
00203  function bool AcceptRemoval(optional array<Property> Props)
00204  {
00205      if (Props.Length > 0)
00206          Properties = Props;
00207  
00208      RemoveMe();
00209      return true;
00210  }
00211  
00212  // should be subclassed
00213  // always use "return !bEnableMyLoader;"
00214  // see LadderLoader.LadderLoader or TeamBalanceLoader.BalanceLoader for examples
00215  function bool WantsToBeDisabled()
00216  {
00217      return false;
00218  }
00219  
00220  // called for each RequiredIniEntry
00221  // return true to apply the RequiredIniEntry.PropValue
00222  function bool ObjectNeedsUpdate(Object O, string PropName, string PropValue)
00223  {
00224      local string Temp;
00225  
00226      Temp = O.GetPropertyText(PropName);
00227      if ( InStr(Caps(Temp),Caps(PropValue)) < 0 )
00228          return true;
00229  
00230      return false;
00231  }
00232  
00233  // notification of pending update - return false to skip update for loader
00234  function bool ApplyUpdate()
00235  {
00236      if (DEBUG) log(class@"Returning"@IsActive(),'ApplyUpdate');
00237      return IsActive();
00238  }
00239  
00240  // return -1 if want to simply add entry
00241  // return index of array entry if want to overwrite
00242  function int CheckArrayEntry(string PropName, array<string> PropArray)
00243  {
00244      return -1;
00245  }
00246  
00247  // To maintain consistency, always add to "Server Actors" page
00248  // static function FillPlayInfo(PlayInfo PI)
00249  // {
00250  //      Super.FillPlayInfo(PI);
00251  //      PI.AddSetting("ServerActors",....
00252  // }
00253  //
00254  //###################################################################
00255  //###################################################################
00256  //
00257  //  Public Final Methods
00258  //  These are used to operate the internal mechanisms of the auto loader system.
00259  //
00260  //
00261  
00262  // Called by ConfigMaster when Level.ServerTravel is called
00263  
00264  // Removes loader if WantsToBeDisabled() returns True
00265  // Applies value for RequiredIniProperties if ObjectNeedsUpdate returns true
00266  final function UpdateConfiguration(array<Property> Props)
00267  {
00268      local Object            O;
00269      local Property          P;
00270  
00271      local string            N,V;
00272      local int               i, j;
00273  
00274      local array<string>     Arr;
00275      local string            ArrS;
00276  
00277      if (DEBUG)
00278          log("Update configuration in"@class,'UpdateConfiguration');
00279  
00280      ResetConfig();
00281      Properties = Props;
00282  
00283      if (WantsToBeDisabled())
00284      {
00285          RemoveMe();
00286          return;
00287      }
00288  
00289      if (bIncludeServerActor && ActorClass != "")
00290      {
00291          O = GetObjectOfClass(class'Engine.GameEngine');
00292          if (O != None)
00293          {
00294              if (ObjectNeedsUpdate(O, "ServerActors", ActorClass))
00295              {
00296                  ArrS = O.GetPropertyText("ServerActors");
00297                  if (ArrS != "")
00298                      Arr = GenerateArray(ArrS);
00299  
00300                  j = -1;
00301                  if (Arr.Length > 0)
00302                      j = CheckArrayEntry("ServerActors", Arr);
00303  
00304                  if (j < 0)
00305                      O.SetPropertyText("ServerActors",AddDynArrayMember(O,"ServerActors",ActorClass));
00306  
00307                  else O.SetPropertyText("ServerActors",InsertArrayMember(O, "ServerActors", ActorClass, j));
00308                  O.SaveConfig();
00309              }
00310          }
00311      }
00312  
00313      for (i = 0;i<RequiredIniEntries.Length;i++)
00314      {
00315          O = GetObjectForEntry(RequiredIniEntries[i]);
00316          if (O == None) continue;
00317  
00318          if (!ObjectNeedsUpdate(O, RequiredIniEntries[i].PropName, RequiredIniEntries[i].PropValue)) continue;
00319  
00320          N = RequiredIniEntries[i].PropName;
00321          V = RequiredIniEntries[i].PropValue;
00322          P = GetProperty(O, N);
00323          if (DEBUG)
00324              log(class@"got property"@p,'UpdateConfiguration');
00325  
00326          if (P == None) continue;
00327  
00328          j = -1;
00329  
00330          if (PropIsArray(P))
00331          {
00332              ArrS = O.GetPropertyText(N);
00333              if (ArrS != "")
00334                  Arr = GenerateArray(ArrS);
00335  
00336              if (Arr.Length > 0)
00337                  j = CheckArrayEntry(N, Arr);
00338  
00339              if (j < 0)
00340                  O.SetPropertyText(N,AddDynArrayMember(O,N,V));
00341  
00342              else O.SetPropertyText(N,InsertArrayMember(O, N, V, j));
00343          }
00344  
00345          else
00346          {
00347              StoreDefaultValue(O, N);
00348              O.SetPropertyText(N,V);
00349          }
00350  
00351          O.SaveConfig();
00352      }
00353  }
00354  
00355  // Regarding OriginalValues
00356  final function StoreDefaultValue(Object O, string PropName)
00357  {
00358      local int i, idx;
00359      local IniEntry NewDefault;
00360      local string CurrentValue, Quote;
00361      local array<string> Ar;
00362  
00363      if (DEBUG)
00364          log(class@"storing default"@o@propname,'StoreDefaultValue');
00365  
00366      for (i = 0; i < ConfigMaster(Owner).OriginalValues.Length; i++)
00367          if (ConfigMaster(Owner).OriginalValues[i].ClassFrom == string(O.Class) && ConfigMaster(Owner).OriginalValues[i].PropName == PropName)
00368              return;
00369  
00370      NewDefault.ClassFrom = string(O.Class);
00371      // Check if this property name is a single array member
00372      i = -1; idx = -1;
00373      i = InStr(PropName, "§");
00374      if (i != -1)
00375      {
00376          idx = int(Left(PropName, i));
00377          PropName = Mid(PropName, i + 1);
00378          CurrentValue = O.GetPropertyText(PropName);
00379          Ar = GenerateArray(CurrentValue);
00380          CurrentValue = Ar[idx];
00381  
00382          // Remove literal string wrapper
00383          if (Left(CurrentValue,1) == "\"")
00384          {
00385              CurrentValue = Mid(CurrentValue,1,Len(CurrentValue) - 2);
00386              Quote = "¶";
00387          }
00388          CurrentValue = idx $ "§" $ CurrentValue $ Quote;
00389      }
00390  
00391      else CurrentValue = O.GetPropertyText(PropName);
00392  
00393      NewDefault.PropName = PropName;
00394      NewDefault.PropValue = CurrentValue;
00395      if (DEBUG)
00396          log(class@"old value:"@NewDefault.PropValue,'StoreDefaultValue');
00397  
00398      ConfigMaster(Owner).OriginalValues[ConfigMaster(Owner).OriginalValues.Length] = NewDefault;
00399      ConfigMaster(Owner).SaveConfig();
00400  }
00401  
00402  final function bool RestoreOriginalValue(Object O, string PropName)
00403  {
00404      local int i, j, idx;
00405      local string CurrentValue, StoredValue;
00406      local array<string> Ar;
00407  
00408      for (i = 0; i < ConfigMaster(Owner).OriginalValues.Length; i++)
00409      {
00410          if (ConfigMaster(Owner).OriginalValues[i].ClassFrom ~= string(O.Class) && ConfigMaster(Owner).OriginalValues[i].PropName ~= PropName)
00411          {
00412              StoredValue = ConfigMaster(Owner).OriginalValues[i].PropValue;
00413              // First check if this was a single array member
00414              j = InStr(StoredValue, "§");
00415              if (j != -1)
00416              {
00417                  idx = int(Left(StoredValue, j));
00418                  StoredValue = Mid(StoredValue, j + 1);
00419                  if (Right(StoredValue, 1) == "¶")
00420                  {
00421                      StoredValue = Left(StoredValue, Len(StoredValue) - 1);
00422                      StoredValue = "\"" $ StoredValue $ "\"";
00423                  }
00424                  CurrentValue = O.GetPropertyText(PropName);
00425                  Ar = GenerateArray(CurrentValue);
00426                  Ar[idx] = StoredValue;
00427                  StoredValue = "(" $ Join(Ar,",",True) $")";
00428              }
00429  
00430              if (DEBUG)
00431                  log(class@"Assigning"@StoredValue@"to property"@string(O.Class)$"."$PropName,'RestoreOriginalValue');
00432              O.SetPropertyText(PropName, StoredValue);
00433              O.SaveConfig();
00434              break;
00435          }
00436      }
00437  
00438      if (i < ConfigMaster(Owner).OriginalValues.Length)
00439      {
00440          ConfigMaster(Owner).OriginalValues.Remove(i, 1);
00441          ConfigMaster(Owner).SaveConfig();
00442          return true;
00443      }
00444  
00445      return false;
00446  }
00447  
00448  //###################################################################
00449  //###################################################################
00450  //
00451  //  Internal Methods
00452  //  These are used to control the internal operation of the loader itself.
00453  //  These methods may only be called by other methods within the loader.
00454  //
00455  
00456  protected final function RemoveMe()
00457  {
00458      local int i;
00459      local Object O;
00460      local Property P;
00461  
00462      if (DEBUG)
00463          log(class@"being removed.",'RemoveMe');
00464  
00465      if (bIncludeServerActor && ActorClass != "")
00466      {
00467          O = GetObjectOfClass(class'Engine.GameEngine');
00468          if (O != None)
00469              RemoveArrayEntry(O, "ServerActors", ActorClass);
00470      }
00471  
00472      for (i = 0; i < RequiredIniEntries.Length; i++)
00473      {
00474          O = GetObjectForEntry(RequiredIniEntries[i]);
00475          if (O == None) continue;
00476  
00477          P = GetProperty(O,RequiredIniEntries[i].PropName);
00478          if (P != None && PropIsArray(P))
00479              RemoveArrayEntry(O,RequiredIniEntries[i].PropName,RequiredIniEntries[i].PropValue);
00480  
00481          else RestoreOriginalValue(O, RequiredIniEntries[i].PropName);
00482      }
00483  
00484      DisableLoader();
00485  }
00486  
00487  protected final function string InsertArrayMember(Object Obj, string PropName, string NewValue, int Pos)
00488  {
00489      local string CurValue, Quote, Tmp;
00490      local array<string> Members;
00491      local bool bStatic;
00492  
00493      if (Obj == None)
00494      {
00495          Warn("Object is None");
00496          return "";
00497      }
00498  
00499      CurValue = Obj.GetPropertyText(PropName);
00500      Members = GenerateArray(CurValue);
00501  
00502      if (DEBUG)
00503      {
00504          log(class$":Inserting new member at position"@Pos@"to"@Obj$"."$PropName$":"@NewValue,'InsertArrayMember');
00505          log(class$":Current Value:"$CurValue,'InsertArrayMember');
00506      }
00507  
00508  // Check for literal string
00509      if (InStr(Caps(CurValue), Caps(NewValue)) < 0 && Members.Length > 0)
00510      {
00511          bStatic = Left(Members[pos], Len(PropName) + 1) ~= (PropName $ "[");
00512          Tmp = StringIf(bStatic, Mid(Members[pos],InStr(Members[pos],"=") + 1), Members[0]);
00513          Quote = StringIf(Left(Tmp,1) == "\"" && Left(NewValue,1) != "\"","\"","");
00514  
00515          NewValue = StringIf(bStatic, PropName $ "=" $ Quote $ NewValue $ Quote, Quote $ NewValue $ Quote);
00516          if (DEBUG)
00517              log(InStr(Caps(CurValue),Caps(NewValue))@InStr(Caps(CurValue),Caps(NewValue))<0@Caps(CurValue)@"||"@Caps(NewValue),'AddDynArrayMember');
00518  
00519          if (NewValue != "" && Pos > -1)
00520          {
00521              StoreDefaultValue(Obj, Pos$"§"$PropName);
00522              Members[Pos] = NewValue;
00523          }
00524  
00525          CurValue = "(" $ Join(Members,",",True) $ ")";
00526      }
00527  
00528      if (DEBUG)
00529      {
00530          log(class@"Returning:"$CurValue,'InsertArrayMember');
00531          log(class@"",'InsertArrayMember');
00532      }
00533  
00534      return CurValue;
00535  }
00536  
00537  // Currently, UT2003 does not support setting static arrays through the use of SetPropertyText
00538  protected final function string AddStaticArrayMember(Object Obj, string PropName, string NewValue)
00539  {
00540      local int i;
00541      local array<string> Members;
00542      local string Quote, TempValue, CurValue;
00543  
00544      if (Obj == None)
00545      {
00546          Warn("Object was None for property"@PropName);
00547          return "";
00548      }
00549  
00550      CurValue = Obj.GetPropertyText(PropName);
00551      Members = GenerateArray(CurValue);
00552  
00553      if (InStr(Caps(CurValue), Caps(NewValue)) < 0)
00554      {
00555          if (Members.Length > 0)
00556          {
00557              TempValue = Mid(Members[0],InStr(Members[0],"=")+1);
00558  
00559              // Check for literal string
00560              Quote = StringIf(Left(TempValue,1) == "\"" && Left(NewValue,1) != "\"", "\"", "");
00561              for (i = 0; i < Members.Length; i++)
00562              {
00563                  if (Members[i] == "")
00564                  {
00565                      Members[i] = PropName $ "[" $ i $ "]=" $ Quote $ NewValue $ Quote;
00566                      break;
00567                  }
00568              }
00569              CurValue = "(" $ Join(Members,",") $")";
00570          }
00571  
00572          else CurValue = "(" $ PropName $ "[0]=" $ NewValue $ ")";
00573      }
00574  
00575      return CurValue;
00576  }
00577  
00578  protected final function string AddDynArrayMember(Object Obj, string PropName, string NewValue)
00579  {
00580      local string CurValue, Quote;
00581      local array<string> Members;
00582  
00583      if (Obj == None)
00584      {
00585          Warn("Object is None");
00586          return "";
00587      }
00588  
00589      CurValue = Obj.GetPropertyText(PropName);
00590      Members = GenerateArray(CurValue);
00591      if (DEBUG)
00592      {
00593          log(class$":Adding new member to"@Obj$"."$PropName$":"@NewValue,'AddDynArrayMember');
00594          log(class$":Current Value:"$CurValue,'AddDynArrayMember');
00595      }
00596  
00597  // Check for literal string
00598      if (InStr(Caps(CurValue), Caps(NewValue)) < 0)
00599      {
00600          if (Members.Length > 0)
00601          {
00602              if (DEBUG)
00603                  log(InStr(Caps(CurValue),Caps(NewValue))@InStr(Caps(CurValue),Caps(NewValue))<0@Caps(CurValue)@"||"@Caps(NewValue),'AddDynArrayMember');
00604  
00605              Quote = StringIf(Left(Members[0],1) == "\"" && Left(NewValue,1) != "\"", "\"", "");
00606              Members[Members.Length] = Quote $ NewValue $ Quote;
00607              CurValue = "(" $ Join(Members,",",True) $ ")";
00608          }
00609          else CurValue = "(" $ NewValue $ ")";
00610      }
00611  
00612      if (DEBUG)
00613      {
00614          log(class@"Returning:"$CurValue,'AddDynArrayMember');
00615          log(class@"",'AddDynArrayMember');
00616      }
00617  
00618      return CurValue;
00619  }
00620  
00621  // UT2003 currently does not support setting the value of static arrays
00622  protected final function RemoveArrayEntry(Object O, string PropName, string PropValue)
00623  {
00624      local int i, j;
00625      local array<string> Members;
00626      local string ArrayString, Quote, Tmp;
00627      local bool bStatic;
00628  
00629      if (O == None)
00630      {
00631          Warn("Object was none for property"@PropName);
00632          return;
00633      }
00634  
00635      ArrayString = O.GetPropertyText(PropName);
00636      if (ArrayString == "")
00637      {
00638          Warn("Property was not found:"@PropName);
00639          return;
00640      }
00641  
00642      if (DEBUG)
00643      {
00644          log(class$": Removing array member"@string(O.Class)$"."$PropName$":"$ArrayString,'RemoveArrayEntry');
00645          log(class$": Member to be removed:"$PropValue,'RemoveArrayEntry');
00646      }
00647  
00648      Members = GenerateArray(ArrayString);
00649      bStatic = Left(Members[0], Len(PropName) + 1) ~= (PropName $ "[");
00650      Tmp = StringIf(bStatic, Mid(Members[0],InStr(Members[0],"=") + 1), Members[0]);
00651      Quote = StringIf(Left(Tmp,1) == "\"" && Left(PropValue,1) != "\"","\"","");
00652  
00653      PropValue = StringIf(bStatic, PropName $ "=" $ Quote $ PropValue $ Quote, Quote $ PropValue $ Quote);
00654      for (i = 0; i < Members.Length; i++)
00655      {
00656          if (DEBUG)
00657              log(class@"Comparing"@i@PropValue@"to"@Members[i],'RemoveArrayEntry');
00658  
00659          if (Members[i] ~= PropValue)
00660              break;
00661      }
00662  
00663      if (i < Members.Length)
00664      {
00665          if (DEBUG) log(class@"Removing array member"@i$":"$Members[i],'RemoveArrayEntry');
00666  
00667          // Check if we should restore a previous value
00668          for (j = 0; j < ConfigMaster(Owner).OriginalValues.Length; j++)
00669          {
00670              if (DEBUG)
00671              {
00672                  log(class@"Checking Backup Value"@j@"class:"$ConfigMaster(Owner).OriginalValues[j].ClassFrom@"against"@string(O.Class),'RemoveArrayEntry');
00673                  log(class@"Checking Backup Value"@j@"Property:"$ConfigMaster(Owner).OriginalValues[j].PropName@"against"@PropName,'RemoveArrayEntry');
00674              }
00675  
00676              if (ConfigMaster(Owner).OriginalValues[j].ClassFrom ~= string(O.Class) &&
00677                  ConfigMaster(Owner).OriginalValues[j].PropName ~= PropName )
00678              {
00679                  RestoreOriginalValue(O, PropName);
00680                  break;
00681              }
00682          }
00683  
00684          if (j < ConfigMaster(Owner).OriginalValues.Length)
00685              return;
00686  
00687          Members.Remove(i,1);
00688      }
00689  
00690      else return;
00691  
00692      PropValue = "(" $ Join(Members,",") $ ")";
00693      if (DEBUG)
00694          log(class@"Assigning"@PropValue@"to property"@string(O.Class)$"."$PropName,'RemoveArrayEntry');
00695      O.SetPropertyText(PropName,PropValue);
00696      O.SaveConfig();
00697      if (DEBUG)
00698          log(class@"Returning"@O.GetPropertyText(PropName),'RemoveArrayEntry');
00699  }
00700  
00701  // Just a function to handle safe object creation
00702  protected final function Object GetObjectForEntry(IniEntry ThisEntry)
00703  {
00704      local Object O;
00705      local class<Object> OClass;
00706  
00707      if (DEBUG)
00708          log(class@"Getting"@ThisEntry.ClassFrom@ThisEntry.PropName@ThisEntry.PropValue,'GetObjectForEntry');
00709  
00710      OClass = class<Object>(DynamicLoadObject(ThisEntry.ClassFrom,class'Class'));
00711      if (OClass == None)
00712      {
00713          Warn("Could not load class"@ThisEntry.ClassFrom);
00714          return None;
00715      }
00716  
00717      O = GetObjectOfClass(OClass);
00718      if (O == None)
00719          Warn("Unable to access object for class"@OClass);
00720  
00721      return O;
00722  }
00723  
00724  protected final function Object GetObjectOfClass(class<Object> ObjClass)
00725  {
00726      local Object Obj;
00727      local Actor A;
00728  
00729      if (DEBUG)
00730          log(class@"Finding"@ObjClass,'GetObjectOfClass');
00731  
00732      // Check for GameEngine
00733      if (ObjClass == class'GameEngine')
00734          return GE;
00735  
00736      // First try the easy way
00737      foreach AllObjects(ObjClass,Obj)
00738          return Obj;
00739  
00740      // Object may not be loaded right now, so attempt to load it
00741      // If actor, spawn it
00742      if (ClassIsChildOf(ObjClass,class'Actor'))
00743      {
00744          A = Spawn(class<Actor>(ObjClass));
00745          A.GoToState('');
00746          return A;
00747      }
00748  
00749      // if object, new it
00750      Obj = new(None) ObjClass;
00751  
00752      // might be property
00753      if (Obj == None)
00754          Obj = new(Class) ObjClass;
00755  
00756      // Don't know if this will even work ?
00757      if (Obj == None)
00758          Obj = New(ObjClass.default.Outer) ObjClass;
00759  
00760      if (DEBUG)
00761      {
00762          log(class@"Could not create new object"@ObjClass,'GetObjectOfClass');
00763          log(class@ObjClass@"outer is"@ObjClass.default.Outer,'GetObjectOfClass');
00764          log(class@"",'GetObjectOfClass');
00765      }
00766  
00767      return Obj;
00768  }
00769  
00770  protected final function Property GetProperty(Object O, string PropName)
00771  {
00772      local int i;
00773      local Class ClassOuter;
00774      local bool classexact, classchild, propn, seenclass;
00775  
00776      for (i=0;i<Properties.Length;i++)
00777      {
00778          seenclass = Class(Properties[i].Outer) == ClassOuter;
00779  
00780          ClassOuter = Class(Properties[i].Outer);
00781          if (DEBUGPROPS)
00782          {
00783              if (ClassOuter == None)
00784              {
00785                  log(class@"Property Outer is not a class!",'GetProperty');
00786                  continue;
00787              }
00788  
00789              if (!seenclass)
00790              {
00791                  log(class@"Compare Obj Class"@O.Class@"to"@Properties[i].Outer,'GetProperty');
00792                  if (O.Class==Properties[i].Outer)
00793                      classexact = true;
00794              }
00795  
00796              if (!classchild && ClassIsChildOf(O.Class,ClassOuter))
00797              {
00798                  log(class@"Obj class"@O.Class@"is child of"@ClassOuter,'GetProperty');
00799                  classchild = true;
00800              }
00801  
00802              else if (!classchild && ClassIsChildOf(ClassOuter,O.Class))
00803              {
00804                  log(class@"Obj class"@O.Class@"is parent of"@ClassOuter,'GetProperty');
00805                  classchild = true;
00806              }
00807  
00808              if (!propn && classexact)
00809              {
00810                  log(class@"Compare Name"@PropName@"to"@Properties[i].Name,'GetProperty');
00811                  if (PropName == string(Properties[i].Name))
00812                      propn = true;
00813              }
00814          }
00815  
00816          if ((ClassIsChildOf(O.Class,ClassOuter)||O.Class == Properties[i].Outer||ClassIsChildOf(ClassOuter,O.Class)) && string(Properties[i].Name) == PropName)
00817          {
00818              if (DEBUG)
00819              {
00820                  log(class@"Returning Property"@Properties[i],'GetProperty');
00821                  log(class@"",'GetProperty');
00822              }
00823  
00824              return Properties[i];
00825          }
00826      }
00827  
00828      return None;
00829  }
00830  
00831  protected final function bool PropIsArray(Property P)
00832  {
00833      if (DEBUG)
00834          log(class@"Checking Property"@P.Outer$"."$P.Name$":"@P.Class,'PropIsArray');
00835      return P.Class == class'ArrayProperty';
00836  }
00837  
00838  protected static final function array<string> GenerateArray(string ArrayString)
00839  {
00840      local array<string> Members;
00841      local int i;
00842      local string S;
00843  
00844      if (ArrayString != "")
00845      {
00846          // Remove the array wrapper ( )
00847          ArrayString = Mid(ArrayString,1,Len(ArrayString)-2);
00848  
00849          // If string contains internal containers, then have to split differently
00850          if (Left(ArrayString,1) == "(")
00851          {
00852              do {
00853                  do {
00854                      if (Left(ArrayString,1) == ")")
00855                          i--;
00856                      else if (Left(ArrayString,1) == "(")
00857                          i++;
00858                      Eat(S, ArrayString, 1);
00859                  } until (i == 0);
00860  
00861                  Members[Members.Length] = S;
00862                  S = "";
00863                  if (ArrayString != "" && Left(ArrayString,1) == ",")
00864                      ArrayString = Mid(ArrayString,1);
00865              } until (ArrayString == "");
00866          }
00867  
00868          else Split2(ArrayString,",",Members);
00869      }
00870  
00871      return Members;
00872  }
00873  
00874  protected static final function bool NotInPlayInfo(PlayInfo PI, class<Info> NewInfo)
00875  {
00876      local int i;
00877      if (PI == None)
00878      {
00879          Warn("Invalid PlayInfo Object!");
00880          return false;
00881      }
00882  
00883      for (i=0;i<PI.InfoClasses.Length;i++)
00884      {
00885          if (PI.InfoClasses[i] == NewInfo)
00886              return false;
00887      }
00888  
00889      return true;
00890  }
00891  
00892  
00893  //###################################################################
00894  //###################################################################
00895  //
00896  //  Utility Methods
00897  //  These are used perform various tedious operations.
00898  //
00899  // Moves Num elements from Source to Dest
00900  static final function Eat(out string Dest, out string Source, int Num)
00901  {
00902      Dest = Dest $ Left(Source, Num);
00903      Source = Mid(Source, Num);
00904  }
00905  
00906  static final function string StringIf(bool Condition, string IfTrue, string IfFalse)
00907  {
00908      if (Condition) return IfTrue;
00909      return IfFalse;
00910  }
00911  
00912  // Based on AccessControlIni & Object.ReplaceText()
00913  static final function string ReplaceTag(string from, string tag, coerce string with)
00914  {
00915      local int i;
00916      local string t;
00917  
00918      // InStr() is case-sensitive
00919      i = InStr(Caps(from), Caps(tag));
00920      while (i != -1)
00921      {
00922          t = t $ Left(from,i) $ with;
00923          from = mid(from,i+len(tag));
00924          i = InStr(Caps(from), Caps(tag));
00925      }
00926  
00927      t = t $ from;
00928      return t;
00929  }
00930  
00931  // Following functions from wUtils103 by El_Muerte[TDS]
00932  // Included by permission (copied to avoid package dependancy)
00933  
00934  // Shifts an element off a string
00935  // example (delim = ' '): 'this is a string' -> 'is a string'
00936  // if quotechar = " : '"this is" a string' -> 'a string'
00937  static final function string StrShift(out string line, string delim, optional string quotechar)
00938  {
00939      local int delimpos, quotepos;
00940      local string result;
00941  
00942      if ( quotechar != "" && Left(line, Len(quotechar)) == quotechar ) {
00943          do {
00944              quotepos = InstrFrom(line, quotechar, quotepos + 1);
00945          } until (quotepos == -1 || quotepos + Len(quotechar) == Len(line)
00946                  || Mid(line, quotepos + len(quotechar), len(delim)) == delim);
00947      }
00948      if ( quotepos != -1 ) {
00949          delimpos = InstrFrom(line, delim, quotepos);
00950      }
00951      else {
00952          delimpos = Instr(line, delim);
00953      }
00954  
00955      if (delimpos == -1)
00956      {
00957          result = line;
00958          line = "";
00959      }
00960      else {
00961          result = Left(line,delimpos);
00962          line = Mid(line,delimpos+len(delim));
00963      }
00964      if ( quotechar != "" && Left(result, Len(quotechar)) == quotechar ) {
00965        result = Mid(result, Len(quotechar), Len(result)-(Len(quotechar)*2));
00966      }
00967      return result;
00968  }
00969  
00970  // Join the elements of a string array to an array
00971  static final function string Join(array< string > ar, optional string delim, optional bool bIgnoreEmpty)
00972  {
00973    local string result;
00974    local int i;
00975    for (i = 0; i < ar.length; i++)
00976    {
00977      if (bIgnoreEmpty && ar[i] == "") continue;
00978      if (result != "") result = result$delim;
00979      result = result$ar[i];
00980    }
00981  
00982    return result;
00983  }
00984  
00985  // Fixed split method
00986  // no problems when it starts with a delim
00987  // no problems with ending spaces
00988  // delim can be a string
00989  static final function int Split2(coerce string src, string delim, out array<string> parts, optional bool ignoreEmpty, optional string quotechar)
00990  {
00991    local string temp;
00992    Parts.Remove(0, Parts.Length);
00993    if (delim == "" || Src == "" ) return 0;
00994    while (src != "")
00995    {
00996      temp = StrShift(src, delim, quotechar);
00997      if (temp == "")
00998      {
00999        if (!ignoreEmpty)
01000        {
01001          parts.length = parts.length+1;
01002          parts[parts.length-1] = temp;
01003        }
01004      }
01005      else {
01006        parts.length = parts.length+1;
01007        parts[parts.length-1] = temp;
01008      }
01009    }
01010    return parts.length;
01011  }
01012  
01013  // InStr starting from an offset
01014  static final function int InStrFrom(coerce string StrText, coerce string StrPart, optional int OffsetStart)
01015  {
01016    local int OffsetPart;
01017  
01018    OffsetPart = InStr(Mid(StrText, OffsetStart), StrPart);
01019    if (OffsetPart >= 0)
01020      OffsetPart += OffsetStart;
01021    return OffsetPart;
01022  }

Wormbo: Hmm, a little documentation instead of the source code wouldn't hurt. E.g. how can you use this to enable/disable a server actor?

El Muerte TDS: like this: [ChatFilter AutoLoader], maybe write a [/example] based on it... first lunch


Category Custom Class

The Unreal Engine Documentation Site

Wiki Community

Topic Categories

Recent Changes

Offline Wiki

Unreal Engine

Console Commands

Terminology

FAQs

Help Desk

Mapping Topics

Mapping Lessons

UnrealEd Interface

UnrealScript Topics

UnrealScript Lessons

Making Mods

Class Tree

Modeling Topics

Chongqing Page

Log In