462 lines
12 KiB
Ucode
462 lines
12 KiB
Ucode
class ChaChaRESTStats expands WebApplication;
|
|
|
|
var() class<UTServerAdminSpectator> SpectatorType;
|
|
var UTServerAdminSpectator Spectator;
|
|
|
|
|
|
var ListItem IncludeMutators;
|
|
var ListItem ExcludeMutators;
|
|
|
|
/* Usage:
|
|
|
|
[UWeb.WebServer]
|
|
Applications[X]=ChaChaRESTStats.ChaChaRESTStats
|
|
ApplicationPaths[X]=/api/v1
|
|
bEnabled=True
|
|
|
|
http://server.ip.address/api/v1/current_game
|
|
|
|
*/
|
|
|
|
event Init()
|
|
{
|
|
Super.Init();
|
|
|
|
if (SpectatorType != None)
|
|
Spectator = Level.Spawn(SpectatorType);
|
|
else
|
|
Spectator = Level.Spawn(class'UTServerAdminSpectator');
|
|
|
|
// won't change as long as the server is up
|
|
LoadMutators();
|
|
}
|
|
|
|
function LoadMutators()
|
|
{
|
|
local int NumMutatorClasses;
|
|
local string NextMutator, NextDesc;
|
|
local listitem TempItem;
|
|
local Mutator M;
|
|
local int k;
|
|
|
|
ExcludeMutators = None;
|
|
|
|
Level.GetNextIntDesc("Engine.Mutator", 0, NextMutator, NextDesc);
|
|
while( (NextMutator != "") && (NumMutatorClasses < 1024) )
|
|
{
|
|
TempItem = new(None) class'ListItem';
|
|
|
|
k = InStr(NextDesc, ",");
|
|
if (k == -1)
|
|
TempItem.Tag = NextDesc;
|
|
else
|
|
TempItem.Tag = Left(NextDesc, k);
|
|
|
|
TempItem.Data = NextMutator;
|
|
|
|
if (ExcludeMutators == None)
|
|
ExcludeMutators = TempItem;
|
|
else
|
|
ExcludeMutators.AddSortedElement(ExcludeMutators, TempItem);
|
|
NumMutatorClasses++;
|
|
Level.GetNextIntDesc("Engine.Mutator", NumMutatorClasses, NextMutator, NextDesc);
|
|
}
|
|
|
|
IncludeMutators = None;
|
|
|
|
for ( M=Level.Game.BaseMutator.NextMutator ; M!=None ; M=M.NextMutator )
|
|
{
|
|
TempItem = ExcludeMutators.DeleteElement(ExcludeMutators, String(M.Class));
|
|
|
|
if (TempItem != None)
|
|
{
|
|
if (IncludeMutators == None)
|
|
IncludeMutators = TempItem;
|
|
else
|
|
IncludeMutators.AddElement(TempItem);
|
|
}
|
|
else
|
|
log("Unknown Mutator in use: "$String(M.Class));
|
|
}
|
|
}
|
|
|
|
event Query(WebRequest Request, WebResponse Response)
|
|
{
|
|
local string tmp;
|
|
//local int i;
|
|
|
|
/* Kept in case auth needed
|
|
if(Request.Username != "test" || Request.Password != "test")
|
|
{
|
|
Response.FailAuthentication("HelloWeb");
|
|
return;
|
|
}
|
|
*/
|
|
Response.SendStandardHeaders("application/json",False);
|
|
Response.bSentText=True; //avoid header to be re-sent
|
|
switch(Request.URI)
|
|
{
|
|
case "/map_list":
|
|
Response.SendText(EncloseJSON(QueryMapList()));
|
|
break;
|
|
case "/current_all":
|
|
tmp=QueryCurrentGame();
|
|
tmp$=",";
|
|
tmp$=QueryCurrentPlayers();
|
|
Response.SendText(EncloseJSON(tmp));
|
|
break;
|
|
case "/current_game":
|
|
Response.SendText(EncloseJSON(QueryCurrentGame()));
|
|
break;
|
|
case "/current_players":
|
|
Response.SendText(EncloseJSON(QueryCurrentPlayers()));
|
|
break;
|
|
case "/default_all":
|
|
tmp=QueryDefaultsSettings();
|
|
tmp$=",";
|
|
tmp$=QueryDefaultsRules();
|
|
tmp$=",";
|
|
tmp$=QueryDefaultsServer();
|
|
Response.SendText(EncloseJSON(tmp));
|
|
break;
|
|
case "/defaults_settings":
|
|
Response.SendText(EncloseJSON(QueryDefaultsSettings()));
|
|
break;
|
|
case "/defaults_rules":
|
|
Response.SendText(EncloseJSON(QueryDefaultsRules()));
|
|
break;
|
|
case "/defaults_server":
|
|
Response.SendText(EncloseJSON(QueryDefaultsServer()));
|
|
break;
|
|
default:
|
|
Response.SendText("ERROR: Page not found or enabled.");
|
|
break;
|
|
}
|
|
}
|
|
|
|
function string EncloseJSON(String _input)
|
|
{
|
|
return "{"$_input$"}";
|
|
}
|
|
|
|
function string RenderJSONBool(string KeyName, bool KeyValue)
|
|
{
|
|
if( KeyValue )
|
|
{
|
|
return "\""$KeyName$"\":\"true\"";
|
|
}
|
|
else
|
|
{
|
|
return "\""$KeyName$"\":\"false\"";
|
|
}
|
|
}
|
|
|
|
function string RenderJSONBoolString(string KeyName, string KeyValue)
|
|
{
|
|
return RenderJSONBool(KeyName,KeyValue ~= "true");
|
|
}
|
|
|
|
function string QueryDefaultsServer()
|
|
{
|
|
local String tmp;
|
|
|
|
tmp$="\"ServerName\":\""$class'Engine.GameReplicationInfo'.default.ServerName$"\",";
|
|
tmp$="\"AdminName\":\""$class'Engine.GameReplicationInfo'.default.AdminName$"\",";
|
|
tmp$="\"AdminEmail\":\""$class'Engine.GameReplicationInfo'.default.AdminEmail$"\",";
|
|
tmp$="\"MOTDLine1\":\""$class'Engine.GameReplicationInfo'.default.MOTDLine1$"\",";
|
|
tmp$="\"MOTDLine2\":\""$class'Engine.GameReplicationInfo'.default.MOTDLine2$"\",";
|
|
tmp$="\"MOTDLine3\":\""$class'Engine.GameReplicationInfo'.default.MOTDLine3$"\",";
|
|
tmp$="\"MOTDLine4\":\""$class'Engine.GameReplicationInfo'.default.MOTDLine4$"\",";
|
|
tmp$=RenderJSONBool("bWorldLog",Level.Game.Default.bWorldLog);
|
|
return tmp;
|
|
}
|
|
|
|
function string QueryDefaultsRules()
|
|
{
|
|
|
|
local float FriendlyFireScale;
|
|
local class<GameInfo> GameClass;
|
|
local String tmp;
|
|
|
|
GameClass = Level.Game.Class;
|
|
|
|
tmp$="\"MaxPlayers\":"$class<DeathMatchPlus>(GameClass).Default.MaxPlayers$",";
|
|
tmp$="\"MaxSpectators\":"$class<DeathMatchPlus>(GameClass).Default.MaxSpectators$",";
|
|
//tmp$="\"bMultiWeaponStay\":"$class<DeathMatchPlus>(GameClass).Default.bMultiWeaponStay$",";
|
|
tmp$=RenderJSONBool("bMultiWeaponStay",class<DeathMatchPlus>(GameClass).Default.bMultiWeaponStay)$",";
|
|
//tmp$="\"bTournament\":"$class<DeathMatchPlus>(GameClass).Default.bTournament;
|
|
tmp$=RenderJSONBool("bTournament",class<DeathMatchPlus>(GameClass).Default.bTournament);
|
|
|
|
if( class<TeamGamePlus>(GameClass) != None )
|
|
{
|
|
//tmp$=",\"bPlayersBalanceTeams\":"$class<TeamGamePlus>(GameClass).Default.bPlayersBalanceTeams;
|
|
tmp$=","$RenderJSONBool("bPlayersBalanceTeams",class<TeamGamePlus>(GameClass).Default.bPlayersBalanceTeams);
|
|
}
|
|
|
|
if( class<LastManStanding>(GameClass) == None )
|
|
{
|
|
//tmp$=",\"bForceRespawn\":"$class<DeathMatchPlus>(GameClass).Default.bForceRespawn;
|
|
tmp$=","$RenderJSONBool("bForceRespawn",class<DeathMatchPlus>(GameClass).Default.bForceRespawn);
|
|
}
|
|
|
|
if (class<DeathMatchPlus>(GameClass) != None && class<Assault>(GameClass) == None)
|
|
{
|
|
if (class<TeamGamePlus>(GameClass) != None)
|
|
{
|
|
tmp$=",\"GoalTeamScore\":"$class<TeamGamePlus>(GameClass).Default.GoalTeamScore;
|
|
}
|
|
else
|
|
{
|
|
tmp$=",\"FragLimit\":"$class<DeathMatchPlus>(GameClass).Default.FragLimit;
|
|
}
|
|
|
|
if(class<LastManStanding>(GameClass) == None)
|
|
{
|
|
tmp$=",\"TimeLimit\":"$class<DeathMatchPlus>(GameClass).Default.TimeLimit;
|
|
}
|
|
}
|
|
|
|
if( class<TeamGamePlus>(GameClass) != None &&
|
|
!ClassIsChildOf( GameClass, class'CTFGame' ) &&
|
|
!ClassIsChildOf( GameClass, class'Assault' ) )
|
|
{
|
|
tmp$=",\"MaxTeams\":"$class<TeamGamePlus>(GameClass).Default.MaxTeams;
|
|
}
|
|
|
|
if (class<TeamGamePlus>(GameClass) != None)
|
|
{
|
|
FriendlyFireScale = class<TeamGamePlus>(GameClass).Default.FriendlyFireScale * 100;
|
|
tmp$=",\"FriendlyFireScale\":"$FriendlyFireScale;
|
|
}
|
|
|
|
return tmp;
|
|
}
|
|
|
|
function string QueryDefaultsSettings()
|
|
{
|
|
local class<GameInfo> GameClass;
|
|
local int GameStyle;
|
|
local float GameSpeed, AirControl;
|
|
local String tmp;
|
|
|
|
GameClass = Level.Game.Class;
|
|
|
|
if (class<DeathMatchPlus>(GameClass).Default.bMegaSpeed == true)
|
|
GameStyle=1;
|
|
if (class<DeathMatchPlus>(GameClass).Default.bHardCoreMode == true)
|
|
GameStyle+=1;
|
|
|
|
switch (GameStyle) {
|
|
case 0:
|
|
tmp$="\"GameStyle\":\"Normal\",";
|
|
break;
|
|
case 1:
|
|
tmp$="\"GameStyle\":\"HardCore\",";
|
|
break;
|
|
case 2:
|
|
tmp$="\"GameStyle\":\"Turbo\",";
|
|
break;
|
|
default:
|
|
tmp$="\"GameStyle\":\"Normal\",";
|
|
break;
|
|
}
|
|
|
|
GameSpeed = class<DeathMatchPlus>(GameClass).Default.GameSpeed * 100.0;
|
|
tmp$="\"GameSpeed\":"$GameSpeed$",";
|
|
|
|
AirControl = class<DeathMatchPlus>(GameClass).Default.AirControl * 100.0;
|
|
tmp$="\"AirControl\":"$AirControl$",";
|
|
|
|
//tmp$="\"UseTranslocator\":"$class<DeathMatchPlus>(GameClass).Default.bUseTranslocator;
|
|
tmp$=RenderJSONBool("bUseTranslocator",class<DeathMatchPlus>(GameClass).Default.bUseTranslocator);
|
|
|
|
return tmp;
|
|
}
|
|
|
|
function string QueryMapList()
|
|
{
|
|
local string tmp;
|
|
local ListItem ExcludeMaps, IncludeMaps;
|
|
ReloadExcludeMaps(ExcludeMaps, String(Level.Game.Class));
|
|
ReloadIncludeMaps(ExcludeMaps, IncludeMaps, String(Level.Game.Class));
|
|
tmp$=RenderDataList("Maplist",IncludeMaps);
|
|
return tmp;
|
|
}
|
|
|
|
function string QueryCurrentGame()
|
|
{
|
|
local string tmp,LevelFullName,LevelName;
|
|
local int k;
|
|
|
|
tmp$="\"GameName\":\""$Level.Game.GameReplicationInfo.GameName$"\",";
|
|
tmp$="\"GameClass\":\""$String(Level.Game.Class)$"\",";
|
|
|
|
tmp$="\"LevelTitle\":\""$Level.Title$"\",";
|
|
|
|
LevelFullName=String(Level);
|
|
k = InStr(LevelFullName, ".");
|
|
LevelName = Left(LevelFullName, k);
|
|
tmp$="\"Level\":\""$LevelName$"\",";
|
|
|
|
if (Level.Game != None && DeathMatchPlus(Level.Game) != None &&
|
|
DeathMatchPlus(Level.Game).TimeLimit > 0.0)
|
|
{
|
|
tmp$="\"TimeLimit\":"$DeathMatchPlus(Level.Game).TimeLimit$",";
|
|
}
|
|
tmp$=RenderDataList("Mutators",IncludeMutators);
|
|
|
|
return tmp;
|
|
}
|
|
|
|
function string QueryCurrentPlayers()
|
|
{
|
|
local string tmp;
|
|
local Pawn P;
|
|
local string IP;
|
|
local bool bFirst;
|
|
|
|
tmp$="\"player_list\":[";
|
|
bFirst=True;
|
|
for (P=Level.PawnList; P!=None; P=P.NextPawn) {
|
|
if (P.bIsPlayer
|
|
&& !P.bDeleteMe
|
|
&& UTServerAdminSpectator(P) == None
|
|
&& P.PlayerReplicationInfo != None)
|
|
{
|
|
if(!bFirst)
|
|
tmp$=",";
|
|
bFirst=False;
|
|
tmp$="{";
|
|
tmp$="\"PlayerName\":\""$P.PlayerReplicationInfo.PlayerName$"\",";
|
|
tmp$="\"Ping\":"$max(P.PlayerReplicationInfo.Ping, 0)$",";
|
|
tmp$="\"Score\":"$P.PlayerReplicationInfo.Score$",";
|
|
if (P.PlayerReplicationInfo.bIsABot)
|
|
{
|
|
tmp$="\"bIsABot\":true,";
|
|
tmp$="\"bIsSpectator\":false,";
|
|
}
|
|
else
|
|
{
|
|
tmp$="\"bIsABot\":false,";
|
|
if (P.PlayerReplicationInfo.bIsSpectator)
|
|
{
|
|
tmp$="\"bIsSpectator\":true,";
|
|
}
|
|
else
|
|
{
|
|
tmp$="\"bIsSpectator\":false,";
|
|
}
|
|
}
|
|
IP = "";
|
|
if ( PlayerPawn(P) != None )
|
|
{
|
|
IP = PlayerPawn(P).GetPlayerNetworkAddress();
|
|
IP = class'InternetInfo'.static.StripPort(IP);
|
|
}
|
|
tmp$="\"IP\":\""$IP$"\"";
|
|
tmp$="}";
|
|
}
|
|
}
|
|
tmp$="]";
|
|
return tmp;
|
|
}
|
|
|
|
function string RenderDataList(String name,ListItem _list)
|
|
{
|
|
local string tmp;
|
|
local ListItem TempItem;
|
|
local bool bFirst;
|
|
tmp$="\""$name$"\":[";
|
|
bFirst = true;
|
|
for (TempItem = _list; TempItem != None; TempItem = TempItem.Next) {
|
|
if(!bFirst)
|
|
tmp$=",";
|
|
tmp$="\""$TempItem.Data$"\"";
|
|
bFirst=false;
|
|
}
|
|
tmp$="]";
|
|
return tmp;
|
|
}
|
|
|
|
function ReloadExcludeMaps(out ListItem ExcludeMaps, String GameType)
|
|
{
|
|
local class<GameInfo> GameClass;
|
|
local string FirstMap, NextMap, TestMap;
|
|
local ListItem TempItem;
|
|
|
|
GameClass = class<GameInfo>(DynamicLoadObject(GameType, class'Class'));
|
|
|
|
ExcludeMaps = None;
|
|
if(GameClass.Default.MapPrefix == "")
|
|
return;
|
|
FirstMap = Level.GetMapName(GameClass.Default.MapPrefix, "", 0);
|
|
NextMap = FirstMap;
|
|
while (!(FirstMap ~= TestMap) && FirstMap != "")
|
|
{
|
|
if(!(Left(NextMap, Len(NextMap) - 4) ~= (GameClass.Default.MapPrefix$"-tutorial")))
|
|
{
|
|
// Add the map.
|
|
TempItem = new(None) class'ListItem';
|
|
TempItem.Data = NextMap;
|
|
|
|
if(Right(NextMap, 4) ~= ".unr")
|
|
TempItem.Tag = Left(NextMap, Len(NextMap) - 4);
|
|
else
|
|
TempItem.Tag = NextMap;
|
|
|
|
if (ExcludeMaps == None)
|
|
ExcludeMaps = TempItem;
|
|
else
|
|
{
|
|
// Maplists returned by GetMapName get sorted in C++ as of the Unreal Tournament 469 patch
|
|
//ExcludeMaps.AddSortedElement(ExcludeMaps, TempItem);
|
|
ExcludeMaps.AddElement(TempItem);
|
|
}
|
|
}
|
|
|
|
NextMap = Level.GetMapName(GameClass.Default.MapPrefix, NextMap, 1);
|
|
TestMap = NextMap;
|
|
}
|
|
}
|
|
|
|
function ReloadIncludeMaps(out ListItem ExcludeMaps, out ListItem IncludeMaps, String GameType)
|
|
{
|
|
local class<GameInfo> GameClass;
|
|
local ListItem TempItem;
|
|
local int i;
|
|
|
|
GameClass = class<GameInfo>(DynamicLoadObject(GameType, class'Class'));
|
|
if(GameClass.Default.MapListType == None)
|
|
return;
|
|
if (GameClass != None)
|
|
{
|
|
for (i=0; i<ArrayCount(GameClass.Default.MapListType.Default.Maps) && GameClass.Default.MapListType.Default.Maps[i] != ""; i++)
|
|
{
|
|
// Add the map.
|
|
TempItem = ExcludeMaps.DeleteElement(ExcludeMaps, GameClass.Default.MapListType.Default.Maps[i]);
|
|
if (TempItem == None)
|
|
{
|
|
TempItem = new(None) class'ListItem';
|
|
TempItem.Data = GameClass.Default.MapListType.Default.Maps[i];
|
|
|
|
if(Right(TempItem.Data, 4) ~= ".unr")
|
|
TempItem.Tag = Left(TempItem.Data, Len(TempItem.Data) - 4);
|
|
else
|
|
TempItem.Tag = TempItem.Data;
|
|
}
|
|
else
|
|
{
|
|
if (IncludeMaps == None)
|
|
IncludeMaps = TempItem;
|
|
else
|
|
IncludeMaps.AddElement(TempItem);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
SpectatorType=Class'utserveradmin.UTServerAdminSpectator'
|
|
Spectator=None
|
|
} |