Ожидаемый контент:

...

Карты, моды, дополнения, утилиты...

...

... и другое

В разработке... (Внимание: это меню отображается некорректно на некоторых стилях форума)

DOOM 0.9.1282

Форум Мапперов и Doom'еров

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Форум Мапперов и Doom'еров » idTech 4 » Исходный код (Source Code)


Исходный код (Source Code)

Сообщений 1 страница 3 из 3

1

Тут будет тема, в которой можно писать всю движуху по сырцам дума третьего - изменению, доработке, обсуждению и прочее прочее.

Сам исходный код движка находится тут - GitHub

+2

2

В оригинальном движке по дефолту русская буква я (маленькая) в чате сетевой игры не вводится. Чтобы это исправить, нужно поправить EditWindow.cpp, находящийся в neo\ui. Изменение вносится в .exe, не в .dll.
В idEditWindow::HandleEvent в блоке if начинающемся на 212 строке нужно добавить:
if ( key == 255 ) {
text = text + '`';
cursorPos = len + 1;
return "";
}

:

Полный код скорректированного idEditWindow::HandleEvent

/*
=============
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;
}

+2

3

Добавляем net_usePreloadedServers

Нужно отредактировать ServerScan.h и ServerScan.cpp в neo\framework\async

Полный код ServerScan.h

#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 request

scan_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 order

idStr        screenshot;
int        challenge;    // challenge for current scan

int        endWaitTime;    // when to stop waiting on a port init

private:
void        LocalClear( );    // we need to clear some internal data as well

void        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__ */

Полный код ServerScan.cpp

#include "../../idlib/precompiled.h"
#pragma hdrstop

idCVar 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);
}
}

+1


Вы здесь » Форум Мапперов и Doom'еров » idTech 4 » Исходный код (Source Code)