Тут будет тема, в которой можно писать всю движуху по сырцам дума третьего - изменению, доработке, обсуждению и прочее прочее.
Сам исходный код движка находится тут - GitHub
...
...
В разработке... (Внимание: это меню отображается некорректно на некоторых стилях форума)
Форум Мапперов и Doom'еров |
Привет, Гость! Войдите или зарегистрируйтесь.
Вы здесь » Форум Мапперов и Doom'еров » idTech 4 » Исходный код (Source Code)
Тут будет тема, в которой можно писать всю движуху по сырцам дума третьего - изменению, доработке, обсуждению и прочее прочее.
Сам исходный код движка находится тут - GitHub
В оригинальном движке по дефолту русская буква я (маленькая) в чате сетевой игры не вводится. Чтобы это исправить, нужно поправить EditWindow.cpp, находящийся в neo\ui. Изменение вносится в .exe, не в .dll.
В idEditWindow::HandleEvent в блоке if начинающемся на 212 строке нужно добавить:
if ( key == 255 ) {
text = text + '`';
cursorPos = len + 1;
return "";
}
:
/*
=============
idEditWindow::HandleEvent
=============
*/
const char *idEditWindow::HandleEvent(const sysEvent_t *event, bool *updateVisuals) {
static char buffer[ MAX_EDITFIELD ];
const char *ret = "";if ( wrap ) {
// need to call this to allow proper focus and capturing on embedded children
ret = idWindow::HandleEvent( event, updateVisuals );
if ( ret && *ret ) {
return ret;
}
}if ( ( event->evType != SE_CHAR && event->evType != SE_KEY ) ) {
return ret;
}idStr::Copynz( buffer, text.c_str(), sizeof( buffer ) );
int key = event->evValue;
int len = text.Length();if ( event->evType == SE_CHAR ) {
if ( event->evValue == Sys_GetConsoleKey( false ) || event->evValue == Sys_GetConsoleKey( true ) ) {
return "";
}if ( updateVisuals ) {
*updateVisuals = true;
}if ( maxChars && len > maxChars ) {
len = maxChars;
}
if ( ( key == K_ENTER || key == K_KP_ENTER ) && event->evValue2 ) {
RunScript( ON_ACTION );
RunScript( ON_ENTER );
return cmd;
}if ( key == K_ESCAPE ) {
RunScript( ON_ESC );
return cmd;
}if ( readonly ) {
return "";
}if ( key == 255 ) {
text = text + '`';
cursorPos = len + 1;
return "";
}
if ( key == 'h' - 'a' + 1 || key == K_BACKSPACE ) { // ctrl-h is backspace
if ( cursorPos > 0 ) {
if ( cursorPos >= len ) {
buffer[len - 1] = 0;
cursorPos = len - 1;
} else {
memmove( &buffer[ cursorPos - 1 ], &buffer[ cursorPos ], len + 1 - cursorPos);
cursorPos--;
}text = buffer;
UpdateCvar( false );
RunScript( ON_ACTION );
}return "";
}//
// ignore any non printable chars (except enter when wrap is enabled)
//
if ( wrap && (key == K_ENTER || key == K_KP_ENTER) ) {
} else if ( !idStr::CharIsPrintable( key ) ) {
return "";
}if ( numeric ) {
if ( ( key < '0' || key > '9' ) && key != '.' ) {
return "";
}
}if ( dc->GetOverStrike() ) {
if ( maxChars && cursorPos >= maxChars ) {
return "";
}
} else {
if ( ( len == MAX_EDITFIELD - 1 ) || ( maxChars && len >= maxChars ) ) {
return "";
}
memmove( &buffer[ cursorPos + 1 ], &buffer[ cursorPos ], len + 1 - cursorPos );
}buffer[ cursorPos ] = key;
text = buffer;
UpdateCvar( false );
RunScript( ON_ACTION );if ( cursorPos < len + 1 ) {
cursorPos++;
}
EnsureCursorVisible();} else if ( event->evType == SE_KEY && event->evValue2 ) {
if ( updateVisuals ) {
*updateVisuals = true;
}if ( key == K_DEL ) {
if ( readonly ) {
return ret;
}
if ( cursorPos < len ) {
memmove( &buffer[cursorPos], &buffer[cursorPos + 1], len - cursorPos);
text = buffer;
UpdateCvar( false );
RunScript( ON_ACTION );
}
return ret;
}if ( key == K_RIGHTARROW ) {
if ( cursorPos < len ) {
if ( idKeyInput::IsDown( K_CTRL ) ) {
// skip to next word
while( ( cursorPos < len ) && ( buffer[ cursorPos ] != ' ' ) ) {
cursorPos++;
}while( ( cursorPos < len ) && ( buffer[ cursorPos ] == ' ' ) ) {
cursorPos++;
}
} else {
if ( cursorPos < len ) {
cursorPos++;
}
}
}EnsureCursorVisible();
return ret;
}if ( key == K_LEFTARROW ) {
if ( idKeyInput::IsDown( K_CTRL ) ) {
// skip to previous word
while( ( cursorPos > 0 ) && ( buffer[ cursorPos - 1 ] == ' ' ) ) {
cursorPos--;
}while( ( cursorPos > 0 ) && ( buffer[ cursorPos - 1 ] != ' ' ) ) {
cursorPos--;
}
} else {
if ( cursorPos > 0 ) {
cursorPos--;
}
}EnsureCursorVisible();
return ret;
}if ( key == K_HOME ) {
if ( idKeyInput::IsDown( K_CTRL ) || cursorLine <= 0 || ( cursorLine >= breaks.Num() ) ) {
cursorPos = 0;
} else {
cursorPos = breaks[cursorLine];
}
EnsureCursorVisible();
return ret;
}if ( key == K_END ) {
if ( idKeyInput::IsDown( K_CTRL ) || (cursorLine < -1) || ( cursorLine >= breaks.Num() - 1 ) ) {
cursorPos = len;
} else {
cursorPos = breaks[cursorLine + 1] - 1;
}
EnsureCursorVisible();
return ret;
}if ( key == K_INS ) {
if ( !readonly ) {
dc->SetOverStrike( !dc->GetOverStrike() );
}
return ret;
}if ( key == K_DOWNARROW ) {
if ( idKeyInput::IsDown( K_CTRL ) ) {
scroller->SetValue( scroller->GetValue() + 1.0f );
} else {
if ( cursorLine < breaks.Num() - 1 ) {
int offset = cursorPos - breaks[cursorLine];
cursorPos = breaks[cursorLine + 1] + offset;
EnsureCursorVisible();
}
}
}if (key == K_UPARROW ) {
if ( idKeyInput::IsDown( K_CTRL ) ) {
scroller->SetValue( scroller->GetValue() - 1.0f );
} else {
if ( cursorLine > 0 ) {
int offset = cursorPos - breaks[cursorLine];
cursorPos = breaks[cursorLine - 1] + offset;
EnsureCursorVisible();
}
}
}if ( key == K_ENTER || key == K_KP_ENTER ) {
RunScript( ON_ACTION );
RunScript( ON_ENTER );
return cmd;
}if ( key == K_ESCAPE ) {
RunScript( ON_ESC );
return cmd;
}} else if ( event->evType == SE_KEY && !event->evValue2 ) {
if ( key == K_ENTER || key == K_KP_ENTER ) {
RunScript( ON_ENTERRELEASE );
return cmd;
} else {
RunScript( ON_ACTIONRELEASE );
}
}return ret;
}
Добавляем net_usePreloadedServers
Нужно отредактировать ServerScan.h и ServerScan.cpp в neo\framework\async
#ifndef __SERVERSCAN_H__
#define __SERVERSCAN_H__/*
===============================================================================Scan for servers, on the LAN or from a list
Update a listDef GUI through usage of idListGUI class
When updating large lists of servers, sends out getInfo in small batches to avoid congestion===============================================================================
*/// storage for incoming servers / server scan
typedef struct {
netadr_t adr;
int id;
int time;
} inServer_t;// the menu gui uses a hard-coded control type to display a list of network games
typedef struct {
netadr_t adr;
idDict serverInfo;
int ping;
int id; // idnet mode sends an id for each server in list
int clients;
char nickname[ MAX_NICKLEN ][ MAX_ASYNC_CLIENTS ];
short pings[ MAX_ASYNC_CLIENTS ];
int rate[ MAX_ASYNC_CLIENTS ];
int OSMask;
int challenge;
} networkServer_t;typedef enum {
SORT_PING,
SORT_SERVERNAME,
SORT_PLAYERS,
SORT_GAMETYPE,
SORT_MAP,
SORT_GAME
} serverSort_t;class idServerScan : public idList<networkServer_t> {
public:
idServerScan( );int InfoResponse( networkServer_t &server );
// add an internet server - ( store a numeric id along with it )
void AddServer( int id, const char *srv );// we are going to feed server entries to be pinged
// if timeout is true, use a timeout once we start AddServer to trigger EndServers and decide the scan is done
void StartServers( bool timeout );
// we are done filling up the list of server entries
void EndServers( );// scan the current list of servers - used for refreshes and while receiving a fresh list
void NetScan( );// clear
void Clear( );// called each game frame. Updates the scanner state, takes care of ongoing scans
void RunFrame( );typedef enum {
IDLE = 0,
WAIT_ON_INIT,
LAN_SCAN,
NET_SCAN
} scan_state_t;scan_state_t GetState() { return scan_state; }
void SetState( scan_state_t );bool GetBestPing( networkServer_t &serv );
// prepare for a LAN scan. idAsyncClient does the network job (UDP broadcast), we do the storage
void SetupLANScan( );void GUIConfig( idUserInterface *pGUI, const char *name );
// update the GUI fields with information about the currently selected server
void GUIUpdateSelected( void );void Shutdown( );
void ApplyFilter( );
// there is an internal toggle, call twice with same sort to switch
void SetSorting( serverSort_t sort );int GetChallenge( );
private:
static const int MAX_PINGREQUESTS = 32; // how many servers to query at once
static const int REPLY_TIMEOUT = 999; // how long should we wait for a reply from a game server
static const int INCOMING_TIMEOUT = 1500; // when we got an incoming server list, how long till we decide the list is done
static const int REFRESH_START = 10000; // how long to wait when sending the initial refresh requestscan_state_t scan_state;
bool incoming_net; // set to true while new servers are fed through AddServer
bool incoming_useTimeout;
int incoming_lastTime;int lan_pingtime; // holds the time of LAN scan
// servers we're waiting for a reply from
// won't exceed MAX_PINGREQUESTS elements
// holds index of net_servers elements, indexed by 'from' string
idDict net_info;idList<inServer_t> net_servers;
// where we are in net_servers list for getInfo emissions ( NET_SCAN only )
// we may either be waiting on MAX_PINGREQUESTS, or for net_servers to grow some more ( through AddServer )
int cur_info;idUserInterface *m_pGUI;
idListGUI * listGUI;serverSort_t m_sort;
bool m_sortAscending;
idList<int> m_sortedServers; // use ascending for the walking orderidStr screenshot;
int challenge; // challenge for current scanint endWaitTime; // when to stop waiting on a port init
private:
void LocalClear( ); // we need to clear some internal data as wellvoid EmitGetInfo( netadr_t &serv );
void GUIAdd( int id, const networkServer_t server );
bool IsFiltered( const networkServer_t server );static int Cmp( const int *a, const int *b );
void AddPreloadedServers();
};#endif /* !__SERVERSCAN_H__ */
#include "../../idlib/precompiled.h"
#pragma hdrstopidCVar gui_filter_password( "gui_filter_password", "0", CVAR_GUI | CVAR_INTEGER | CVAR_ARCHIVE, "Password filter" );
idCVar gui_filter_players( "gui_filter_players", "0", CVAR_GUI | CVAR_INTEGER | CVAR_ARCHIVE, "Players filter" );
idCVar gui_filter_gameType( "gui_filter_gameType", "0", CVAR_GUI | CVAR_INTEGER | CVAR_ARCHIVE, "Gametype filter" );
idCVar gui_filter_idle( "gui_filter_idle", "0", CVAR_GUI | CVAR_INTEGER | CVAR_ARCHIVE, "Idle servers filter" );
idCVar gui_filter_game( "gui_filter_game", "0", CVAR_GUI | CVAR_INTEGER | CVAR_ARCHIVE, "Game filter" );idCVar net_usePreloadedServers ("net_usePreloadedServers","0", CVAR_BOOL | CVAR_ARCHIVE, "Use preloaded servers in server browser if master-server has no response");
idCVar net_preloadedServer1 ("net_preloadedServer1", "", CVAR_ARCHIVE, "Preloaded server 1 (IP:port)");
idCVar net_preloadedServer2 ("net_preloadedServer2", "", CVAR_ARCHIVE, "Preloaded server 2 (IP:port)");
idCVar net_preloadedServer3 ("net_preloadedServer3", "", CVAR_ARCHIVE, "Preloaded server 3 (IP:port)");
idCVar net_preloadedServer4 ("net_preloadedServer4", "", CVAR_ARCHIVE, "Preloaded server 4 (IP:port)");
idCVar net_preloadedServer5 ("net_preloadedServer5", "", CVAR_ARCHIVE, "Preloaded server 5 (IP:port)");
idCVar net_preloadedServer6 ("net_preloadedServer6", "", CVAR_ARCHIVE, "Preloaded server 6 (IP:port)");
idCVar net_preloadedServer7 ("net_preloadedServer7", "", CVAR_ARCHIVE, "Preloaded server 7 (IP:port)");
idCVar net_preloadedServer8 ("net_preloadedServer8", "", CVAR_ARCHIVE, "Preloaded server 8 (IP:port)");
idCVar net_preloadedServer9 ("net_preloadedServer9", "", CVAR_ARCHIVE, "Preloaded server 9 (IP:port)");
idCVar net_preloadedServer10 ("net_preloadedServer10", "", CVAR_ARCHIVE, "Preloaded server 10 (IP:port)");
idCVar net_preloadedServer11 ("net_preloadedServer11", "", CVAR_ARCHIVE, "Preloaded server 11 (IP:port)");
idCVar net_preloadedServer12 ("net_preloadedServer12", "", CVAR_ARCHIVE, "Preloaded server 12 (IP:port)");
idCVar net_preloadedServer13 ("net_preloadedServer13", "", CVAR_ARCHIVE, "Preloaded server 13 (IP:port)");
idCVar net_preloadedServer14 ("net_preloadedServer14", "", CVAR_ARCHIVE, "Preloaded server 14 (IP:port)");
idCVar net_preloadedServer15 ("net_preloadedServer15", "", CVAR_ARCHIVE, "Preloaded server 15 (IP:port)");
idCVar net_preloadedServer16 ("net_preloadedServer16", "", CVAR_ARCHIVE, "Preloaded server 16 (IP:port)");
idCVar net_preloadedServer17 ("net_preloadedServer17", "", CVAR_ARCHIVE, "Preloaded server 17 (IP:port)");
idCVar net_preloadedServer18 ("net_preloadedServer18", "", CVAR_ARCHIVE, "Preloaded server 18 (IP:port)");
idCVar net_preloadedServer19 ("net_preloadedServer19", "", CVAR_ARCHIVE, "Preloaded server 19 (IP:port)");
idCVar net_preloadedServer20 ("net_preloadedServer20", "", CVAR_ARCHIVE, "Preloaded server 20 (IP:port)");
idCVar net_preloadedServer21 ("net_preloadedServer21", "", CVAR_ARCHIVE, "Preloaded server 21 (IP:port)");
idCVar net_preloadedServer22 ("net_preloadedServer22", "", CVAR_ARCHIVE, "Preloaded server 22 (IP:port)");
idCVar net_preloadedServer23 ("net_preloadedServer23", "", CVAR_ARCHIVE, "Preloaded server 23 (IP:port)");
idCVar net_preloadedServer24 ("net_preloadedServer24", "", CVAR_ARCHIVE, "Preloaded server 24 (IP:port)");
idCVar net_preloadedServer25 ("net_preloadedServer25", "", CVAR_ARCHIVE, "Preloaded server 25 (IP:port)");
idCVar net_preloadedServer26 ("net_preloadedServer26", "", CVAR_ARCHIVE, "Preloaded server 26 (IP:port)");
idCVar net_preloadedServer27 ("net_preloadedServer27", "", CVAR_ARCHIVE, "Preloaded server 27 (IP:port)");
idCVar net_preloadedServer28 ("net_preloadedServer28", "", CVAR_ARCHIVE, "Preloaded server 28 (IP:port)");
idCVar net_preloadedServer29 ("net_preloadedServer29", "", CVAR_ARCHIVE, "Preloaded server 29 (IP:port)");
idCVar net_preloadedServer30 ("net_preloadedServer30", "", CVAR_ARCHIVE, "Preloaded server 30 (IP:port)");
static idCVar* preloadedServers[30] = {
&net_preloadedServer1, &net_preloadedServer2, &net_preloadedServer3, &net_preloadedServer4, &net_preloadedServer5,
&net_preloadedServer6, &net_preloadedServer7, &net_preloadedServer8, &net_preloadedServer9, &net_preloadedServer10,
&net_preloadedServer11, &net_preloadedServer12, &net_preloadedServer13, &net_preloadedServer14, &net_preloadedServer15,
&net_preloadedServer16, &net_preloadedServer17, &net_preloadedServer18, &net_preloadedServer19, &net_preloadedServer20,
&net_preloadedServer21, &net_preloadedServer22, &net_preloadedServer23, &net_preloadedServer24, &net_preloadedServer25,
&net_preloadedServer26, &net_preloadedServer27, &net_preloadedServer28, &net_preloadedServer29, &net_preloadedServer30
};
static bool NetAdrEqual(const netadr_t& a, const netadr_t& b) {
return a.type == b.type &&
a.port == b.port &&
memcmp(a.ip, b.ip, 4) == 0;
}const char* l_gameTypes[] = {
"Deathmatch",
"Tourney",
"Team DM",
"Last Man",
"CTF",
NULL
};static idServerScan *l_serverScan = NULL;
/*
================
idServerScan::idServerScan
================
*/
idServerScan::idServerScan( ) {
m_pGUI = NULL;
m_sort = SORT_PING;
m_sortAscending = true;
challenge = 0;
LocalClear();
}/*
================
idServerScan::LocalClear
================
*/
void idServerScan::LocalClear( ) {
scan_state = IDLE;
incoming_net = false;
lan_pingtime = -1;
net_info.Clear();
net_servers.Clear();
cur_info = 0;
if ( listGUI ) {
listGUI->Clear();
}
incoming_useTimeout = false;
m_sortedServers.Clear();
}/*
================
idServerScan::Clear
================
*/
void idServerScan::Clear( ) {
LocalClear();
idList<networkServer_t>::Clear();
}/*
================
idServerScan::Shutdown
================
*/
void idServerScan::Shutdown( ) {
m_pGUI = NULL;
if ( listGUI ) {
listGUI->Config( NULL, NULL );
uiManager->FreeListGUI( listGUI );
listGUI = NULL;
}
screenshot.Clear();
}/*
================
idServerScan::SetupLANScan
================
*/
void idServerScan::SetupLANScan( ) {
Clear();
GUIUpdateSelected();
scan_state = LAN_SCAN;
challenge++;
lan_pingtime = Sys_Milliseconds();
common->DPrintf( "SetupLANScan with challenge %d\n", challenge );
}/*
================
idServerScan::InfoResponse
================
*/
int idServerScan::InfoResponse( networkServer_t &server ) {
if ( scan_state == IDLE ) {
return false;
}idStr serv = Sys_NetAdrToString( server.adr );
if ( server.challenge != challenge ) {
common->DPrintf( "idServerScan::InfoResponse - ignoring response from %s, wrong challenge %d.", serv.c_str(), server.challenge );
return false;
}if ( scan_state == NET_SCAN ) {
const idKeyValue *info = net_info.FindKey( serv.c_str() );
if ( !info ) {
common->DPrintf( "idServerScan::InfoResponse NET_SCAN: reply from unknown %s\n", serv.c_str() );
return false;
}
int id = atoi( info->GetValue() );
net_info.Delete( serv.c_str() );
inServer_t iserv = net_servers[ id ];
server.ping = Sys_Milliseconds() - iserv.time;
server.id = iserv.id;
} else {
server.ping = Sys_Milliseconds() - lan_pingtime;
server.id = 0;// check for duplicate servers
for ( int i = 0; i < Num() ; i++ ) {
if ( memcmp( &(*this)[ i ].adr, &server.adr, sizeof(netadr_t) ) == 0 ) {
common->DPrintf( "idServerScan::InfoResponse LAN_SCAN: duplicate server %s\n", serv.c_str() );
return true;
}
}
}const char *si_map = server.serverInfo.GetString( "si_map" );
const idDecl *mapDecl = declManager->FindType( DECL_MAPDEF, si_map, false );
const idDeclEntityDef *mapDef = static_cast< const idDeclEntityDef * >( mapDecl );
if ( mapDef ) {
const char *mapName = common->GetLanguageDict()->GetString( mapDef->dict.GetString( "name", si_map ) );
server.serverInfo.Set( "si_mapName", mapName );
} else {
server.serverInfo.Set( "si_mapName", si_map );
}int index = Append( server );
// for now, don't maintain sorting when adding new info response servers
m_sortedServers.Append( Num()-1 );
if ( listGUI->IsConfigured( ) && !IsFiltered( server ) ) {
GUIAdd( Num()-1, server );
}
if ( listGUI->GetSelection( NULL, 0 ) == ( Num()-1 ) ) {
GUIUpdateSelected();
}return index;
}/*
================
idServerScan::AddServer
================
*/
void idServerScan::AddServer(int id, const char* srv) {
inServer_t s;incoming_net = true;
incoming_lastTime = Sys_Milliseconds() + INCOMING_TIMEOUT;
s.id = id;if (!Sys_StringToNetAdr(srv, &s.adr, false)) {
common->DPrintf("idServerScan::AddServer: failed to parse server %s\n", srv);
return;
}if (!s.adr.port) {
s.adr.port = PORT_SERVER;
}
if (net_usePreloadedServers.GetBool()) {
for (int i = 0; i < net_servers.Num(); i++) {
if (NetAdrEqual(net_servers[i].adr, s.adr)) {
common->DPrintf("idServerScan::AddServer: duplicate server %s\n", srv);
return;
}
}
}net_servers.Append(s);
}/*
================
idServerScan::EndServers
================
*/
void idServerScan::EndServers( ) {
incoming_net = false;
l_serverScan = this;
m_sortedServers.Sort( idServerScan::Cmp );
}/*
================
idServerScan::StartServers
================
*/
void idServerScan::StartServers( bool timeout ) {
incoming_net = true;
incoming_useTimeout = timeout;
incoming_lastTime = Sys_Milliseconds() + REFRESH_START;
if (net_usePreloadedServers.GetBool()) {
AddPreloadedServers();
}
ApplyFilter();
}/*
================
idServerScan::EmitGetInfo
================
*/
void idServerScan::EmitGetInfo( netadr_t &serv ) {
idAsyncNetwork::client.GetServerInfo( serv );
}/*
===============
idServerScan::GetChallenge
===============
*/
int idServerScan::GetChallenge( ) {
return challenge;
}/*
================
idServerScan::NetScan
================
*/
void idServerScan::NetScan( ) {
if ( !idAsyncNetwork::client.IsPortInitialized() ) {
// if the port isn't open, initialize it, but wait for a short
// time to let the OS do whatever magic things it needs to do...
idAsyncNetwork::client.InitPort();
// start the scan one second from now...
scan_state = WAIT_ON_INIT;
endWaitTime = Sys_Milliseconds() + 1000;
return;
}// make sure the client port is open
idAsyncNetwork::client.InitPort();scan_state = NET_SCAN;
challenge++;idList<networkServer_t>::Clear();
m_sortedServers.Clear();
cur_info = 0;
net_info.Clear();
listGUI->Clear();
GUIUpdateSelected();
common->DPrintf( "NetScan with challenge %d\n", challenge );while ( cur_info < Min( net_servers.Num(), MAX_PINGREQUESTS ) ) {
netadr_t serv = net_servers[ cur_info ].adr;
EmitGetInfo( serv );
net_servers[ cur_info ].time = Sys_Milliseconds();
net_info.SetInt( Sys_NetAdrToString( serv ), cur_info );
cur_info++;
}
}/*
===============
idServerScan::ServerScanFrame
===============
*/
void idServerScan::RunFrame( ) {
if ( scan_state == IDLE ) {
return;
}if ( scan_state == WAIT_ON_INIT ) {
if ( Sys_Milliseconds() >= endWaitTime ) {
scan_state = IDLE;
NetScan();
}
return;
}int timeout_limit = Sys_Milliseconds() - REPLY_TIMEOUT;
if ( scan_state == LAN_SCAN ) {
if ( timeout_limit > lan_pingtime ) {
common->Printf( "Scanned for servers on the LAN\n" );
scan_state = IDLE;
}
return;
}// if scan_state == NET_SCAN
// check for timeouts
int i = 0;
while ( i < net_info.GetNumKeyVals() ) {
if ( timeout_limit > net_servers[ atoi( net_info.GetKeyVal( i )->GetValue().c_str() ) ].time ) {
common->DPrintf( "timeout %s\n", net_info.GetKeyVal( i )->GetKey().c_str() );
net_info.Delete( net_info.GetKeyVal( i )->GetKey().c_str() );
} else {
i++;
}
}
// possibly send more queries
while ( cur_info < net_servers.Num() && net_info.GetNumKeyVals() < MAX_PINGREQUESTS ) {
netadr_t serv = net_servers[ cur_info ].adr;
EmitGetInfo( serv );
net_servers[ cur_info ].time = Sys_Milliseconds();
net_info.SetInt( Sys_NetAdrToString( serv ), cur_info );
cur_info++;
}// update state
if ( ( !incoming_net || ( incoming_useTimeout && Sys_Milliseconds() > incoming_lastTime ) ) && net_info.GetNumKeyVals() == 0 ) {
EndServers();
// the list is complete, we are no longer waiting for any getInfo replies
common->Printf( "Scanned %d servers.\n", cur_info );
scan_state = IDLE;
}
}/*
===============
idServerScan::GetBestPing
===============
*/
bool idServerScan::GetBestPing( networkServer_t &serv ) {
int i, ic;
ic = Num();
if ( !ic ) {
return false;
}
serv = (*this)[ 0 ];
for ( i = 0 ; i < ic ; i++ ) {
if ( (*this)[ i ].ping < serv.ping ) {
serv = (*this)[ i ];
}
}
return true;
}/*
================
idServerScan::GUIConfig
================
*/
void idServerScan::GUIConfig( idUserInterface *pGUI, const char *name ) {
m_pGUI = pGUI;
if ( listGUI == NULL ) {
listGUI = uiManager->AllocListGUI();
}
listGUI->Config( pGUI, name );
}/*
================
idServerScan::GUIUpdateSelected
================
*/
void idServerScan::GUIUpdateSelected( void ) {
char screenshot[ MAX_STRING_CHARS ];if ( !m_pGUI ) {
return;
}
int i = listGUI->GetSelection( NULL, 0 );
if ( i == -1 || i >= Num() ) {
m_pGUI->SetStateString( "server_name", "" );
m_pGUI->SetStateString( "player1", "" );
m_pGUI->SetStateString( "player2", "" );
m_pGUI->SetStateString( "player3", "" );
m_pGUI->SetStateString( "player4", "" );
m_pGUI->SetStateString( "player5", "" );
m_pGUI->SetStateString( "player6", "" );
m_pGUI->SetStateString( "player7", "" );
m_pGUI->SetStateString( "player8", "" );
m_pGUI->SetStateString( "server_map", "" );
m_pGUI->SetStateString( "browser_levelshot", "" );
m_pGUI->SetStateString( "server_gameType", "" );
m_pGUI->SetStateString( "server_IP", "" );
m_pGUI->SetStateString( "server_passworded", "" );
} else {
m_pGUI->SetStateString( "server_name", (*this)[ i ].serverInfo.GetString( "si_name" ) );
for ( int j = 0; j < 8; j++ ) {
if ( (*this)[i].clients > j ) {
m_pGUI->SetStateString( va( "player%i", j + 1 ) , (*this)[ i ].nickname[ j ] );
} else {
m_pGUI->SetStateString( va( "player%i", j + 1 ) , "" );
}
}
m_pGUI->SetStateString( "server_map", (*this)[ i ].serverInfo.GetString( "si_mapName" ) );
fileSystem->FindMapScreenshot( (*this)[ i ].serverInfo.GetString( "si_map" ), screenshot, MAX_STRING_CHARS );
m_pGUI->SetStateString( "browser_levelshot", screenshot );
m_pGUI->SetStateString( "server_gameType", (*this)[ i ].serverInfo.GetString( "si_gameType" ) );
m_pGUI->SetStateString( "server_IP", Sys_NetAdrToString( (*this)[ i ].adr ) );
if ( (*this)[ i ].serverInfo.GetBool( "si_usePass" ) ) {
m_pGUI->SetStateString( "server_passworded", "PASSWORD REQUIRED" );
} else {
m_pGUI->SetStateString( "server_passworded", "" );
}
}
}/*
================
idServerScan::GUIAdd
================
*/
void idServerScan::GUIAdd( int id, const networkServer_t server ) {
idStr name = server.serverInfo.GetString( "si_name", GAME_NAME " Server" );
bool d3xp = false;
bool mod = false;if ( !idStr::Icmp( server.serverInfo.GetString( "fs_game" ), "d3xp" ) ||
!idStr::Icmp( server.serverInfo.GetString( "fs_game_base" ), "d3xp" ) ) {
d3xp = true;
}
if ( server.serverInfo.GetString( "fs_game" )[ 0 ] != '\0' ) {
mod = true;
}name += "\t";
if ( server.serverInfo.GetString( "sv_punkbuster" )[ 0 ] == '1' ) {
name += "mtr_PB";
}name += "\t";
if ( d3xp ) {
// FIXME: even for a 'D3XP mod'
// could have a specific icon for this case
name += "mtr_doom3XPIcon";
} else if ( mod ) {
name += "mtr_doom3Mod";
} else {
name += "mtr_doom3Icon";
}
name += "\t";
name += va( "%i/%i\t", server.clients, server.serverInfo.GetInt( "si_maxPlayers" ) );
name += ( server.ping > -1 ) ? va( "%i\t", server.ping ) : "na\t";
name += server.serverInfo.GetString( "si_gametype" );
name += "\t";
name += server.serverInfo.GetString( "si_mapName" );
name += "\t";
listGUI->Add( id, name );
}/*
================
idServerScan::ApplyFilter
================
*/
void idServerScan::ApplyFilter( ) {
int i;
networkServer_t serv;
idStr s;listGUI->SetStateChanges( false );
listGUI->Clear();
for ( i = m_sortAscending ? 0 : m_sortedServers.Num() - 1;
m_sortAscending ? i < m_sortedServers.Num() : i >= 0;
m_sortAscending ? i++ : i-- ) {
serv = (*this)[ m_sortedServers[ i ] ];
if ( !IsFiltered( serv ) ) {
GUIAdd( m_sortedServers[ i ], serv );
}
}
GUIUpdateSelected();
listGUI->SetStateChanges( true );
}/*
================
idServerScan::IsFiltered
================
*/
bool idServerScan::IsFiltered( const networkServer_t server ) {
int i;
const idKeyValue *keyval;// OS support filter
#if 0
// filter out pure servers that won't provide checksumed game code for client OS
keyval = server.serverInfo.FindKey( "si_pure" );
if ( keyval && !idStr::Cmp( keyval->GetValue(), "1" ) ) {
if ( ( server.OSMask & ( 1 << BUILD_OS_ID ) ) == 0 ) {
return true;
}
}
#else
if ( ( server.OSMask & ( 1 << BUILD_OS_ID ) ) == 0 ) {
return true;
}
#endif
// password filter
keyval = server.serverInfo.FindKey( "si_usePass" );
if ( keyval && gui_filter_password.GetInteger() == 1 ) {
// show passworded only
if ( keyval->GetValue()[ 0 ] == '0' ) {
return true;
}
} else if ( keyval && gui_filter_password.GetInteger() == 2 ) {
// show no password only
if ( keyval->GetValue()[ 0 ] != '0' ) {
return true;
}
}
// players filter
keyval = server.serverInfo.FindKey( "si_maxPlayers" );
if ( keyval ) {
if ( gui_filter_players.GetInteger() == 1 && server.clients == atoi( keyval->GetValue() ) ) {
return true;
} else if ( gui_filter_players.GetInteger() == 2 && ( !server.clients || server.clients == atoi( keyval->GetValue() ) ) ) {
return true;
}
}
// gametype filter
keyval = server.serverInfo.FindKey( "si_gameType" );
if ( keyval && gui_filter_gameType.GetInteger() ) {
i = 0;
while ( l_gameTypes[ i ] ) {
if ( !keyval->GetValue().Icmp( l_gameTypes[ i ] ) ) {
break;
}
i++;
}
if ( l_gameTypes[ i ] && i != gui_filter_gameType.GetInteger() -1 ) {
return true;
}
}
// idle server filter
keyval = server.serverInfo.FindKey( "si_idleServer" );
if ( keyval && !gui_filter_idle.GetInteger() ) {
if ( !keyval->GetValue().Icmp( "1" ) ) {
return true;
}
}// autofilter D3XP games if the user does not has the XP installed
if(!fileSystem->HasD3XP() && !idStr::Icmp(server.serverInfo.GetString( "fs_game" ), "d3xp")) {
return true;
}// filter based on the game doom or XP
if(gui_filter_game.GetInteger() == 1) { //Only Doom
if(idStr::Icmp(server.serverInfo.GetString("fs_game"), "")) {
return true;
}
} else if(gui_filter_game.GetInteger() == 2) { //Only D3XP
if(idStr::Icmp(server.serverInfo.GetString("fs_game"), "d3xp")) {
return true;
}
}return false;
}/*
================
idServerScan::Cmp
================
*/int idServerScan::Cmp( const int *a, const int *b ) {
networkServer_t serv1, serv2;
idStr s1, s2;
int ret;serv1 = (*l_serverScan)[ *a ];
serv2 = (*l_serverScan)[ *b ];
switch ( l_serverScan->m_sort ) {
case SORT_PING:
ret = serv1.ping < serv2.ping ? -1 : ( serv1.ping > serv2.ping ? 1 : 0 );
return ret;
case SORT_SERVERNAME:
serv1.serverInfo.GetString( "si_name", "", s1 );
serv2.serverInfo.GetString( "si_name", "", s2 );
return s1.IcmpNoColor( s2 );
case SORT_PLAYERS:
ret = serv1.clients < serv2.clients ? -1 : ( serv1.clients > serv2.clients ? 1 : 0 );
return ret;
case SORT_GAMETYPE:
serv1.serverInfo.GetString( "si_gameType", "", s1 );
serv2.serverInfo.GetString( "si_gameType", "", s2 );
return s1.Icmp( s2 );
case SORT_MAP:
serv1.serverInfo.GetString( "si_mapName", "", s1 );
serv2.serverInfo.GetString( "si_mapName", "", s2 );
return s1.Icmp( s2 );
case SORT_GAME:
serv1.serverInfo.GetString( "fs_game", "", s1 );
serv2.serverInfo.GetString( "fs_game", "", s2 );
return s1.Icmp( s2 );
}
return 0;
}/*
================
idServerScan::SetSorting
================
*/
void idServerScan::SetSorting( serverSort_t sort ) {
l_serverScan = this;
if ( sort == m_sort ) {
m_sortAscending = !m_sortAscending;
} else {
m_sort = sort;
m_sortAscending = true; // is the default for any new sort
m_sortedServers.Sort( idServerScan::Cmp );
}
// trigger a redraw
ApplyFilter();
}
void idServerScan::AddPreloadedServers() {
for (int i = 0; i < 30; i++) {
const char* srv = preloadedServers[i]->GetString();
if (!srv[0]) {
continue;
}
inServer_t s;
if (!Sys_StringToNetAdr(srv, &s.adr, false)) {
common->DPrintf("idServerScan::AddPreloadedServers: failed to parse server %s\n", srv);
continue;
}
if (!s.adr.port) {
s.adr.port = PORT_SERVER;
}
bool duplicate = false;
for (int j = 0; j < net_servers.Num(); j++) {
if (NetAdrEqual(net_servers[j].adr, s.adr)) {
duplicate = true;
break;
}
}
if (duplicate) {
common->DPrintf("idServerScan::AddPreloadedServers: duplicate server %s\n", srv);
continue;
}
s.id = 777 + i;
net_servers.Append(s);
common->DPrintf("idServerScan::AddPreloadedServers: added %s with id %d\n", Sys_NetAdrToString(s.adr), s.id);
}
}
Вы здесь » Форум Мапперов и Doom'еров » idTech 4 » Исходный код (Source Code)