rott/kf_sources/XAdmin/Classes/AdminIni.uc
2026-07-14 20:27:09 +07:00

646 lines
16 KiB
Ucode

// ====================================================================
// 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"
}