first commit
This commit is contained in:
parent
5acd55ace2
commit
edc5651395
61
README.md
61
README.md
|
@ -1,5 +1,60 @@
|
|||
# UT99-Mod-ChaChaRESTStats
|
||||
|
||||
A tiny mod to allow reading server stats with REST requests.
|
||||
|
||||
/!\ Require UT99 v451+, not compatible with v436, prefered 469+.
|
||||
A tiny mod to allow reading server stats with REST requests.
|
||||
|
||||
!!! Require UT99 v451+, not compatible with v436, prefered 469+.
|
||||
|
||||
# Installation
|
||||
## On Linux (crudini required)
|
||||
|
||||
./Run.sh <Your UT99 Installation Path> (<custom UnrealTounrnament.ini>)
|
||||
|
||||
## Manual installation
|
||||
|
||||
- Copy __ChaChaRESTStats.u__ file to your UT99 __System__ dir
|
||||
|
||||
- Edit UnrealTournament.ini and update / adapt [UWeb.WebServer] section:
|
||||
|
||||
|
||||
[UWeb.WebServer]
|
||||
Applications[0]=UTServerAdmin.UTServerAdmin
|
||||
ApplicationPaths[0]=/ServerAdmin
|
||||
Applications[1]=UTServerAdmin.UTImageServer
|
||||
ApplicationPaths[1]=/images
|
||||
Applications[2]=ChaChaRESTStats.ChaChaRESTStats
|
||||
ApplicationPaths[2]=/api/v1
|
||||
DefaultApplication=0
|
||||
bEnabled=True
|
||||
ListenPort=<YOUR_LISTEN_PORT>
|
||||
|
||||
## Available Resources:
|
||||
__GET__ <SERVER_PREFIX>/api/v1/map_list
|
||||
|
||||
__GET__ <SERVER_PREFIX>/api/v1/current_all
|
||||
|
||||
__GET__ <SERVER_PREFIX>/api/v1/current_game
|
||||
|
||||
__GET__ <SERVER_PREFIX>/api/v1/current_players
|
||||
|
||||
__GET__ <SERVER_PREFIX>/api/v1/default_all
|
||||
|
||||
__GET__ <SERVER_PREFIX>/api/v1/defaults_settings
|
||||
|
||||
__GET__ <SERVER_PREFIX>/api/v1/defaults_rules
|
||||
|
||||
__GET__ <SERVER_PREFIX>/api/v1/defaults_server
|
||||
|
||||
## Sample Output
|
||||
|
||||
__GET__ http://YOUR_SERVER_IP:YOUR_LISTEN_PORT/api/v1/map_list
|
||||
|
||||
{"Maplist":["CTF-Gauntlet.unr","CTF-Command.unr","CTF-Coret.unr","CTF-Dreary.unr","CTF-LavaGiant.unr","CTF-November.unr"]}
|
||||
|
||||
|
||||
__GET__ http://YOUR_SERVER_IP:YOUR_LISTEN_PORT/api/v1/current_all
|
||||
|
||||
{"GameName":"Capture the Flag","GameClass":"Botpack.CTFGame","LevelTitle":"Lava Giant","Level":"CTF-LavaGiant","Mutators":["Botpack.FatBoy"],"player_list":[{"PlayerName":"chacha","Ping":12,"Score":0.000000,"bIsABot":false,"bIsSpectator":true,"IP":"172.16.4.101"}]}
|
||||
|
||||
__GET__ http://YOUR_SERVER_IP:YOUR_LISTEN_PORT/api/v1/default_all
|
||||
|
||||
{"GameStyle":"HardCore","GameStyle":"Turbo","GameSpeed":100.000000,"AirControl":35.000000,"UseTranslocator":True,"MaxPlayers":16,"MaxSpectators":2,"bMultiWeaponStay":True,"bTournament":False,"bPlayersBalanceTeams":False,"bForceRespawn":False,"GoalTeamScore":3.000000,"TimeLimit":0,"FriendlyFireScale":0.000000,"ServerName":"Another UT Server","AdminName":"","AdminEmail":"","MOTDLine1":"","MOTDLine2":"","MOTDLine3":"","MOTDLine4":"","bWorldLog":True}
|
|
@ -0,0 +1,114 @@
|
|||
#!/bin/bash
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
OUTPUT_DIR="$2"
|
||||
DEFAULT_CFG_FILE=UnrealTournament.ini
|
||||
CFG_FILE="${3:-$DEFAULT_CFG_FILE}"
|
||||
|
||||
function add_iniKeyEx() {
|
||||
crudini --set $OUTPUT_DIR/System/$1 $2 __$3 $4
|
||||
# Warning: ugly hack with sed to allow multiple key instances + to remove space around '='
|
||||
sed -i "s/[[:space:]]*__$(echo $3 | sed -e 's/\([[\/.*]\|\]\)/\\&/g')[[:space:]]*=[[:space:]]*/$(echo $3 | sed -e 's/\([[\/.*]\|\]\)/\\&/g')=/g" $OUTPUT_DIR/System/$1
|
||||
}
|
||||
# !!Warning!! section is not considered
|
||||
function del_iniKeyEx() {
|
||||
sed -i "/[[:space:]]*$(echo $3 | sed -e 's/\([[\/.*]\|\]\)/\\&/g')[[:space:]]*=[[:space:]]*$(echo $4 | sed -e 's/\([[\/.*]\|\]\)/\\&/g')/d" $OUTPUT_DIR/System/$1
|
||||
}
|
||||
function add_iniKey() {
|
||||
add_iniKeyEx $CFG_FILE $1 $2 $3
|
||||
}
|
||||
# !!Warning!! section is not considered
|
||||
function del_iniKey() {
|
||||
del_iniKeyEx $CFG_FILE $1 $2 $3
|
||||
}
|
||||
function add_ServerPackage() {
|
||||
add_iniKey 'Engine.GameEngine' ServerPackages $1
|
||||
add_iniKey 'XC_Engine.XC_GameEngine' ServerPackages $1
|
||||
}
|
||||
function del_ServerPackage() {
|
||||
del_iniKey 'Engine.GameEngine' ServerPackages $1
|
||||
del_iniKey 'XC_Engine.XC_GameEngine' ServerPackages $1
|
||||
}
|
||||
function add_ServerActors() {
|
||||
add_iniKey 'Engine.GameEngine' ServerActors $1
|
||||
add_iniKey 'XC_Engine.XC_GameEngine' ServerActors $1
|
||||
}
|
||||
function del_ServerActors() {
|
||||
del_iniKey 'Engine.GameEngine' ServerActors $1
|
||||
del_iniKey 'XC_Engine.XC_GameEngine' ServerActors $1
|
||||
}
|
||||
|
||||
function install() {
|
||||
rsync -a $SCRIPT_DIR/System/ $OUTPUT_DIR/System/ --exclude '.git'
|
||||
echo install ok
|
||||
}
|
||||
|
||||
function enable() {
|
||||
add_iniKeyEx IpToCountry.ini UWeb.WebServer 'Applications[2]' ChaChaRESTStats.ChaChaRESTStats
|
||||
add_iniKeyEx IpToCountry.ini UWeb.WebServer 'ApplicationPaths[2]' '/api/v1'
|
||||
add_iniKeyEx IpToCountry.ini UWeb.WebServer 'bEnabled' True
|
||||
|
||||
echo enable ok
|
||||
}
|
||||
|
||||
function disable() {
|
||||
crudini --del $OUTPUT_DIR/System/$CFG_FILE UWeb.WebServer 'Applications[2]'
|
||||
crudini --del $OUTPUT_DIR/System/$CFG_FILE UWeb.WebServer 'ApplicationPaths[2]'
|
||||
echo disable ok
|
||||
}
|
||||
|
||||
function show_help() {
|
||||
echo
|
||||
echo "Usage: $0 { install | enable | disable } <UT99_INSTALL_DIR> [<UT99_CONFIG_FILE>]"
|
||||
echo
|
||||
}
|
||||
|
||||
function check_cfg_file() {
|
||||
if [ -z ${CFG_FILE} ]
|
||||
then
|
||||
echo "CFG_FILE is unset, setting it to $DEFAULT_CFG_FILE"
|
||||
CFG_FILE=$DEFAULT_CFG_FILE
|
||||
else
|
||||
echo "CFG_FILE is set to '$CFG_FILE'"
|
||||
fi
|
||||
|
||||
if [ ! -f $OUTPUT_DIR/System/$CFG_FILE ]
|
||||
then
|
||||
echo "$OUTPUT_DIR/System/$CFG_FILE does not exist"
|
||||
show_help
|
||||
exit 9999 # die with error code 9999
|
||||
fi
|
||||
}
|
||||
|
||||
function check_game_dir() {
|
||||
### Check if a directory does not exist ###
|
||||
if [ ! -d $OUTPUT_DIR ]
|
||||
then
|
||||
echo "incorrect <UT99_INSTALL_DIR>"
|
||||
show_help
|
||||
exit 9999 # die with error code 9999
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
'install')
|
||||
check_game_dir
|
||||
install
|
||||
;;
|
||||
'enable')
|
||||
check_game_dir
|
||||
check_cfg_file
|
||||
disable
|
||||
enable
|
||||
;;
|
||||
'disable')
|
||||
check_game_dir
|
||||
check_cfg_file
|
||||
disable
|
||||
;;
|
||||
*)
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,436 @@
|
|||
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 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$="\"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$="\"bTournament\":"$class<DeathMatchPlus>(GameClass).Default.bTournament;
|
||||
|
||||
if( class<TeamGamePlus>(GameClass) != None )
|
||||
{
|
||||
tmp$=",\"bPlayersBalanceTeams\":"$class<TeamGamePlus>(GameClass).Default.bPlayersBalanceTeams;
|
||||
}
|
||||
|
||||
if( class<LastManStanding>(GameClass) == None )
|
||||
{
|
||||
tmp$=",\"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\",";
|
||||
case 2:
|
||||
tmp$="\"GameStyle\":\"Turbo\",";
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
del %~dp0\..\System\ChaChaRESTStats.u
|
||||
%~dp0\..\System\ucc.exe make ChaChaRESTStats
|
Binary file not shown.
Loading…
Reference in New Issue