26 #include "../../cl_shared.h"
27 #include "../cl_game.h"
28 #include "../../../shared/parse.h"
29 #include "../../ui/ui_data.h"
30 #include "../../../shared/infostring.h"
34 #define MAX_SERVERLIST 128
113 cgi->NET_StreamFree(s);
117 const int cmd = cgi->NET_ReadByte(
buf);
119 cgi->NET_StreamFree(s);
124 cgi->NET_ReadStringLine(
buf, str,
sizeof(str));
126 if (strncmp(str,
"info", 4) == 0) {
127 cgi->NET_ReadString(
buf, str,
sizeof(str));
140 }
else if (strncmp(str,
"print", 5) == 0) {
142 cgi->NET_ReadString(
buf, paramBuf,
sizeof(paramBuf));
145 cgi->NET_StreamFree(s);
157 cgi->Com_Printf(
"pinging failed [%s]:%s...\n", server->
node, server->
service);
162 cgi->NET_StreamSetData(s, server);
175 cgi->Com_Printf(
"%02i: [%s]:%s (pinged: %i)\n",
i, list->
node, list->
service, list->
pinged);
190 if (
Q_streq(serverList[
i].node, node) &&
Q_streq(serverList[
i].service, service))
193 OBJZERO(serverList[serverListLength]);
211 if (cgi->NET_ReadString(msg, str,
sizeof(str)) == 0) {
214 cgi->UI_ExecuteConfunc(
"multiplayer_playerNumber 0");
215 cgi->Com_DPrintf(
DEBUG_CLIENT,
"GAME_MP_ParseTeamInfoMessage: No teaminfo string\n");
229 while (cgi->NET_ReadString(msg, str,
sizeof(str)) > 0) {
238 cgi->LIST_AddString(&userList, user);
240 cgi->LIST_AddString(&userTeam,
va(
_(
"Team %d"), team));
242 cgi->LIST_AddString(&userTeam,
_(
"No team"));
244 cgi->UI_ExecuteConfunc(
"multiplayer_playerIsReady %i %i", cnt, isReady);
251 cgi->UI_ExecuteConfunc(
"multiplayer_playerNumber %i", cnt);
279 cgi->NET_ReadString(msg, str,
sizeof(str));
289 const char* users = strstr(str,
"\n");
290 if (users ==
nullptr) {
296 cgi->
Cvar_Set(
"mn_mappic",
"maps/shots/default");
298 cgi->
Cvar_Set(
"mn_server_need_password",
"1");
300 cgi->
Cvar_Set(
"mn_server_need_password",
"0");
303 cgi->
Cvar_Set(
"mn_server_ip",
"%s", hostname);
306 cgi->
Cvar_Set(
"mn_svmapname",
"%s", value);
309 const char* token =
buf;
315 if (!cgi->R_ImageExists(
"pics/maps/shots/%s", token)) {
317 cgi->
Cvar_Set(
"mn_mappic",
"maps/shots/%s", token);
338 if (users ==
nullptr)
340 const int team = atoi(token);
342 if (users ==
nullptr)
347 cgi->UI_PushWindow(
"serverinfo");
358 cgi->NET_StreamFree(s);
361 const int cmd = cgi->NET_ReadByte(
buf);
363 cgi->NET_StreamFree(s);
367 cgi->NET_ReadStringLine(
buf, str,
sizeof(str));
373 cgi->NET_StreamFree(s);
379 cgi->Com_Printf(
"Could not query masterserver\n");
383 const char* serverListBuf = responseBuf;
386 const char* token =
Com_Parse(&serverListBuf);
388 int num = atoi(token);
390 cgi->Com_DPrintf(
DEBUG_CLIENT,
"Too many servers: %i\n", num);
393 for (
int i = 0;
i < num;
i++) {
396 if (!*token || !serverListBuf) {
397 cgi->Com_Printf(
"Could not finish the masterserver response parsing\n");
404 if (token[0] ==
'\0' || !serverListBuf) {
405 cgi->Com_Printf(
"Could not finish the masterserver response parsing\n");
419 const char match[] =
"discovered";
420 if (len ==
sizeof(match) && memcmp(buf, match, len) == 0) {
423 cgi->NET_SockaddrToStrings(s, from, node,
sizeof(node), service,
sizeof(service));
435 const char* newBookmark;
437 if (cgi->Cmd_Argc() < 2) {
440 cgi->Com_Printf(
"Usage: %s <ip>\n", cgi->
Cmd_Argv(0));
449 if (bookmark[0] ==
'\0') {
455 cgi->UI_Popup(
_(
"Notice"),
"%s",
_(
"All bookmark slots are used - please removed unused entries and repeat this step"));
466 switch (cgi->Cmd_Argc()) {
476 if (selectedServer) {
477 host = selectedServer->
node;
478 port = selectedServer->
service;
490 cgi->Com_Printf(
"Could not connect to %s %s\n", host, port);
500 if (cgi->Cmd_Argc() < 2) {
501 cgi->Com_Printf(
"Usage: %s <num>\n", cgi->
Cmd_Argv(0));
504 const int num = atoi(cgi->
Cmd_Argv(1));
514 selectedServer = &serverList[
i];
515 cgi->Cbuf_AddText(
"server_info %s %s\n", serverList[
i].node, serverList[
i].service);
524 #define SERVERQUERYTIMEOUT 40000
533 selectedServer =
nullptr;
536 if (cgi->Cmd_Argc() == 2) {
541 cgi->Free(serverList[
i].node);
542 cgi->Free(serverList[
i].service);
545 serverListLength = 0;
552 if (!netDatagramSocket)
556 if (netDatagramSocket) {
557 const char buf[] =
"discover";
558 cgi->NET_DatagramBroadcast(netDatagramSocket, buf,
sizeof(buf),
PORT_SERVER);
584 {
nullptr,
nullptr,
nullptr}
592 cl_serverlist = cgi->
Cvar_Get(
"cl_serverlist",
"0",
CVAR_ARCHIVE,
"0=show all, 1=hide full - servers on the serverlist");
594 cgi->Cmd_TableAddList(serverListCmds);
599 cgi->Cmd_TableRemoveList(serverListCmds);
601 cgi->NET_DatagramSocketClose(netDatagramSocket);
602 netDatagramSocket =
nullptr;
bool Q_strnull(const char *string)
serverList_t * selectedServer
static void GAME_MP_PrintServerList_f(void)
Prints all the servers on the list to game console.
static const cgame_import_t * cgi
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
static void GAME_MP_ServerListClick_f(void)
Callback for bookmark nodes in multiplayer menu (mp_bookmarks)
static int serverListLength
This is a cvar definition. Cvars can be user modified and used in our menus e.g.
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Serverlist menu callbacks headers for multiplayer.
static void GAME_MP_ServerInfo_f(void)
static bool GAME_MP_ShowServer(const serverList_t *server)
Perform the server filtering.
static void GAME_MP_PingServerCallback(struct net_stream *s)
char *IMPORT * GAME_StrDup(const char *string)
static void GAME_MP_ServerInfoCallback(struct net_stream *s)
static void GAME_MP_QueryMasterServerThread(const char *responseBuf, void *userdata)
static char userInfoText[256]
static void GAME_MP_ServerListDiscoveryCallback(struct datagram_socket *s, const char *buf, int len, struct sockaddr *from)
static void GAME_MP_PingServer(serverList_t *server)
Pings all servers in serverList.
static void GAME_MP_BookmarkAdd_f(void)
Add a new bookmark.
static cvar_t * cl_serverlist
const char *IMPORT * Cvar_GetString(const char *varName)
static serverList_t serverList[MAX_SERVERLIST]
const char * Info_ValueForKey(const char *s, const char *key)
Searches the string for the given key and returns the associated value, or an empty string...
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
cvar_t *IMPORT * Cvar_Set(const char *varName, const char *value,...) __attribute__((format(__printf__
dbuffer *IMPORT * NET_ReadMsg(struct net_stream *s)
Serverlist management headers for multiplayer.
char sv_hostname[MAX_OSPATH]
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
cvar_t *IMPORT * Cvar_Get(const char *varName, const char *value, int flags, const char *desc)
const char *IMPORT * NET_StreamPeerToName(struct net_stream *s, char *dst, int len, bool appendPort)
struct net_stream *IMPORT * NET_Connect(const char *node, const char *service, stream_onclose_func *onclose)
#define SERVERQUERYTIMEOUT
void *IMPORT * NET_StreamGetData(struct net_stream *s)
void GAME_MP_ParseTeamInfoMessage(dbuffer *msg)
Team selection text.
const char * Com_Parse(const char *data_p[], char *target, size_t size, bool replaceWhitespaces)
Parse a token out of a string.
static char serverInfoText[1024]
void GAME_MP_ServerListShutdown(void)
QGL_EXTERN GLuint GLchar GLuint * len
static void GAME_MP_AddServerToList(const char *node, const char *service)
Adds a server to the serverlist cache.
static void GAME_MP_ParseServerInfoMessage(dbuffer *msg, const char *hostname)
Serverbrowser text.
struct datagram_socket *IMPORT * NET_DatagramSocketNew(const char *node, const char *service, datagram_callback_func *func)
void GAME_MP_PingServers_f(void)
The first function called when entering the multiplayer menu, then CL_Frame takes over...
static bool GAME_MP_ProcessPingReply(serverList_t *server, const char *msg)
Parsed the server ping response.
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
static bool serversAlreadyQueried
static char serverText[1024]
static int lastServerQuery
void GAME_MP_ServerListInit(const cgame_import_t *import)
static struct datagram_socket * netDatagramSocket
static const cmdList_t serverListCmds[]
const char *IMPORT * Cmd_Argv(int n)
const char * Info_BoolForKey(const char *s, const char *key)
int Info_IntegerForKey(const char *s, const char *key)