Prepare fixtures

This commit is contained in:
dkanus 2026-07-14 20:27:09 +07:00
commit 9c94356263
6021 changed files with 722805 additions and 22 deletions

View file

@ -0,0 +1,285 @@
// ====================================================================
// Class: XAdmin.AccessControlIni
// Parent: Engine.AccessControl
//
// <Enter a description here>
// ====================================================================
class AccessControlIni extends AccessControl;
var GameConfigSet ConfigSet;
var AdminBase CSEditor;
event Destroyed()
{
if (CSEditor != None)
{
ConfigSet.EndEdit(false);
AdminIni(CSEditor).ConfigSet = None;
CSEditor = None;
}
Super.Destroyed();
}
function InitPrivs()
{
local int i, cnt;
local xPrivilegeBase xPriv;
Super.InitPrivs();
cnt = 0;
for (i = 0; i<PrivClasses.Length; i++)
{
xPriv = new PrivClasses[i];
if (xPriv != None)
{
PrivManagers.Length = cnt+1;
PrivManagers[cnt] = xPriv;
cnt++;
if (xPriv.LoadMsg != "")
Log(xPriv.LoadMsg);
// Prepare an AllPrivs string
if (AllPrivs != "") AllPrivs = AllPrivs $ "|";
AllPrivs = AllPrivs $ xPriv.MainPrivs $ "|" $xPriv.SubPrivs;
}
else
Log("Invalid Privilege Class:"@PrivClasses[i]);
}
}
event PreBeginPlay()
{
Users=new(Level.xLevel) class'xAdminUserList';
Groups=new(Level.xLevel) class'xAdminGroupList';
class'xAdminConfigIni'.static.Load(Users, Groups, bDontAddDefaultAdmin);
ConfigSet = new(Level.xLevel) class'GameConfigSet';
ConfigSet.Level = Level;
Super(Info).PreBeginPlay();
InitPrivs();
}
function SaveAdmins()
{
class'xAdminConfigIni'.static.Save(Users, Groups);
}
function bool AdminLogin( PlayerController P, string Username, string Password )
{
local xAdminUser User;
local int index;
if (P == None)
return false;
User = GetLoggedAdmin(P);
if (User == None)
{
User = Users.FindByName(UserName);
if (User != None)
{
// Check Password
if (User.Password == Password)
{
index = LoggedAdmins.Length;
LoggedAdmins.Length = index + 1;
LoggedAdmins[index].User = User;
LoggedAdmins[index].PRI = P.PlayerReplicationInfo;
P.PlayerReplicationInfo.bAdmin = User.bMasterAdmin || User.HasPrivilege("Kp") || User.HasPrivilege("Bp");
}
else
User = None;
}
}
return (User != None);
}
function bool AdminLogout( PlayerController P )
{
local int i;
for (i=0; i < LoggedAdmins.Length; i++)
if (LoggedAdmins[i].PRI == P.PlayerReplicationInfo)
{
P.PlayerReplicationInfo.bAdmin = false;
LoggedAdmins.Remove(i, 1);
return true;
}
return false;
}
function SetAdminFromURL(string N, string P)
{
local xAdminGroup xGroup;
local xAdminUser User;
// Check that there is not a User by that name already
// TODO: This check should happen MUCH earlier, like at GUI level.
if (Users.FindByName(N) != None)
{
Log("User"@N@"already in user list, please choose another name");
return;
}
// Find an Admin Group .. and if none, add one called URL::Admin (cant be created manually)
xGroup = Groups.FindByName("URL::Admin");
if (xGroup == None)
{
xGroup = Groups.CreateGroup("URL::Admin", "", 255);
Groups.Add(xGroup);
}
if (xGroup != None)
{
xGroup.bMasterAdmin = true;
xGroup.GameSecLevel = 255;
// Then create a user to add to that group
User = Users.Create(N, P, "");
User.AddGroup(xGroup);
Users.Add(User);
}
}
function bool ValidLogin(string UserName, string Password)
{
local xAdminUser User;
User = Users.FindByName(UserName);
return User != None && User.Password == Password;
}
function bool IsAdmin(PlayerController P)
{
local int i;
for (i=0; i < LoggedAdmins.Length; i++)
if (LoggedAdmins[i].PRI == P.PlayerReplicationInfo)
return true;
return false;
}
function bool IsLogged(xAdminUser User)
{
local int i;
for (i=0; i < LoggedAdmins.Length; i++)
if (LoggedAdmins[i].User == User)
return true;
return false;
}
// Each admin can change his own password
function bool SetAdminPassword(string P)
{
// There is no single Admin Password
// Todo : Find the master admin password and change it ?
return false;
}
function bool AllowPriv(string priv)
{
return true;
}
function SetGamePassword(string P)
{
// TODO: Check privs b4 calling super
Super.SetGamePassword(P);
}
function string GetAdminName(PlayerController PC)
{
local xAdminUser User;
User = GetLoggedAdmin(PC);
if (User != None)
{
return User.UserName;
}
return "Unknown";
}
function AdminEntered( PlayerController P, string Username)
{
Log(P.PlayerReplicationInfo.PlayerName@"logged in as"@Username$".");
Level.Game.Broadcast( P, P.PlayerReplicationInfo.PlayerName@"logged in as a server administrator." );
}
// Verify if an admin action can be performed by a player
function bool CanPerform(PlayerController P, string Action)
{
local int i;
for (i=0; i<LoggedAdmins.Length; i++)
if (LoggedAdmins[i].PRI == P.PlayerReplicationInfo)
return LoggedAdmins[i].User.HasPrivilege(Action);
return false;
}
function bool ReportLoggedAdminsTo(PlayerController P)
{
return false;
}
function bool LockConfigSet(out GameConfigSet GCS, AdminBase Admin)
{
if (CSEditor == None)
{
CSEditor = Admin;
GCS = ConfigSet;
return true;
}
return false;
}
function bool ReleaseConfigSet(out GameConfigSet GCS, AdminBase Admin)
{
if (CSEditor == Admin && GCS == ConfigSet)
{
CSEditor = None;
GCS = None;
return true;
}
return false;
}
/////////////////////////////////////////////////////////////////////
// Local Functions Area
//
//
function xAdminUser GetLoggedAdmin(PlayerController P)
{
local int i;
for (i=0; i < LoggedAdmins.Length; i++)
if (LoggedAdmins[i].PRI == P.PlayerReplicationInfo)
return LoggedAdmins[i].User;
return None;
}
function xAdminUser GetUser(string uname)
{
return Users.FindByName(uname);
}
static event bool AcceptPlayInfoProperty(string PropertyName)
{
if ( PropertyName ~= "AdminPassword" )
return false;
return Super.AcceptPlayInfoProperty(PropertyName);
}
defaultproperties
{
PrivClasses(0)=Class'XAdmin.xKickPrivs'
PrivClasses(1)=Class'XAdmin.xGamePrivs'
PrivClasses(2)=Class'XAdmin.xUserGroupPrivs'
PrivClasses(3)=Class'XAdmin.xExtraPrivs'
AdminClass=Class'XAdmin.AdminIni'
}

View file

@ -0,0 +1,645 @@
// ====================================================================
// Class: XAdmin.AdminIni
// Parent: Engine.Admin
//
// TODO: Implement <cmd> help for inline help text ?
// ====================================================================
class AdminIni extends AdminBase;
var AccessControlIni xManager;
var xAdminUser AdminUser;
var GameConfigSet ConfigSet;
var protected string NextMutators;
var protected string NextGameType;
// Localization
var localized string Msg_FinishGameEditFirst;
var localized string Msg_FinishGameRestart;
var localized string Msg_MutNeedGameEdit;
var localized string Msg_NoMutatorInUse;
var localized string Msg_NoUnusedMuts;
var localized string Msg_AddedMutator;
var localized string Msg_ErrAddingMutator;
var localized string Msg_RemovedMutator;
var localized string Msg_ErrRemovingMutator;
var localized string Msg_MapListNeedGameEdit;
var localized string Msg_MustEndGameEdit;
var localized string Msg_EditingClass;
var localized string Msg_EditFailed;
var localized string Msg_AlreadyEdited;
var localized string Msg_NotEditing;
var localized string Msg_EditingCompleted;
var localized string Msg_EditingCancelled;
var localized string Msg_NoBotGameFull;
var localized string Msg_NoAddNamedBot;
var localized string Msg_NoBotsPlaying;
var localized string Msg_GameNoSupportBots;
var localized string Msg_StatsNoBots;
var localized string Msg_SetBotNeedVal;
event Created()
{
Super.Created();
xManager = AccessControlIni(Manager);
}
// Execute an administrative console command on the server.
function DoLogin( string Username, string Password )
{
if (AdminUser == None && xManager.AdminLogin(Outer, Username, Password))
{
bAdmin = true;
AdminUser = xManager.GetLoggedAdmin(Outer);
xManager.AdminEntered(Outer, Username);
}
}
function DoLogout()
{
if (xManager.AdminLogout(Outer))
{
xManager.ReleaseConfigSet(ConfigSet, Self);
xManager.AdminExited(Outer);
bAdmin=false;
}
}
function RestartCurrentMap()
{
if (CanPerform("Mr") || CanPerform("Mc")) // Mr = MapRestart, Mc = Map Change
{
if (ConfigSet == None)
DoSwitch("?restart");
else
ClientMessage(Msg_FinishGameEditFirst);
}
}
function DoSwitch( string URL)
{
if (CanPerform("Mc"))
{
if (ConfigSet == None)
{
// Rebuild the URL based on edited game settings
if (NextGameType != "" && Level.Game.ParseOption(URL, "Game") == "")
URL=URL$"?Game="$NextGameType;
if (NextMutators != "" && Level.Game.ParseOption(URL, "Mutator") == "")
URL=URL$"?Mutator="$NextMutators;
Level.ServerTravel( URL, false );
}
else
ClientMessage(Msg_FinishGameRestart);
}
}
function GotoNextMap()
{
local string NextMap;
local MapList MyList;
local GameInfo G;
if (CanPerform("Mc"))
{
if (ConfigSet == None)
{
G = Level.Game;
if ( G.bChangeLevels && !G.bAlreadyChanged && (G.MapListType != "") )
{
// open a the nextmap actor for this game type and get the next map
G.bAlreadyChanged = true;
MyList = G.GetMapList(G.MapListType);
if (MyList != None)
{
NextMap = MyList.GetNextMap();
MyList.Destroy();
}
if ( NextMap == "" )
NextMap = GetMapName(G.MapPrefix, NextMap,1);
if ( NextMap != "" )
{
DoSwitch(NextMap);
ClientMessage(Repl(Msg_ChangingMapTo, "%NextMap%", NextMap));
return;
}
}
ClientMessage(Msg_NextMapNotFound);
Level.ServerTravel( "?Restart", false );
}
else
ClientMessage(Msg_FinishGameEditFirst);
}
}
exec function User( string Cmd, string Extra)
{
if (Cmd ~= "List") // Admin User List *mask*
{
SendUserList(Extra);
}
else if (Cmd ~= "Del") // Admin User Del *mask*
{
// TODO: Later .. need to make sure its acceptable to do so
}
else if (Cmd ~= "Logged") // List of currently logged admins
{
SendLoggedList();
}
}
// TODO: Mutators Logic should be separate from GameConfigSet since
// they are not associated to a game type.
exec function Mutators( string Cmd, string Extra)
{
local array<string> Values;
local int i;
if (CanPerform("Mu"))
{
// TODO: Separate Mutator stuff from ConfigSet ?
if (ConfigSet == None)
{
ClientMessage(Msg_MutNeedGameEdit);
return;
}
if (Cmd ~= "Used")
{
// List Used Mutators
Values = ConfigSet.GetUsedMutators();
for (i = 0; i<Values.Length; i++)
ClientMessage(i$")"@Values[i]);
if (i == 0)
ClientMessage(Msg_NoMutatorInUse);
}
else if (Cmd ~= "Unused")
{
Values = ConfigSet.GetUnusedMutators();
for (i = 0; i<Values.Length; i++)
ClientMessage(i$")"@Values[i]);
if (i == 0)
ClientMessage(Msg_NoUnusedMuts);
}
else if (Cmd ~= "Add")
{
Split(Extra, " ", Values);
for (i = 0; i<Values.Length; i++)
{
if (ConfigSet.AddMutator(Values[i]))
ClientMessage(Repl(Msg_AddedMutator, "%Mutator%", Values[i]));
else
ClientMessage(Repl(Msg_ErrAddingMutator, "%Mutator%", Values[i]));
}
}
else if (Cmd ~= "Del")
{
Split(Extra, " ", Values);
for (i = 0; i<Values.Length; i++)
{
if (ConfigSet.DelMutator(Values[i]))
ClientMessage(Repl(Msg_RemovedMutator, "%Mutator%", Values[i]));
else
ClientMessage(Repl(Msg_ErrRemovingMutator, "%Mutator%", Values[i]));
}
}
}
}
function MapListCommand( string Cmd, string Extra )
{
local array<string> Values, Tmp;
local string Str;
local int i, c;
if (CanPerform("Ml"))
{
Cmd = Caps(Cmd);
if (ConfigSet == None)
{
i = MapHandler.GetGameIndex(string(Level.Game.Class));
if (Extra == "")
c = MapHandler.GetActiveList(i);
else c = int(Extra);
Str = MapHandler.GetMapListTitle(i, c);
switch (Cmd)
{
case "LIST":
Values = MapHandler.GetMapListNames(i);
SendComplexMsg(Values, Repl(Msg_AllMapLists, "%gametype%", string(Level.Game.Class)));
break;
case "USED":
Values = MapHandler.GetMapList(i, c);
SendComplexMsg(Values, Repl(Msg_MapRotationList, "%maplist%", Str));
break;
case "SWITCH":
MapHandler.ApplyMapList(i, c);
break;
default:
ClientMessage(Msg_MapListNeedGameEdit);
break;
}
}
else
{
i = MapHandler.GetGameIndex(ConfigSet.GetEditedClass());
switch (Cmd)
{
case "LIST":
if (Extra == "")
{
Values = ConfigSet.GetLists();
SendComplexMsg(Values, "MapLists for"@ConfigSet.GetEditedClass());
}
else
{
Values = ConfigSet.GetMaps();
Str = MapHandler.GetMapListTitle(i, int(Extra));
SendComplexMsg(Values, Repl(Msg_MapRotationList,"%maplist%",Str));
}
break;
case "USED":
Str = Repl(Msg_MapRotationList, "%maplist%", MapHandler.GetMapListTitle(i, ConfigSet.CurrentMapList));
Values = ConfigSet.GetMaps();
if (Values.Length > 0)
SendComplexMsg(Values, Str);
else ClientMessage(Msg_NoMapInRotation);
break;
case "SWITCH":
ClientMessage(Msg_MustEndGameEdit);
break;
case "EDIT":
if (Extra == "") Extra = string(ConfigSet.GetActiveList());
ConfigSet.CurrentMapList = int(extra);
ClientMessage(Repl(Msg_EditingMapList, "%List%", MapHandler.GetMapListTitle(i, ConfigSet.CurrentMapList)));
break;
case "ENDEDIT":
ConfigSet.EndEdit(bool(Extra));
break;
case "NEW":
Str = ConfigSet.GetEditedClass();
MapHandler.AddList(Str, Extra, Values);
ClientMessage(Repl(Msg_MapListAdded, "%listname%", Extra)@Str$".");
break;
case "REMOVE":
Str = MapHandler.GetMapListTitle(i, ConfigSet.CurrentMapList);
MapHandler.RemoveList(i, ConfigSet.CurrentMapList);
ClientMessage(Repl(Msg_MapListRemoved, "%listname%", Str)@ConfigSet.GetEditedClass()$".");
break;
case "ADD":
Values = ConfigSet.AddMaps(Extra);
if (Values.Length == 0)
ClientMessage(Msg_NoMapsAdded@Str$".");
else SendComplexMsg(Values, Msg_AddedMapToList @ MapHandler.GetMapListTitle(i, ConfigSet.CurrentMapList));
break;
case "DEL":
Str = MapHandler.GetMapListTitle(i, ConfigSet.CurrentMapList);
Values = ConfigSet.RemoveMaps(Extra);
if (Values.Length == 0)
ClientMessage(Msg_NoMapsRemoved@Str$".");
else SendComplexMsg(Values, Msg_RemovedFromList @ MapHandler.GetMapListTitle(i, ConfigSet.CurrentMapList));
break;
case "FIND":
Str = MapHandler.GetMapListTitle(i, ConfigSet.CurrentMapList);
Values = ConfigSet.FindMaps(Extra);
for (i = 0; i<Values.Length; i++)
{
if (Left(Values[i], 1) != "+")
{
Tmp[Tmp.Length] = Values[i];
Values.Remove(i--,1);
}
else Values[i] = Mid(Values[i],1);
}
if (Values.Length > 0)
SendComplexMsg(Values, Repl(Msg_MapIsInRotation,"%maplist%",Str));
else ClientMessage(Repl(Msg_NoMapsFound, "%maplist%", Str));
if (Tmp.Length > 0)
SendComplexMsg(Tmp, Repl(Msg_MapIsNotInRotation,"%maplist%",Str));
break;
}
}
}
}
exec function Game( string Cmd, string Extra )
{
local array<string> Params;
local string LastParam, LastValue;
local int p;
if (Cmd ~= "ChangeTo") // Admin Game ChangeTo <gameclass>
{
if (CanPerform("Mt"))
{
if (ConfigSet != None)
{
ClientMessage(Msg_MustEndGameEdit);
return;
}
NextGameType = FindGameType(Extra);
}
return;
}
if (!CanPerform("Ms"))
return;
if (Cmd ~= "Edit") // Admin Game Edit [CTF]
{
if (xManager.LockConfigSet(ConfigSet, Self))
{
if (ConfigSet.StartEdit(Extra))
ClientMessage(Repl(Msg_EditingClass, "%Class%", ConfigSet.GetEditedClass()));
else
{
ClientMessage(Msg_EditFailed);
xManager.ReleaseConfigSet(ConfigSet, Self);
}
}
else
ClientMessage(Msg_AlreadyEdited);
return;
}
if (ConfigSet == None)
{
ClientMessage(Msg_NotEditing);
return;
}
if (Cmd ~= "EndEdit")
{
ConfigSet.EndEdit(true);
NextMutators = ConfigSet.NextMutators;
xManager.ReleaseConfigSet(ConfigSet, Self);
ClientMessage(Msg_EditingCompleted);
}
else if (Cmd ~= "CancelEdit")
{
ConfigSet.EndEdit(false);
xManager.ReleaseConfigSet(ConfigSet, Self);
ClientMessage(Msg_EditingCancelled);
}
else if (Cmd ~= "Get")
{
if (Instr(Extra, "*") == -1 && Instr(Extra, " ") == -1)
{
LastValue = ConfigSet.GetNamedParam(Extra);
if (LastValue == "")
ClientMessage(Repl(Msg_UnknownParam,"%Value%", Extra));
else
ClientMessage(Extra@"="@LastValue);
}
else
{
Params = ConfigSet.GetMaskedParams(Extra);
if (Params.Length == 0)
ClientMessage(Msg_NoParamsFound);
else
for (p = 0; p<Params.Length; p+=2)
ClientMessage(Params[p]@"="@Params[p+1]);
}
}
else if (Cmd ~= "Set")
{
p = Instr(Extra, " ");
if (p >= 0)
{
LastParam = Left(Extra, p);
LastValue = Mid(Extra, p+1);
if (ConfigSet.SetNamedParam(LastParam, LastValue))
{
ClientMessage(Msg_ParamModified);
return;
}
}
ClientMessage(Msg_ParamNotModified);
}
}
protected function bool CanPerform(string priv)
{
return AdminUser != None && AdminUser.HasPrivilege(priv);
}
protected function SendUserList(string mask) // Todo: Mask Feature
{
local xAdminUserList uList;
local int i;
uList = AdminUser.GetManagedUsers(xManager.Groups);
for (i=0; i<uList.Count(); i++)
ClientMessage(string(i)$uList.Get(i).UserName);
}
/// TODO: Check if should send ALL logged admins or only
protected function SendLoggedList()
{
local xAdminUserList uList;
local int i;
uList = AdminUser.GetManagedUsers(xManager.Groups);
for (i=0; i<uList.Count(); i++)
if (xManager.IsLogged(uList.Get(i)))
ClientMessage(string(i)$uList.Get(i).UserName);
}
// All Bots functions are not Persistent unless Level.Game.SaveConfig()
exec function Bots( string Cmd, string Extra)
{
local int MinV, i, j;
local array<string> Params;
local array<XUtil.PlayerRecord> BotList, BotsToAdd;
local DeathMatch Game;
local Controller C, NextC;
local xBot Bot;
if (CanPerform("Mb"))
{
Game = DeathMatch(Level.Game);
if (Game == None)
{
ClientMessage(Msg_GameNoSupportBots);
return;
}
if (Game.GameStats != None)
{
ClientMessage(Msg_StatsNoBots);
return;
}
Params = SplitParams(Extra);
if (Cmd ~= "Add")
{
MinV = Game.MinPlayers;
if (MinV == 32)
{
ClientMessage(Msg_NoBotGameFull);
return;
}
if (Params.Length == 0)
{
Game.ForceAddBot();
}
else if (Params.Length == 1 && IsNumeric(Params[0]))
{
MinV = Min(32, MinV + int(Params[0]));
while (Game.MinPlayers < MinV)
Game.ForceAddBot();
}
else // Else add named bots
{
if (!Game.IsInState('MatchInProgress'))
{
ClientMessage(Msg_NoAddNamedBot);
return;
}
MakeBotsList(BotList);
// First Build a list of Bots to add
for (i = 0; i<BotList.Length; i++)
{
for (j = 0; j<Params.Length; j++)
{
if (MaskedCompare(BotList[i].DefaultName, Params[j]))
{
BotsToAdd[BotsToAdd.Length] = BotList[i];
BotList.Remove(i, 1);
i--;
}
}
}
MinV = Min(32, MinV + BotsToAdd.Length);
while (Game.MinPlayers<MinV)
{
if (!Game.AddBot(BotsToAdd[0].DefaultName))
break;
BotsToAdd.Remove(0, 1);
}
}
}
else if (Cmd ~= "Kill")
{
if (Game.MinPlayers == 0 || Game.NumBots == 0)
{
ClientMessage(Msg_NoBotsPlaying);
return;
}
if (Params.Length == 0) // Kill 1 random bot
{
Game.KillBots(1);
}
else if (Params.Length == 1 && IsNumeric(Params[0])) // Kill a Number of Bots
{
Game.KillBots(int(Params[0]));
}
else // Kill Named Bots
{
// TODO: Rework Loop ?
for (C = Level.ControllerList; C != None; C = NextC)
{
Bot = xBot(C);
NextC = C.NextController;
if (Bot != None && Bot.PlayerReplicationInfo != None)
{
for (i = 0; i<Params.Length; i++)
{
if (MaskedCompare(Bot.PlayerReplicationInfo.PlayerName, Params[i]))
{
Game.KillBot(C);
break;
}
}
}
}
}
}
else if (Cmd ~= "Set") // Minimum number of Players
{
if (Params.Length == 1 && IsNumeric(Params[0]) && int(Params[0]) < 33)
{
Game.MinPlayers=int(Params[0]);
}
else
ClientMessage(Msg_SetBotNeedVal);
}
}
}
function MakeBotsList(out array<XUtil.PlayerRecord> BotList)
{
local xBot Bot;
local int i;
local Controller C;
// Get Full Bot List
class'XUtil'.static.GetPlayerList(BotList);
// Filter out Playing Bots
for (C = Level.ControllerList; C != None; C = C.NextController)
{
Bot = xBot(C);
if (Bot != None && Bot.PlayerReplicationInfo != None)
{
for (i = 0; i<BotList.Length; i++)
{
if (Bot.PlayerReplicationInfo.CharacterName == BotList[i].DefaultName)
{
BotList.Remove(i,1);
break;
}
}
}
}
}
defaultproperties
{
Msg_NoBotGameFull="Cannot add a bot, game is full."
Msg_NoAddNamedBot="Can only add named bots once the match has started"
Msg_NoBotsPlaying="No bots are currently playing"
Msg_GameNoSupportBots="The current Game Type does not support Bots"
Msg_StatsNoBots="Cannot control bots when Worlds Stats are enabled"
Msg_FinishGameEditFirst="You must finish your Game Edit before restarting the map"
Msg_FinishGameRestart="You must finish your Game Edit before changing or restarting the map"
Msg_MutNeedGameEdit="You must use 'Game Edit' command before 'Mutators' commands"
Msg_NoMutatorInUse="No Mutators in use"
Msg_NoUnusedMuts="Found no unused mutators"
Msg_AddedMutator="Added '%Mutator%' to used mutator list."
Msg_ErrAddingMutator="Error Adding '%Mutator%'To Used Mutator List"
Msg_RemovedMutator="Removed '%Mutator%' From Used Mutator List"
Msg_ErrRemovingMutator="Error Removing '%Mutator%' from used mutator List"
Msg_MapListNeedGameEdit="You must use 'Game Edit' command before 'MapList' command"
Msg_MustEndGameEdit="You must end your Game Edit first"
Msg_EditingClass="Editing %Class%"
Msg_EditFailed="Failed Starting To Edit"
Msg_AlreadyEdited="Game Already being edited by Someone Else"
Msg_NotEditing="You are not editing Game Settings, use 'Game Edit' first"
Msg_EditingCompleted="Editing Completed"
Msg_EditingCancelled="Editing Cancelled"
Msg_SetBotNeedVal="This command requires a numeric value between 0 and 32"
}

View file

@ -0,0 +1,565 @@
// ====================================================================
// Class: XAdmin.GameConfigSet
// Parent: XAdmin.xAdminConfigBase
//
// This class is responsible for handling changes to a Game default
// Behavior like Map List,Mutators and Ini Settings.
// ====================================================================
class GameConfigSet extends Object;
var LevelInfo Level; // Need access to Level function
var protected class<GameInfo> GameClass; // Which game class is being edited
var protected int GameIndex; // Index of GameClass
var protected PlayInfo Settings; // Game Setting Defaults
var int CurrentMapList; // Index of maplist we're editing
var protected array<int> UsedMutators; // List of Mutators in use
var protected array<int> UsedMaps; // Index of maps within active maplist
// Maintaining Global Lists
var protected string AllMapsPrefix; // Which map prefix is currently loaded
var protected array<string> AllMapLists; // List of all maplists for the specified gametype
var protected array<string> AllMaps; // List of all Maps for the specified gametype.
var protected array<string> AllMutators; // List of all available mutators
var protected array< class<GameInfo> > AllGameTypes;
var string NextMutators; // What mutators were set during this session
var protected bool bEdit; // We are currently editing something
function bool StartEdit(optional string GameType)
{
if (Level == None || bEdit)
return false;
// Load all Game Types, unless already loaded
if (AllGameTypes.Length == 0)
LoadGameTypes();
// Load All Mutators (Unless already loaded)
if (AllMutators.Length == 0)
LoadAllMutators();
// If no GameType Specified, use currently loaded one.
if (GameType == "")
GameType = String(Level.Game.Class);
// When editing allow for many ways to find the good game class
// Try with Acronym, Class, Alternate class, etc
GameClass = FindGameType(GameType);
log("GameClass is"@GameClass);
if (GameClass == None)
return false;
LoadAllMaps();
GameIndex = Level.Game.MaplistHandler.GetGameIndex(string(GameClass));
CurrentMapList = GetActiveList();
AllMapLists = GetLists();
// Load Game Setting
LoadSettings(GameClass);
// Fill in Used Mutators
SetUsedMutators();
NextMutators = "";
bEdit = true;
return true;
}
function bool EndEdit(bool bSave)
{
local int i;
if (Level == None || !bEdit)
return false;
// Save all data where it belongs
if (bSave)
{
// Log("GCS.EndEdit is now Saving All the Data");
// Commit to PlayInfo
Settings.SaveSettings();
NextMutators = "";
if (UsedMutators.Length > 0)
{
NextMutators = AllMutators[UsedMutators[0]];
for (i=1; i<UsedMutators.Length; i++)
NextMutators = NextMutators$","$AllMutators[UsedMutators[i]];
}
// Log("CGS.NextMutators="@NextMutators);
Level.Game.MaplistHandler.SaveGame(GameIndex);
}
else Level.Game.MaplistHandler.ResetGame(GameIndex);
bEdit = false;
return true;
}
function bool CanEdit()
{
return !bEdit;
}
// Settings Functions
function string GetParam(int idx)
{
if (idx < 0 || idx >= Settings.Settings.Length)
return "";
return Settings.Settings[idx].Value;
}
function string GetNamedParam(string Parameter)
{
local int i;
local string SettingName;
for (i = 0; i < Settings.Settings.Length; i++)
{
SettingName = Settings.Settings[i].SettingName;
if (SettingName ~= Parameter || Right(SettingName, Len(Parameter) + 1) ~= ("."$Parameter))
return Settings.Settings[i].Value;
}
return "";
}
function array<string> GetMaskedParams(string ParamMask)
{
local array<string> FoundParams;
local array<string> FoundMasks;
local string SettingName, ShortName;
local int i, j, p;
Split(ParamMask, " ", FoundMasks);
if (FoundMasks.Length > 0)
{
for (i = 0; i<Settings.Settings.Length; i++)
{
SettingName = Settings.Settings[i].SettingName;
ShortName = SettingName;
j = Instr(ShortName, ".");
while (j != -1)
{
ShortName = Mid(ShortName, p+1);
j = Instr(ShortName, ".");
}
for (j = 0; j<FoundMasks.Length; j++)
{
if (MaskedCompare(ShortName, FoundMasks[j]) || MaskedCompare(SettingName, FoundMasks[j]))
{
FoundParams[FoundParams.Length] = SettingName;
FoundParams[FoundParams.Length] = Settings.Settings[i].Value;
break;
}
}
}
}
return FoundParams;
}
function bool SetParam(int idx, string Value)
{
if (idx < 0 || idx >= Settings.Settings.Length)
return false;
return Settings.StoreSetting(idx, Value);
}
// Settings Commands Processing
function bool SetNamedParam(string Parameter, string Value)
{
local int i;
local string SettingName;
for (i = 0; i < Settings.Settings.Length; i++)
{
SettingName = Settings.Settings[i].SettingName;
if (SettingName ~= Parameter || Right(SettingName, Len(Parameter) + 1) ~= ("."$Parameter))
return Settings.StoreSetting(i, Value);
}
// Parameter not found
return false;
}
// MapList Functions
function array<string> GetLists()
{
local array<string> Names;
Names = Level.Game.MaplistHandler.GetMapListNames(GameIndex);
return Names;
}
function int GetActiveList()
{
return Level.Game.MaplistHandler.GetActiveList(GameIndex);
}
//function bool SetActiveList(int Index)
//{
// if (Index < 0 || Index > AllMapLists.Length || !bEdit)
// return false;
//
// CurrentMapList = Index;
// return true;
//}
function array<string> GetMaps()
{
return Level.Game.MaplistHandler.GetMapList(GameIndex, CurrentMapList);
}
function array<string> AddMaps(string MapMask)
{
local array<string> FoundMasks, AddedMaps, CurrentMaps;
local int i, j, k;
local bool bFound;
Split(MapMask, " ",FoundMasks);
if (FoundMasks.Length > 0)
{
CurrentMaps = GetMaps();
for (i = 0; i<AllMaps.Length; i++)
{
for (j = 0; j<FoundMasks.Length; j++)
{
if (MaskedCompare(AllMaps[i], FoundMasks[j]))
{
// Found a matching map, see if its already in the Used Maps list
bFound = false;
for (k = 0; k<CurrentMaps.Length; k++)
{
if (CurrentMaps[k] == AllMaps[i])
{
bFound = true;
break;
}
}
if (!bFound)
{
Level.Game.MaplistHandler.AddMap(GameIndex, CurrentMapList, AllMaps[i]);
AddedMaps[AddedMaps.Length] = AllMaps[i];
break;
}
}
}
}
}
return AddedMaps;
}
function array<string> RemoveMaps(string MapMask)
{
local array<string> FoundMasks, DelMaps, CurrentMaps;
local int i, j;
Split(MapMask, " ", FoundMasks);
if (FoundMasks.Length > 0)
{
CurrentMaps = GetMaps();
for (i=0; i<CurrentMaps.Length; i++)
{
for (j=0; j<FoundMasks.Length; j++)
{
if (MaskedCompare(CurrentMaps[i], FoundMasks[j]))
{
DelMaps[DelMaps.Length] = CurrentMaps[i];
Level.Game.MaplistHandler.RemoveMap(GameIndex, CurrentMapList, CurrentMaps[i]);
i--;
break;
}
}
}
}
return DelMaps;
}
function array<string> FindMaps(string MapMask)
{
local array<string> FoundMasks, FoundMaps, CurrentMaps;
local int i, j, k;
local bool bFound;
Split(MapMask, " ", FoundMasks);
if (FoundMasks.Length > 0)
{
CurrentMaps = GetMaps();
for (i = 0; i<AllMaps.Length; i++)
{
for (j = 0; j<FoundMasks.Length; j++)
{
if (MaskedCompare(AllMaps[i], FoundMasks[j]))
{
// Found a matching map, see if its already in the Used Maps list
bFound = false;
for (k = 0; k<CurrentMaps.Length; k++)
{
if (CurrentMaps[k] ~= AllMaps[i])
{
// Log("Found the map");
bFound = true;
break;
}
}
if (bFound)
FoundMaps[FoundMaps.Length] = "+"$AllMaps[i];
else
FoundMaps[FoundMaps.Length] = AllMaps[i];
break;
}
}
}
}
return FoundMaps;
}
// Mutator list functions
function array<string> GetUsedMutators()
{
local array<string> Strings;
local int i;
for (i = 0; i<UsedMutators.Length; i++)
Strings[Strings.Length] = AllMutators[UsedMutators[i]];
return Strings;
}
function array<string> GetUnusedMutators()
{
local array<string> Strings;
local int i;
Strings.Length = AllMutators.Length;
for (i = 0; i<AllMutators.Length; i++)
Strings[i] = AllMutators[i];
// Tag all used mutators
for (i = 0; i<UsedMutators.Length; i++)
Strings[UsedMutators[i]] = "";
for (i = 0; i<Strings.Length; i++)
{
if (Strings[i] == "")
{
Strings.Remove(i, 1);
i--;
}
}
return Strings;
}
function bool AddMutator(string MutatorName)
{
local int i, j;
local string Str;
// First make sure it isnt in the list
for (i = 0; i<AllMutators.Length; i++)
{
Str = AllMutators[i];
if (Str ~= MutatorName || Right(Str, Len(MutatorName) + 1) ~= ("."$MutatorName))
{
for (j=0; j<UsedMutators.Length; j++)
if (UsedMutators[j] == i)
return false;
UsedMutators[UsedMutators.Length] = i;
return true;
}
}
return false;
}
function bool DelMutator(string MutatorName)
{
local int i;
local string Str;
// First make sure it isnt in the list
for (i = 0; i<UsedMutators.Length; i++)
{
Str = AllMutators[UsedMutators[i]];
if (Str ~= MutatorName || Right(Str, Len(MutatorName) + 1) ~= ("."$MutatorName))
{
UsedMutators.Remove(i, 1);
return true;
}
}
return false;
}
////////////////////////////////
// Public Information
////////////////////////////////
function string GetEditedClass()
{
if (GameClass != None)
return String(GameClass);
return "";
}
function string GetGameAcronym()
{
if (GameClass != None)
return GameClass.default.Acronym;
return "";
}
////////////////////////////////
// Protected Helping functions
////////////////////////////////
protected function LoadGameTypes()
{
local class<GameInfo> TempClass;
local String NextGame;
local int i;
// Compile a list of all gametypes.
i = 0;
NextGame = Level.GetNextInt("Engine.GameInfo", 0);
while (NextGame != "")
{
TempClass = class<GameInfo>(DynamicLoadObject(NextGame, class'Class'));
if (TempClass != None)
AllGameTypes[AllGameTypes.Length] = TempClass;
NextGame = Level.GetNextInt("Engine.GameInfo", ++i);
}
}
protected function class<GameInfo> FindGameType(string GameType)
{
local class<GameInfo> TempClass;
local int i;
TempClass = None;
for (i=0; i<AllGameTypes.Length; i++)
{
TempClass = AllGameTypes[i];
if (GameType ~= string(TempClass)) break;
if (GameType ~= TempClass.default.Acronym) break;
if (GameType ~= TempClass.default.DecoTextName) break;
if (Right(string(TempClass), Len(GameType)+1) ~= ("."$GameType)) break;
if (Right(TempClass.default.DecoTextName, Len(GameType)+1) ~= ("."$GameType)) break;
}
return TempClass;
}
protected function LoadAllMutators()
{
local string NextMutator, NextDesc;
local int Cnt;
Level.GetNextIntDesc("Engine.Mutator", 0, NextMutator, NextDesc);
Cnt = 0;
AllMutators.Length = 0;
while(NextMutator != "")
{
AllMutators[AllMutators.Length] = NextMutator;
Cnt++;
Level.GetNextIntDesc("Engine.Mutator", Cnt, NextMutator, NextDesc);
}
}
protected function SetUsedMutators()
{
local Mutator M;
local int i;
for (M = Level.Game.BaseMutator.NextMutator; M != None; M = M.NextMutator)
{
if (M.bUserAdded)
{
for (i=0; i<AllMutators.Length; i++)
if (string(M.Class) ~= AllMutators[i])
break;
if (i == AllMutators.Length)
{
// Since this mutator had no .int entry, but it was added on the command line
// lets just add it to the list.
AllMutators[AllMutators.Length] = string(M.Class);
log("Unknown Mutator in use: "@String(M.Class));
}
UsedMutators[UsedMutators.Length] = i;
}
}
}
// Always reload settings at StartEdit()
protected function string LoadSettings(class<GameInfo> GameClass)
{
if (Settings == None)
Settings = new(None) class'PlayInfo';
Settings.Clear();
GameClass.static.FillPlayInfo(Settings);
return string(GameClass);
}
// TODO: Have a "native array<string> LoadAllMapNames(string MapPrefix)" somewhere ?
protected function LoadAllMaps(optional bool bForceLoad)
{
local string MapPrefix;
if (GameClass == None)
return;
MapPrefix = GameClass.Default.MapPrefix;
if(MapPrefix != "" && (MapPrefix != AllMapsPrefix || bForceLoad))
{
GameClass.static.LoadMapList(MapPrefix, AllMaps);
AllMapsPrefix = MapPrefix;
}
}
////////////////////////////////////////////////////////////
// TODO: Find Centralized place for the following functions
////////////////////////////////////////////////////////////
// Mask can be *|*Name|Name*|*Name*|Name
protected function bool MaskedCompare(string SettingName, string Mask)
{
local bool bMaskLeft, bMaskRight;
local int MaskLen;
if (Mask == "*" || Mask == "**")
return true;
MaskLen = Len(Mask);
bMaskLeft = Left(Mask, 1) == "*";
bMaskRight = Right(Mask, 1) == "*";
if (bMaskLeft && bMaskRight)
return Instr(Caps(SettingName), Mid(Caps(Mask), 1, MaskLen-2)) >= 0;
if (bMaskLeft)
return Left(SettingName, MaskLen -1) ~= Left(Mask, MaskLen - 1);
if (bMaskRight)
return Right(SettingName, MaskLen -1) ~= Right(Mask, MaskLen - 1);
return SettingName ~= Mask;
}
defaultproperties
{
}

View file

@ -0,0 +1,15 @@
<html>
<head><title>Index of /kf_sources/XAdmin/Classes/</title></head>
<body>
<h1>Index of /kf_sources/XAdmin/Classes/</h1><hr><pre><a href="../">../</a>
<a href="AccessControlIni.uc">AccessControlIni.uc</a> 06-Oct-2019 10:27 6325
<a href="AdminIni.uc">AdminIni.uc</a> 06-Oct-2019 10:27 16797
<a href="GameConfigSet.uc">GameConfigSet.uc</a> 06-Oct-2019 10:27 13579
<a href="xAdminCommandlet.uc">xAdminCommandlet.uc</a> 06-Oct-2019 10:27 543
<a href="xAdminConfigIni.uc">xAdminConfigIni.uc</a> 06-Oct-2019 10:27 4427
<a href="xExtraPrivs.uc">xExtraPrivs.uc</a> 06-Oct-2019 10:27 674
<a href="xGamePrivs.uc">xGamePrivs.uc</a> 06-Oct-2019 10:27 708
<a href="xKickPrivs.uc">xKickPrivs.uc</a> 06-Oct-2019 10:27 520
<a href="xUserGroupPrivs.uc">xUserGroupPrivs.uc</a> 06-Oct-2019 10:27 727
</pre><hr></body>
</html>

View file

@ -0,0 +1,23 @@
// ====================================================================
// Class: XAdmin.DBTestCommandlet
// Parent: Core.Commandlet
//
// <Enter a description here>
// ====================================================================
class xAdminCommandlet extends Commandlet;
var AccessControlIni m;
event int Main( string Parms )
{
m = new(None) class'AccessControlIni';
// m.Groups.Add(m.Groups.CreateGroup("Kickers", "K", 10));
// m.AConfig.Save(m.Users, m.Groups);
return 0;
}
defaultproperties
{
}

View file

@ -0,0 +1,151 @@
// ====================================================================
// Class: XAdmin.xAdminConfigIni
// Parent: Engine.xAdminConfigBase
//
// Retains the list of Admin Users and Groups and keeps them into an
// Ini file.
// ====================================================================
class xAdminConfigIni extends xAdminConfigBase
Config(xAdmin)
ParseConfig;
struct AdminUser
{
var string AdminName;
var string Password;
var string Privileges;
var array<string> Groups; // A User can be part of multiple groups
var array<string> ManagedGroups;
};
struct AdminGroup
{
var string GroupName;
var string Privileges;
var byte GameSecLevel;
};
var config array<AdminUser> AdminUsers;
var config array<AdminGroup> AdminGroups;
// TODO: Define when it should return false
static function bool Load(xAdminUserList Users, xAdminGroupList Groups, bool bDontAddDefaultAdmin)
{
local int i;
local xAdminUser NewUser;
local xAdminGroup NewGroup;
local AdminUser User;
local AdminGroup Group;
local bool bDirty;
Log("Loading Admins & Groups");
// Start with converting groups
for (i = 0; i<Default.AdminGroups.Length; i++)
{
// Make sure a group wasnt already added with a given name (manual tampering of ini file)
Group = Default.AdminGroups[i];
if (Groups.FindByName(Group.GroupName) == None)
{
NewGroup = Groups.CreateGroup(Group.GroupName, Group.Privileges, Group.GameSecLevel);
Groups.Add(NewGroup);
}
}
// If there are No Groups, Create a default Group (Admin)
if (Groups.Count() == 0 || Groups.FindByName("Admin") == None)
{
Log("Creating Admin Group");
Groups.Add(Groups.CreateGroup("Admin", "", 255));
Groups.Add(Groups.CreateGroup("MatchSetup", "Xm", 240));
bDirty = true;
}
// Then, convert each User
for (i = 0; i<Default.AdminUsers.Length; i++)
{
// Make sure that a user with that name wasnt already added
User = Default.AdminUsers[i];
if (Users.FindByName(User.AdminName) == None)
{
NewUser = Users.Create(User.AdminName, User.Password, User.Privileges);
if (NewUser != None)
{
NewUser.AddGroupsByName(Groups, User.Groups);
NewUser.AddManagedGroupsByName(Groups, User.ManagedGroups);
Users.Add(NewUser);
}
}
}
// if there are no Users, Create a default User (Admin)
if (Users.Count() == 0 && !bDontAddDefaultAdmin)
{
NewUser = Users.Create("Admin", "Admin", "");
NewUser.AddGroup(Groups.FindByName("Admin"));
Users.Add(NewUser);
bDirty = true;
}
if (bDirty)
Save(Users, Groups);
return true;
}
static function bool Save(xAdminUserList Users, xAdminGroupList Groups)
{
local int i, j, GrpLen, UserLen;
local xAdminUser User;
local xAdminGroup Group;
// Fix the sizes of the current structure lists
Default.AdminUsers.Length = Users.Count();
Default.AdminGroups.Length = Groups.Count();
// Rebuild the list of AdminGroups based on current internal list
GrpLen = 0;
for (i=0; i<Groups.Count(); i++)
{
Group = Groups.Get(i);
if (Group.GroupName != "URL::Admin")
{
Default.AdminGroups[GrpLen].GroupName = Group.GroupName;
Default.AdminGroups[GrpLen].Privileges = Group.Privileges;
Default.AdminGroups[GrpLen].GameSecLevel = Group.GameSecLevel;
GrpLen++;
}
}
Default.AdminGroups.Length = GrpLen;
// Rebuild the list of AdminUsers based on current internal list
UserLen = 0;
for (i=0; i<Users.Count(); i++)
{
User = Users.Get(i);
if (User.GetGroup("URL::Admin") == None)
{
Default.AdminUsers[UserLen].AdminName = User.UserName;
Default.AdminUsers[UserLen].Password = User.Password;
Default.AdminUsers[UserLen].Privileges = User.Privileges;
if (User.Groups != None && User.Groups.Count() > 0)
{
Default.AdminUsers[UserLen].Groups.Length = User.Groups.Count();
for (j = 0; j<User.Groups.Count(); j++)
Default.AdminUsers[UserLen].Groups[j] = User.Groups.Get(j).GroupName;
}
if (User.ManagedGroups != None && User.ManagedGroups.Count() > 0)
{
Default.AdminUsers[UserLen].ManagedGroups.Length = User.ManagedGroups.Count();
for (j = 0; j<User.ManagedGroups.Count(); j++)
Default.AdminUsers[UserLen].ManagedGroups[j] = User.ManagedGroups.Get(j).GroupName;
}
UserLen++;
}
}
Default.AdminUsers.Length = UserLen;
StaticSaveConfig();
return true;
}

View file

@ -0,0 +1,23 @@
// ====================================================================
// Class: XAdmin.xExtraPrivs
// Parent: Engine.xPrivilegeBase
//
// <Enter a description here>
// ====================================================================
class xExtraPrivs extends xPrivilegeBase;
defaultproperties
{
LoadMsg="Extra Privileges Loaded"
MainPrivs="X"
Tags(0)="Miscellaneous"
SubPrivs="Xb|Xc|Xp|Xs|Xi|Xv|Xm"
Tags(1)="Set Bot Skill"
Tags(2)="Use Console"
Tags(3)="Player List"
Tags(4)="Change Webadmin Skin"
Tags(5)="Manage Access Policies"
Tags(6)="Voice Chat Management"
Tags(7)="Match Setup"
}

View file

@ -0,0 +1,24 @@
// ====================================================================
// Class: XAdmin.xGamePrivs
// Parent: Engine.xPrivilegeBase
//
// <Enter a description here>
// ====================================================================
class xGamePrivs extends xPrivilegeBase;
defaultproperties
{
LoadMsg="Maps & Game Privileges Loaded"
MainPrivs="M"
Tags(0)="Maps/Game Settings"
SubPrivs="Mr|Mt|Mm|Ml|Ms|Mu|Mb|Ma"
Tags(1)="Restart Map"
Tags(2)="Change Game Type"
Tags(3)="Change Map"
Tags(4)="Manages Map Rotation"
Tags(5)="Game Settings"
Tags(6)="Select Mutators"
Tags(7)="Add/Remove Bots"
Tags(8)="Game Status"
}

View file

@ -0,0 +1,19 @@
// ====================================================================
// Class: XAdmin.xKickPrivs
// Parent: Engine.xPrivilegeBase
//
// <Enter a description here>
// ====================================================================
class xKickPrivs extends xPrivilegeBase;
defaultproperties
{
LoadMsg="Kick and Ban Privileges Loaded"
MainPrivs="K"
SubPrivs="Kp|Kb|Ko"
Tags(0)="Kick/Ban"
Tags(1)="Kick Players"
Tags(2)="Ban Players"
Tags(3)="Kick Bots"
}

View file

@ -0,0 +1,25 @@
// ====================================================================
// Class: XAdmin.xUserGroupPrivs
// Parent: Engine.xPrivilegeBase
//
// <Enter a description here>
// ====================================================================
class xUserGroupPrivs extends xPrivilegeBase;
defaultproperties
{
LoadMsg="Admins & Groups Management Loaded"
MainPrivs="A|G"
SubPrivs="Al|Aa|Ae|Ag|Am|Gl|Ga|Ge"
Tags(0)="Users"
Tags(1)="List Admins"
Tags(2)="Add/Remove Admins"
Tags(3)="Edit Admins"
Tags(4)="Assign Groups"
Tags(5)="Make Managers"
Tags(6)="Groups"
Tags(7)="List Groups"
Tags(8)="Add/Remove Groups"
Tags(9)="Edit Groups"
}