diff --git a/code/client/cl_instantAction.cpp b/code/client/cl_instantAction.cpp index cd5cf9fd..475a7774 100644 --- a/code/client/cl_instantAction.cpp +++ b/code/client/cl_instantAction.cpp @@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cl_ui.h" #include "cl_instantAction.h" #include "cl_uiserverlist.h" +#include "../gamespy/sv_gamespy.h" Event EV_UIInstantAction_AcceptServer ( @@ -68,24 +69,146 @@ CLASS_DECLARATION(UIWidget, UIInstantAction, NULL) { {NULL, NULL } }; +struct ServerListInstance { + int iServerType; + UIInstantAction *pServerList; +}; + +ServerListInstance g_IAServerListInst[2]; + UIInstantAction::UIInstantAction() { - // FIXME: unimplemented + state = IA_INITIALIZE; + numFoundServers = 0; + numServers = 0; + minPlayers = 3; + startingMaxPing = 100; + endingMaxPing = 1500; + maxServers = -1; + doneList[0] = false; + doneList[1] = false; + servers = 0; + serverList[0] = NULL; + serverList[1] = NULL; + + ReadIniFile(); + EnableServerInfo(false); + + menuManager.PassEventToWidget("ia_cancel_button", &EV_Widget_Disable); + menuManager.PassEventToWidget("ia_refresh_button", &EV_Widget_Disable); } UIInstantAction::~UIInstantAction() { - // FIXME: unimplemented + CleanUp(); } void UIInstantAction::CleanUp() { - // FIXME: unimplemented + if (serverList[0]) { + ServerListFree(serverList[0]); + serverList[0] = NULL; + } + + if (serverList[1]) { + ServerListFree(serverList[1]); + serverList[1] = NULL; + } + + if (servers) { + delete[] servers; + servers = NULL; + } } void UIInstantAction::Init() { - // FIXME: unimplemented + const char *secret_key; + const char *game_name; + + static const unsigned int iNumConcurrent = 10; + + numFoundServers = 0; + numServers = 0; + doneList[0] = false; + doneList[1] = false; + + EnableServerInfo(false); + + menuManager.PassEventToWidget("ia_cancel_button", &EV_Widget_Disable); + menuManager.PassEventToWidget("ia_refresh_button", &EV_Widget_Disable); + menuManager.PassEventToWidget("ia_noserverfound", &EV_Widget_Disable); + + Cvar_Set("ia_search_percentage", va("%d %%", 0)); + + if (com_target_game->integer < target_game_e::TG_MOHTT) { + g_IAServerListInst[0].iServerType = com_target_game->integer; + g_IAServerListInst[0].pServerList = this; + + game_name = GS_GetGameName(com_target_game->integer); + secret_key = GS_GetGameKey(com_target_game->integer); + + serverList[0] = ServerListNew( + game_name, + game_name, + secret_key, + iNumConcurrent, + (void *)&IAServerListCallBack, + 1, + (void *)&g_IAServerListInst[0] + ); + + ServerListClear(serverList[0]); + } else { + g_IAServerListInst[0].iServerType = target_game_e::TG_MOHTT; + g_IAServerListInst[0].pServerList = this; + + game_name = GS_GetGameName(target_game_e::TG_MOHTT); + secret_key = GS_GetGameKey(target_game_e::TG_MOHTT); + + serverList[0] = ServerListNew( + game_name, + game_name, + secret_key, + iNumConcurrent, + (void *)&IAServerListCallBack, + 1, + (void *)&g_IAServerListInst[0] + ); + + ServerListClear(serverList[0]); + + g_IAServerListInst[1].iServerType = target_game_e::TG_MOHTA; + g_IAServerListInst[1].pServerList = this; + + game_name = GS_GetGameName(target_game_e::TG_MOHTA); + secret_key = GS_GetGameKey(target_game_e::TG_MOHTA); + + serverList[1] = ServerListNew( + game_name, + game_name, + secret_key, + iNumConcurrent, + (void *)&IAServerListCallBack, + 1, + (void *)&g_IAServerListInst[1] + ); + + ServerListClear(serverList[1]); + } + + state = IA_WAITING; + numFoundServers = 0; + + ServerListUpdate(serverList[0], true); + + if (serverList[1]) { + ServerListUpdate(serverList[1], true); + } + + menuManager.PassEventToWidget("ia_cancel_button", &EV_Widget_Enable); + menuManager.PassEventToWidget("searchstatus", &EV_Widget_Enable); + menuManager.PassEventToWidget("searchstatuslable", &EV_Widget_Enable); } int UIInstantAction::GetServerIndex(int maxPing, int gameType) @@ -96,7 +219,48 @@ int UIInstantAction::GetServerIndex(int maxPing, int gameType) void UIInstantAction::ReadIniFile() { - // FIXME: unimplemented + char *buffer; + const char *p; + const char *pVal; + int intValue; + char value[32]; + + if (!FS_ReadFileEx("iaction.ini", (void **)&buffer, qtrue)) { + return; + } + + for (p = buffer; p; p = strstr(pVal, "\n")) { + if (!sscanf(p, "%32s", value)) { + break; + } + + pVal = strstr(p, "="); + if (!pVal) { + break; + } + + pVal++; + + if (!sscanf(pVal, "%d", &intValue)) { + break; + } + + if (!Q_stricmpn(value, "MinPlayers", 10)) { + minPlayers = intValue; + } + + if (!Q_stricmpn(value, "StartingMaxPing", 15)) { + startingMaxPing = intValue; + } + + if (!Q_stricmpn(value, "EndingMaxPing", 13)) { + endingMaxPing = intValue; + } + + if (!Q_stricmpn(value, "MaxServers", 10)) { + maxServers = intValue; + } + } } void UIInstantAction::FindServer() @@ -111,12 +275,33 @@ void UIInstantAction::Connect(Event *ev) void UIInstantAction::Reject(Event *ev) { - // FIXME: unimplemented + servers[currentServer].rejected = 1; + FindServer(); } void UIInstantAction::Draw() { - // FIXME: unimplemented + switch (state) { + case IA_INITIALIZE: + Init(); + break; + case IA_UPDATE: + Update(); + break; + case IA_FINISHED: + FindServer(); + break; + default: + break; + } + + if (serverList[0]) { + ServerListThink(serverList[0]); + } + + if (serverList[1]) { + ServerListThink(serverList[1]); + } } void UIInstantAction::Update() @@ -124,17 +309,105 @@ void UIInstantAction::Update() // FIXME: unimplemented } -void UIInstantAction::AddServer(GServer server, const ServerGame_t& serverGame) +int UIInstantAction::AddServer(GServer server, const ServerGame_t& serverGame) { - // FIXME: unimplemented + servers[numFoundServers].server = server; + servers[numFoundServers].serverGame = serverGame; + servers[numFoundServers].rejected = false; + numFoundServers++; + + return numFoundServers; } void UIInstantAction::CancelRefresh(Event *ev) { - // FIXME: unimplemented + state = IA_FINISHED; + ServerListHalt(serverList[0]); + ServerListHalt(serverList[1]); } void UIInstantAction::EnableServerInfo(bool enable) { - // FIXME: unimplemented + if (enable) { + menuManager.PassEventToWidget("iaservername_label", &EV_Widget_Enable); + menuManager.PassEventToWidget("ia_servername_field", &EV_Widget_Enable); + menuManager.PassEventToWidget("ia_ping_label", &EV_Widget_Enable); + menuManager.PassEventToWidget("ia_ping_field", &EV_Widget_Enable); + menuManager.PassEventToWidget("ia_gametype_label", &EV_Widget_Enable); + menuManager.PassEventToWidget("ia_gametype_field", &EV_Widget_Enable); + menuManager.PassEventToWidget("ia_players_label", &EV_Widget_Enable); + menuManager.PassEventToWidget("ia_players_field", &EV_Widget_Enable); + menuManager.PassEventToWidget("ia_maxplayers_label", &EV_Widget_Enable); + menuManager.PassEventToWidget("ia_maxplayers_field", &EV_Widget_Enable); + menuManager.PassEventToWidget("acceptserver", &EV_Widget_Enable); + menuManager.PassEventToWidget("rejectserver", &EV_Widget_Enable); + } else { + menuManager.PassEventToWidget("iaservername_label", &EV_Widget_Disable); + menuManager.PassEventToWidget("ia_servername_field", &EV_Widget_Disable); + menuManager.PassEventToWidget("ia_ping_label", &EV_Widget_Disable); + menuManager.PassEventToWidget("ia_ping_field", &EV_Widget_Disable); + menuManager.PassEventToWidget("ia_gametype_label", &EV_Widget_Disable); + menuManager.PassEventToWidget("ia_gametype_field", &EV_Widget_Disable); + menuManager.PassEventToWidget("ia_players_label", &EV_Widget_Disable); + menuManager.PassEventToWidget("ia_players_field", &EV_Widget_Disable); + menuManager.PassEventToWidget("ia_maxplayers_label", &EV_Widget_Disable); + menuManager.PassEventToWidget("ia_maxplayers_field", &EV_Widget_Disable); + menuManager.PassEventToWidget("acceptserver", &EV_Widget_Disable); + menuManager.PassEventToWidget("rejectserver", &EV_Widget_Disable); + } +} + +void UIInstantAction::IAServerListCallBack(GServerList serverlist, int msg, void *instance, void *param1, void *param2) +{ + const ServerListInstance *pInstance = (const ServerListInstance *)instance; + UIInstantAction *pServerList = pInstance->pServerList; + + if (msg == LIST_PROGRESS) { + if (pServerList->state == IA_WAITING) { + if (pInstance->iServerType == 2) { + pServerList->doneList[0] = 1; + } + if (pInstance->iServerType == 1) { + pServerList->doneList[1] = 1; + } + if (pServerList->doneList[0] && pServerList->doneList[1]) { + pServerList->state = IA_UPDATE; + } + } else if (pServerList->state == IA_SEARCHING) { + ServerGame_t serverGame; + serverGame.serverType = pInstance->iServerType; + const int serverIndex = pServerList->AddServer((GServer)param1, serverGame); + + Cvar_Set("ia_search_percentage", va("%d %%", 100 * serverIndex / pServerList->numServers)); + + if (pServerList->maxServers >= 0 && serverIndex >= pServerList->maxServers) { + pServerList->doneList[0] = true; + ServerListHalt(pServerList->serverList[0]); + + if (pServerList->serverList[1]) { + pServerList->doneList[1] = true; + ServerListHalt(pServerList->serverList[1]); + } + + pServerList->state = IA_FINISHED; + } + } + } else if (msg == LIST_STATECHANGED && ServerListState(serverlist) == GServerListState::sl_idle) { + if (pInstance->iServerType == com_target_game->integer) { + pServerList->doneList[0] = true; + } + + if (com_target_game->integer >= target_game_e::TG_MOHTT && pInstance->iServerType == target_game_e::TG_MOHTA) { + pServerList->doneList[1] = true; + } + + if (pServerList->doneList[0] && (!pServerList->serverList[1] || pServerList->doneList[1])) { + if (pServerList->state == IA_WAITING) { + pServerList->state = IA_UPDATE; + } + if (pServerList->state == IA_SEARCHING) { + pServerList->state = IA_FINISHED; + } + } + } } diff --git a/code/client/cl_instantAction.h b/code/client/cl_instantAction.h index 92aa206b..c588fe7f 100644 --- a/code/client/cl_instantAction.h +++ b/code/client/cl_instantAction.h @@ -20,16 +20,19 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ +// Added in 2.30 +// Instantly find a server matching common criterias + #pragma once #include "../gamespy/goaceng.h" typedef struct { - GServer server; int serverType; } ServerGame_t; typedef struct { + GServer server; ServerGame_t serverGame; bool rejected; } IAServer_t; @@ -62,10 +65,13 @@ public: void Reject(Event *ev); void Draw(); void Update(); - void AddServer(GServer server, const ServerGame_t& serverGame); + int AddServer(GServer server, const ServerGame_t& serverGame); void CancelRefresh(Event *ev); void EnableServerInfo(bool enable); +private: + static void IAServerListCallBack(GServerList serverlist, int msg, void* instance, void* param1, void* param2); + private: bool doneList[2]; GServerList serverList[2];