499 lines
13 KiB
Ucode
499 lines
13 KiB
Ucode
class Browser_ServersList extends GUIMultiColumnList;
|
|
|
|
//#exec OBJ LOAD file=..\Textures\Old2k4\ServerIcons.utx
|
|
//#exec Texture Import File=textures\UTClassicIcon.tga Name=S_UTClassic Mips=Off Alpha=1
|
|
|
|
var() array<GameInfo.ServerResponseLine> Servers;
|
|
|
|
var Browser_ServerListPageBase MyPage;
|
|
var Browser_RulesList MyRulesList;
|
|
var Browser_PlayersList MyPlayersList;
|
|
var GUIStyles SelStyle;
|
|
var array<int> OutstandingPings;
|
|
var int UseSimultaneousPings;
|
|
var int PingStart;
|
|
var int NumReceivedPings;
|
|
var int NumPlayers;
|
|
|
|
//ifdef _KF_
|
|
var int MaxPingsPerSecond;
|
|
//endif _KF_
|
|
|
|
var() array<Material> Icons;
|
|
var() localized array<String> IconDescriptions;
|
|
|
|
function InitComponent(GUIController MyController, GUIComponent MyOwner)
|
|
{
|
|
local int i;
|
|
|
|
// let rules/players know about us
|
|
MyPlayersList.MyServersList = Self;
|
|
MyRulesList.MyServersList = Self;
|
|
|
|
// set delegates
|
|
OnDrawItem = MyOnDrawItem;
|
|
OnChange = MyOnChange;
|
|
OnDblClick = MyOnDblClick;
|
|
|
|
Super.Initcomponent(MyController, MyOwner);
|
|
SelStyle = Controller.GetStyle("SquareButton",FontScale);
|
|
|
|
if( Controller.MaxSimultaneousPings == 0 )
|
|
{
|
|
i = class'Player'.default.ConfiguredInternetSpeed;
|
|
if (i<=2600)
|
|
UseSimultaneousPings = 10;
|
|
else if (i<=5000)
|
|
UseSimultaneousPings = 15;
|
|
else if (i<=10000)
|
|
UseSimultaneousPings = 20;
|
|
else
|
|
UseSimultaneousPings = 35;
|
|
}
|
|
else
|
|
UseSimultaneousPings = Controller.MaxSimultaneousPings;
|
|
|
|
//ifdef _KF_
|
|
MaxPingsPerSecond = Controller.MaxPingsPerSecond;
|
|
//endif _KF_
|
|
}
|
|
|
|
function Clear()
|
|
{
|
|
PingStart = 0;
|
|
StopPings();
|
|
Servers.Remove(0,Servers.Length);
|
|
ItemCount = 0;
|
|
Super.Clear();
|
|
}
|
|
|
|
function CopyServerToClipboard()
|
|
{
|
|
local string URL;
|
|
|
|
if( Index >= 0 )
|
|
{
|
|
URL = PlayerOwner().GetURLProtocol()$"://"$Servers[SortData[Index].SortItem].IP$":"$string(Servers[SortData[Index].SortItem].Port);
|
|
PlayerOwner().CopyToClipboard(URL);
|
|
}
|
|
}
|
|
|
|
function Connect(bool Spectator)
|
|
{
|
|
local string URL;
|
|
if( Index >= 0 )
|
|
{
|
|
URL = PlayerOwner().GetURLProtocol()$"://"$Servers[SortData[Index].SortItem].IP$":"$string(Servers[SortData[Index].SortItem].Port);
|
|
if( Spectator )
|
|
URL = URL $ "?SpectatorOnly=1";
|
|
if( MyPage.ConnectLAN )
|
|
URL = URL $ "?LAN";
|
|
|
|
Controller.CloseAll(false);
|
|
PlayerOwner().ClientTravel( URL, TRAVEL_Absolute, false );
|
|
}
|
|
}
|
|
|
|
function AddFavorite( ServerBrowser Browser )
|
|
{
|
|
if( Index >= 0 )
|
|
Browser.OnAddFavorite( Servers[SortData[Index].SortItem] );
|
|
}
|
|
|
|
function bool MyOnDblClick(GUIComponent Sender)
|
|
{
|
|
Connect(false);
|
|
return true;
|
|
}
|
|
|
|
function bool InternalOnKeyEvent(out byte Key, out byte State, float delta)
|
|
{
|
|
if( Super.InternalOnKeyEvent(Key, State, delta) )
|
|
return true;
|
|
|
|
if( State==1 )
|
|
{
|
|
switch(Key)
|
|
{
|
|
case 0x0D: //IK_Enter
|
|
Connect(false);
|
|
return true;
|
|
break;
|
|
case 0x74: //IK_F5
|
|
MyPage.RefreshList();
|
|
return true;
|
|
break;
|
|
case 0x43: // IK_C
|
|
if(Controller.CtrlPressed)
|
|
{
|
|
// Ctrl-C on the server list copies selected server to clipboard.
|
|
CopyServerToClipboard();
|
|
return true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function MyOnReceivedServer( GameInfo.ServerResponseLine s )
|
|
{
|
|
local int i;
|
|
|
|
i = Servers.Length;
|
|
Servers.Length=i+1;
|
|
Servers[i] = s;
|
|
if( Servers[i].Ping == 0 )
|
|
Servers[i].Ping = 9999;
|
|
ItemCount++;
|
|
AddedItem();
|
|
}
|
|
|
|
function MyPingTimeout( int listid, ServerQueryClient.EPingCause PingCause )
|
|
{
|
|
local int i;
|
|
|
|
if(listid >= Servers.Length)
|
|
return;
|
|
|
|
if( Servers[listid].Ping == 9999 )
|
|
{
|
|
Servers[listid].Ping = 10000;
|
|
UpdatedItem(listid);
|
|
}
|
|
|
|
// remove from the outstanding ping list
|
|
for( i=0;i<OutstandingPings.Length;i++ )
|
|
if( OutstandingPings[i] == listid )
|
|
{
|
|
OutstandingPings.Remove(i,1);
|
|
break;
|
|
}
|
|
|
|
// continue pinging
|
|
if( PingCause == PC_AutoPing )
|
|
{
|
|
NumReceivedPings++;
|
|
NeedsSorting = True;
|
|
AutoPingServers();
|
|
}
|
|
}
|
|
|
|
function MyReceivedPingInfo( int listid, ServerQueryClient.EPingCause PingCause, GameInfo.ServerResponseLine s )
|
|
{
|
|
local int i;
|
|
|
|
if( listid < 0 )
|
|
{
|
|
PingStart = 0;
|
|
return;
|
|
}
|
|
|
|
Servers[listid] = s;
|
|
|
|
// see if we can move the ping start marker down
|
|
for( i=PingStart;i<listid && i<Servers.Length;i++ )
|
|
if( Servers[i].Ping == 9999 )
|
|
break;
|
|
if( i < listid )
|
|
PingStart = listid;
|
|
|
|
// remove from the outstanding ping list
|
|
for( i=0;i<OutstandingPings.Length;i++ )
|
|
if( OutstandingPings[i] == listid )
|
|
{
|
|
OutstandingPings.Remove(i,1);
|
|
break;
|
|
}
|
|
|
|
UpdatedItem(listid);
|
|
|
|
// update rules/player info
|
|
if( Index>=0 && listid == SortData[Index].SortItem )
|
|
MyOnChange(None);
|
|
|
|
// continue pinging
|
|
if( PingCause == PC_AutoPing )
|
|
{
|
|
NumReceivedPings++;
|
|
NumPlayers += s.CurrentPlayers;
|
|
NeedsSorting = True;
|
|
AutoPingServers();
|
|
}
|
|
}
|
|
|
|
function RePingServers()
|
|
{
|
|
InvalidatePings();
|
|
AutoPingServers();
|
|
}
|
|
|
|
function MyQueryFinished( MasterServerClient.EResponseInfo ResponseInfo, int Info )
|
|
{
|
|
if( ResponseInfo == RI_Success )
|
|
{
|
|
RePingServers();
|
|
}
|
|
}
|
|
|
|
function InvalidatePings()
|
|
{
|
|
local int i;
|
|
StopPings();
|
|
PingStart = 0;
|
|
NumReceivedPings=0;
|
|
NumPlayers=0;
|
|
for( i=0;i<Servers.Length;i++ )
|
|
{
|
|
Servers[i].Ping = 9999;
|
|
UpdatedItem(i);
|
|
}
|
|
}
|
|
|
|
function AutoPingServers()
|
|
{
|
|
local int i, j;
|
|
|
|
for( i=PingStart;i<Servers.Length && OutstandingPings.Length < UseSimultaneousPings;i++ )
|
|
{
|
|
if( Servers[i].Ping == 9999 )
|
|
{
|
|
// see if we already have an outstanding ping for this server.
|
|
for( j=0;j<OutstandingPings.Length;j++ )
|
|
if( OutstandingPings[j] == i )
|
|
break;
|
|
|
|
if( j == OutstandingPings.Length )
|
|
{
|
|
// ping
|
|
MyPage.PingServer( i, PC_AutoPing, Servers[i] );
|
|
|
|
// add out outstanding ping list
|
|
j = OutstandingPings.Length;
|
|
OutstandingPings.Length = j+1;
|
|
OutstandingPings[j] = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(OutstandingPings.Length == 0)
|
|
NumReceivedPings = Servers.Length;
|
|
}
|
|
|
|
function StopPings()
|
|
{
|
|
OutstandingPings.Remove(0,OutstandingPings.Length);
|
|
MyPage.CancelPings();
|
|
}
|
|
|
|
event Timer()
|
|
{
|
|
if( Index >= 0 )
|
|
MyOnChange( Self );
|
|
}
|
|
|
|
function MyOnChange(GUIComponent Sender)
|
|
{
|
|
MyRulesList.Clear();
|
|
MyPlayersList.Clear();
|
|
if( Index >= 0 )
|
|
{
|
|
// when changing selected servers, get their rules
|
|
if( Sender != None )
|
|
MyPage.PingServer( SortData[Index].SortItem, PC_Clicked, Servers[SortData[Index].SortItem] );
|
|
|
|
MyRulesList.ItemCount = Servers[SortData[Index].SortItem].ServerInfo.Length;
|
|
MyRulesList.ListItem = SortData[Index].SortItem;
|
|
MyPlayersList.ItemCount = Servers[SortData[Index].SortItem].PlayerInfo.Length;
|
|
MyPlayersList.ListItem = SortData[Index].SortItem;
|
|
SetTimer( 5, false );
|
|
}
|
|
else
|
|
{
|
|
MyRulesList.ItemCount = 0;
|
|
MyPlayersList.ItemCount = 0;
|
|
}
|
|
}
|
|
|
|
function int RemoveCurrentServer()
|
|
{
|
|
local int OldItem;
|
|
if( Index >= 0 )
|
|
{
|
|
OldItem = SortData[Index].SortItem;
|
|
|
|
Servers.Remove( OldItem, 1 );
|
|
ItemCount--;
|
|
|
|
MyRulesList.ItemCount = 0;
|
|
MyPlayersList.ItemCount = 0;
|
|
|
|
// tell sort lists.
|
|
RemovedCurrent();
|
|
|
|
return OldItem;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
function MyOnDrawItem(Canvas Canvas, int i, float X, float Y, float W, float H, bool bSelected, bool bPending)
|
|
{
|
|
local float CellLeft, CellWidth, DrawX;
|
|
local float IconPosX, IconPosY;
|
|
local string Ping;
|
|
local int k, flags, checkFlag;
|
|
|
|
// Draw the selection border
|
|
if( bSelected )
|
|
SelStyle.Draw(Canvas,MSAT_Pressed, X, Y-2, W, H+2 );
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Here we get the flags for this server.
|
|
// Passworded 1 << 30
|
|
// Stats 1 << 29
|
|
// LatestVersion 1 << 28
|
|
// Listen Server 1 << 27
|
|
// Instagib 1 << 26
|
|
// Standard 1 << 25
|
|
// UT CLassic 1 << 24
|
|
|
|
// flags are encoded at the top of MaxPlayers
|
|
flags = Servers[SortData[i].SortItem].MaxPlayers;
|
|
//flags = (1 << 30) | (1 << 29) | (1 << 28) | (1 << 27) | (1 << 26) | (1 << 25); // For testing
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
GetCellLeftWidth( 0, CellLeft, CellWidth );
|
|
IconPosX = CellLeft;
|
|
IconPosY = Y;
|
|
|
|
// First flag is in the second to most sig bit (dont want to mess with sign bit). Then we work down.
|
|
checkFlag = 1 << 30;
|
|
|
|
// While we still have icon, and we can fit another one in.
|
|
for(k=0; (k<Icons.Length) && (IconPosX < CellLeft + CellWidth); k++)
|
|
{
|
|
if((flags & checkFlag) != 0)
|
|
{
|
|
DrawX = Min(14, (CellLeft + CellWidth) - IconPosX);
|
|
|
|
Canvas.DrawColor = Canvas.MakeColor(255, 255, 255, 255);
|
|
|
|
Canvas.SetPos(IconPosX, IconPosY);
|
|
Canvas.DrawTile(Icons[k], DrawX, 14, 0, 0, DrawX+1.0, 15.0);
|
|
|
|
IconPosX += 14;
|
|
}
|
|
|
|
checkFlag = checkFlag >> 1;
|
|
}
|
|
|
|
|
|
GetCellLeftWidth( 1, CellLeft, CellWidth );
|
|
Style.DrawText( Canvas, MenuState, CellLeft, Y, CellWidth, H, TXTA_Left, Servers[SortData[i].SortItem].ServerName, FontScale );
|
|
|
|
GetCellLeftWidth( 2, CellLeft, CellWidth );
|
|
Style.DrawText( Canvas, MenuState, CellLeft, Y, CellWidth, H, TXTA_Left, Servers[SortData[i].SortItem].MapName, FontScale );
|
|
|
|
GetCellLeftWidth( 3, CellLeft, CellWidth );
|
|
if( Servers[SortData[i].SortItem].CurrentPlayers>0 || Servers[SortData[i].SortItem].MaxPlayers>0 )
|
|
Style.DrawText( Canvas, MenuState, CellLeft, Y, CellWidth, H, TXTA_Left, string(Servers[SortData[i].SortItem].CurrentPlayers)$"/"$string((Servers[SortData[i].SortItem].MaxPlayers&255)), FontScale );
|
|
|
|
GetCellLeftWidth( 4, CellLeft, CellWidth );
|
|
if( Servers[SortData[i].SortItem].Ping == 9999 )
|
|
Ping = "?";
|
|
else
|
|
if( Servers[SortData[i].SortItem].Ping == 10000 )
|
|
Ping = "N/A";
|
|
else
|
|
Ping = string(Servers[SortData[i].SortItem].Ping);
|
|
Style.DrawText( Canvas, MenuState, CellLeft, Y, CellWidth, H, TXTA_Left, Ping, FontScale );
|
|
|
|
// GetCellLeftWidth( 4, CellLeft, CellWidth );
|
|
// Style.DrawText( Canvas, MenuState, X+CellLeft, Y, CellWidth, H, TXTA_Left, SortData[i].SortString, FontScale );
|
|
}
|
|
|
|
function string GetSortString( int i )
|
|
{
|
|
local string s, t;
|
|
|
|
switch( SortColumn )
|
|
{
|
|
case 0:
|
|
case 1:
|
|
s = Left(caps(Servers[i].ServerName), 8);
|
|
break;
|
|
case 2:
|
|
s = Left(caps(Servers[i].MapName), 8);
|
|
break;
|
|
case 3:
|
|
s = string(Servers[i].CurrentPlayers);
|
|
while(Len(s) < 4 )
|
|
s = "0"$s;
|
|
t = string((Servers[i].MaxPlayers&255));
|
|
while(Len(t) < 4 )
|
|
t = "0"$t;
|
|
s = s $ t;
|
|
break;
|
|
case 4:
|
|
s = string(Servers[i].Ping);
|
|
while(Len(s) < 5 )
|
|
s = "0"$s;
|
|
break;
|
|
default:
|
|
s = string(Servers[i].Ping);
|
|
while(Len(s) < 5 )
|
|
s = "0"$s;
|
|
break;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
ColumnHeadings(0)=""
|
|
ColumnHeadings(1)="Server Name"
|
|
ColumnHeadings(2)="Map"
|
|
ColumnHeadings(3)="Players"
|
|
ColumnHeadings(4)="Ping"
|
|
|
|
InitColumnPerc(0)=0.10
|
|
InitColumnPerc(1)=0.37
|
|
InitColumnPerc(2)=0.25
|
|
InitColumnPerc(3)=0.13
|
|
InitColumnPerc(4)=0.15
|
|
|
|
SortColumn=4
|
|
SortDescending=False
|
|
|
|
// if _RO_
|
|
/*
|
|
// end if _RO_
|
|
|
|
Icons(0)=material'ServerIcons.Password'
|
|
IconDescriptions(0)="Passworded"
|
|
|
|
Icons(1)=material'ServerIcons.Stats'
|
|
IconDescriptions(1)="Stats Enabled"
|
|
|
|
Icons(2)=material'ServerIcons.LatestVersion'
|
|
IconDescriptions(2)="Latest Version"
|
|
|
|
Icons(3)=material'ServerIcons.ListenServer'
|
|
IconDescriptions(3)="Listen Server"
|
|
|
|
Icons(4)=material'ServerIcons.Instagib'
|
|
IconDescriptions(4)="Instagib"
|
|
|
|
Icons(5)=material'ServerIcons.Standard'
|
|
IconDescriptions(5)="Standard Server"
|
|
|
|
Icons(6)=material'xInterface.S_UTClassic'
|
|
IconDescriptions(6)="UT Classic"
|
|
// if _RO_
|
|
*/
|
|
// end if _RO_
|
|
}
|