diff --git a/engine/server/sv_master.c b/engine/server/sv_master.c index 4ec5fa012..410d2fa7b 100644 --- a/engine/server/sv_master.c +++ b/engine/server/sv_master.c @@ -30,6 +30,11 @@ //queryresponse: "getservers[Ext]Response\\aaaapp/aaaaaaaaaaaapp\\EOF" #define QUAKE3PROTOCOLNAME "Quake3" + +#define PREFIX_SECURE(issecure) ((issecure)?"🛡":"⚠️")//shield, vs yellow warning +#define PREFIX_NEEDPASS(needpass) (((needpass)&1)?"🔒":"") //padlock, vs no indicator. +#define PREFIX_COOP(iscoop) (((iscoop)&1)?"☮":"") //coop: peace sign, deathmatch:no indicator. + enum gametypes_e { GT_FFA=0, @@ -656,15 +661,85 @@ static int QDECL SVM_SortServerRule(const void *r1, const void *r2) return Q_strcasecmp(*(char*const*const)r1, *(char*const*const)r2); } -vfsfile_t *SVM_Generate_Serverinfo(const char **mimetype, const char *serveraddr, const char *query) +void SVM_Generate_ServerinfoEntry(vfsfile_t *f, const char *masteraddr, svm_server_t *server, const char *query) +{ + char tmpbuf[512]; + char hostname[1024]; + size_t u; + const char *url, *fp; + + VFS_PRINTF(f, "\n"); + VFS_PRINTF(f, "\n"); + QuakeCharsToHTML(hostname, sizeof(hostname), server->hostname, false); + + if (server->brokerid) + url=tmpbuf, Q_snprintfz(tmpbuf, sizeof(tmpbuf), "rtc://%s/%s", masteraddr, server->brokerid); + else + url = NET_AdrToString(tmpbuf, sizeof(tmpbuf), &server->adr); + fp = Info_ValueForKey(server->rules, "*fp"); + if (*fp) + fp = va("?fp=%s", Info_ValueForKey(server->rules, "*fp")); + if (server->game->scheme && !server->brokerid) + url = va("%s", server->game->scheme, url,fp, url); + + VFS_PRINTF(f, "\n", + server->game?server->game->name:"Unknown", query?"?":"", query?query:"", server->game?server->game->name:"Unknown", //game column + url, //address column + PREFIX_SECURE(server->secure), PREFIX_NEEDPASS(server->needpass), PREFIX_COOP(server->coop), hostname, //hostname column + server->gamedir, server->mapname, server->clients, server->maxclients); + VFS_PRINTF(f, "
GameAddressHostnameMod dirMapnamePlayers
%s%s%s%s%s%s%s%s%u/%u
\n"); + VFS_PRINTF(f, "
\n"); + + if (*server->rules) + { + struct rulelist_s rules; + rules.lines = rules.blobofs = 0; + Info_Enumerate(server->rules, &rules, SVM_GatherServerRule); + qsort(rules.line, rules.lines, sizeof(rules.line[0]), SVM_SortServerRule); + + //VFS_PRINTF(f, "\n"); + // VFS_PRINTF(f, ""); + //VFS_PRINTF(f, "
"); + VFS_PRINTF(f, "\n"); + VFS_PRINTF(f, "\n"); + for (u = 0; u < rules.lines; u++) + VFS_PUTS(f, rules.line[u]); + VFS_PRINTF(f, "
RuleValue
"); + // VFS_PRINTF(f, "
\n"); + VFS_PRINTF(f, "
\n"); + } +} +static svm_server_t *SVM_FindBrokerHost(const char *brokerid); +static vfsfile_t *SVM_Generate_RoomServerinfo(const char **mimetype, const char *masteraddr, const char *serveraddr, const char *query) +{ + vfsfile_t *f = VFSPIPE_Open(1, false); + svm_server_t *server = SVM_FindBrokerHost(serveraddr); + + VFS_PRINTF(f, "%s", master_css); + VFS_PRINTF(f, "

Single Server Info

\n"); + + if (server) + SVM_Generate_ServerinfoEntry(f, masteraddr, server, query); + else + { + VFS_PRINTF(f, "\n"); + VFS_PRINTF(f, "\n"); + VFS_PRINTF(f, "\n", serveraddr); + VFS_PRINTF(f, "
GameAddressHostnameMod dirMapnamePlayers
?%s????/?
\n"); + } + + *mimetype = "text/html"; + return f; +} +static vfsfile_t *SVM_Generate_AddrServerinfo(const char **mimetype, const char *masteraddr, const char *serveraddr, const char *query) { vfsfile_t *f = VFSPIPE_Open(1, false); char tmpbuf[512]; - char hostname[1024]; +// char hostname[1024]; svm_server_t *server; netadr_t adr[64]; - size_t count, u; - const char *url, *fp; + size_t count;//, u; +// const char *url, *fp; VFS_PRINTF(f, "%s", master_css); VFS_PRINTF(f, "

Single Server Info

\n"); @@ -675,45 +750,7 @@ vfsfile_t *SVM_Generate_Serverinfo(const char **mimetype, const char *serveraddr { server = SVM_GetServer(&adr[count]); if (server) - { - VFS_PRINTF(f, "\n"); - VFS_PRINTF(f, "\n"); - QuakeCharsToHTML(hostname, sizeof(hostname), server->hostname, false); - - url = NET_AdrToString(tmpbuf, sizeof(tmpbuf), &server->adr); - fp = Info_ValueForKey(server->rules, "*fp"); - if (*fp) - fp = va("?fp=%s", Info_ValueForKey(server->rules, "*fp")); - if (server->game->scheme && !server->brokerid) - url = va("%s", server->game->scheme, url,fp, url); - - VFS_PRINTF(f, "\n", - server->game?server->game->name:"Unknown", query?"?":"", query?query:"", server->game?server->game->name:"Unknown", //game column - url, //address column - server->secure?"🛡":"🚫", (server->needpass&1)?"🔒":"", (server->coop&1)?"🚸":"", hostname, //hostname column - server->gamedir, server->mapname, server->clients, server->maxclients); - VFS_PRINTF(f, "
GameAddressHostnameMod dirMapnamePlayers
%s%s%s%s%s%s%s%s%u/%u
\n"); - VFS_PRINTF(f, "
\n"); - - if (*server->rules) - { - struct rulelist_s rules; - rules.lines = rules.blobofs = 0; - Info_Enumerate(server->rules, &rules, SVM_GatherServerRule); - qsort(rules.line, rules.lines, sizeof(rules.line[0]), SVM_SortServerRule); - - //VFS_PRINTF(f, "\n"); - // VFS_PRINTF(f, ""); - //VFS_PRINTF(f, "
"); - VFS_PRINTF(f, "\n"); - VFS_PRINTF(f, "\n"); - for (u = 0; u < rules.lines; u++) - VFS_PUTS(f, rules.line[u]); - VFS_PRINTF(f, "
RuleValue
"); - // VFS_PRINTF(f, "
\n"); - VFS_PRINTF(f, "
\n"); - } - } + SVM_Generate_ServerinfoEntry(f, masteraddr, server, query); else { VFS_PRINTF(f, "\n"); @@ -732,7 +769,7 @@ vfsfile_t *SVM_Generate_Serverlist(const char **mimetype, const char *masteraddr vfsfile_t *f = VFSPIPE_Open(1, false); char tmpbuf[256]; char hostname[1024]; - const char *url, *infourl; + const char *url, *infourl, *preurl; svm_game_t *game; svm_server_t *server; unsigned clients=0,bots=0,specs=0; @@ -770,18 +807,20 @@ vfsfile_t *SVM_Generate_Serverlist(const char **mimetype, const char *masteraddr VFS_PRINTF(f, "\n"); for (server = game->firstserver; server; server = server->next) { + QuakeCharsToHTML(hostname, sizeof(hostname), server->hostname, false); if (server->brokerid) { url = tmpbuf; Q_snprintfz(tmpbuf, sizeof(tmpbuf), "rtc://%s/%s", masteraddr, server->brokerid); - infourl = tmpbuf; + infourl = server->brokerid; + preurl = "/room/"; } else { infourl = url = NET_AdrToString(tmpbuf, sizeof(tmpbuf), &server->adr); + preurl = "/server/"; } - QuakeCharsToHTML(hostname, sizeof(hostname), server->hostname, false); - VFS_PRINTF(f, "
%s%s%s%s%s%s%s%u", infourl, url, server->secure?"🛡":"🚫", (server->needpass&1)?"🔒":"", (server->coop&1)?"🚸":"", hostname, server->gamedir, server->mapname, server->clients); + VFS_PRINTF(f, "
%s%s%s%s%s%s%s%u", preurl,infourl, url, PREFIX_SECURE(server->secure), PREFIX_NEEDPASS(server->needpass), PREFIX_COOP(server->coop), hostname, server->gamedir, server->mapname, server->clients); if (server->bots) VFS_PRINTF(f, "+%ub", server->bots); VFS_PRINTF(f, "/%u", server->maxclients); @@ -853,7 +892,9 @@ vfsfile_t *SVM_GenerateIndex(const char *requesthost, const char *fname, const c if (!strcmp(fname, "index.html")) f = SVM_Generate_Gamelist(mimetype, query); else if (!strncmp(fname, "server/", 7)) - f = SVM_Generate_Serverinfo(mimetype, fname+7, query); + f = SVM_Generate_AddrServerinfo(mimetype, requesthost, fname+7, query); + else if (!strncmp(fname, "room/", 5)) + f = SVM_Generate_RoomServerinfo(mimetype, requesthost, fname+5, query); else if (!strncmp(fname, "game/", 5)) f = SVM_Generate_Serverlist(mimetype, requesthost, fname+5, query); else if (!strncmp(fname, "raw/", 4)) @@ -888,7 +929,7 @@ static svm_server_t *SVM_FindBrokerHost(const char *brokerid) while (server) { if (server->brokerid) //don't report brokered servers by address. - if (server->brokerid == brokerid) + if (!strcmp(server->brokerid, brokerid)) return server; server = Hash_GetNextKey(&svm.serverhash, key, server); } @@ -955,6 +996,14 @@ void SVM_AddBrokerGame(const char *brokerid, const char *info) server->protover = atoi(Info_ValueForKey(info, "protocol")); server->maxclients = atoi(Info_ValueForKey(info, "maxclients")); server->clients = atoi(Info_ValueForKey(info, "clients")); + server->secure = !!*Info_ValueForKey(info, "*fp"); + server->needpass = atoi(Info_ValueForKey(info, "needpass")); + server->coop = atoi(Info_ValueForKey(info, "coop")); + if (!server->coop) + { //deathmatch 0 also means coop 1... servers that report neither are probably annoying DP servers that report nothing useful and should default to DM. + const char *v = Info_ValueForKey(info, "deathmatch"); + server->coop = *v && !atoi(v); + } Q_strncpyz(server->hostname, Info_ValueForKey(info, "hostname"), sizeof(server->hostname)); Q_strncpyz(server->gamedir, Info_ValueForKey(info, "modname"), sizeof(server->gamedir)); Q_strncpyz(server->mapname, Info_ValueForKey(info, "mapname"), sizeof(server->mapname)); @@ -963,6 +1012,8 @@ void SVM_AddBrokerGame(const char *brokerid, const char *info) Q_strncpyz(server->version, Info_ValueForKey(info, "*version"), sizeof(server->version)); if (!*server->version) Q_strncpyz(server->version, Info_ValueForKey(info, "ver"), sizeof(server->version)); + + Q_strncpyz(server->rules, info, sizeof(server->rules)); } static svm_server_t *SVM_Heartbeat(const char *gamename, netadr_t *adr, int numclients, int numbots, int numspecs, double validuntil)