mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-22 20:11:44 +00:00
Prevent FTE servers from getting mistreated as NQ servers, this should restore the 'observe' option.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6294 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
ce8155f8a1
commit
62e8bb5774
11 changed files with 146 additions and 67 deletions
|
@ -493,7 +493,7 @@ void CL_ConnectToDarkPlaces(char *challenge, netadr_t *adr)
|
||||||
|
|
||||||
connectinfo.time = realtime; // for retransmit requests
|
connectinfo.time = realtime; // for retransmit requests
|
||||||
|
|
||||||
Q_snprintfz(data, sizeof(data), "%c%c%c%cconnect\\protocol\\darkplaces 3\\protocols\\DP7 DP6 DP5 RMQ FITZ NEHAHRABJP2 NEHAHRABJP NEHAHRABJP3 QUAKE\\challenge\\%s\\name\\%s", 255, 255, 255, 255, challenge, name.string);
|
Q_snprintfz(data, sizeof(data), "%c%c%c%cconnect\\protocol\\darkplaces "STRINGIFY(NQ_NETCHAN_VERSION)"\\protocols\\DP7 DP6 DP5 RMQ FITZ NEHAHRABJP2 NEHAHRABJP NEHAHRABJP3 QUAKE\\challenge\\%s\\name\\%s", 255, 255, 255, 255, challenge, name.string);
|
||||||
|
|
||||||
NET_SendPacket (cls.sockets, strlen(data), data, adr);
|
NET_SendPacket (cls.sockets, strlen(data), data, adr);
|
||||||
|
|
||||||
|
@ -1160,7 +1160,7 @@ void CL_CheckForResend (void)
|
||||||
else if (1)
|
else if (1)
|
||||||
{
|
{
|
||||||
net_from = connectinfo.adr[connectinfo.nextadr];
|
net_from = connectinfo.adr[connectinfo.nextadr];
|
||||||
Q_snprintfz(net_message.data, net_message.maxsize, "xxxxconnect\\protocol\\darkplaces 3\\protocols\\DP7 DP6 DP5 RMQ FITZ NEHAHRABJP2 NEHAHRABJP NEHAHRABJP3 QUAKE\\challenge\\0x%x\\name\\%s", SV_NewChallenge(), name.string);
|
Q_snprintfz(net_message.data, net_message.maxsize, "xxxxconnect\\protocol\\darkplaces "STRINGIFY(NQ_NETCHAN_VERSION)"\\protocols\\DP7 DP6 DP5 RMQ FITZ NEHAHRABJP2 NEHAHRABJP NEHAHRABJP3 QUAKE\\challenge\\0x%x\\name\\%s", SV_NewChallenge(), name.string);
|
||||||
Cmd_TokenizeString (net_message.data+4, false, false);
|
Cmd_TokenizeString (net_message.data+4, false, false);
|
||||||
SVC_DirectConnect(0);
|
SVC_DirectConnect(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,17 +22,18 @@ enum masterprotocol_e
|
||||||
#define SS_UNKNOWN 0
|
#define SS_UNKNOWN 0
|
||||||
#define SS_QUAKEWORLD 1
|
#define SS_QUAKEWORLD 1
|
||||||
#define SS_NETQUAKE 2
|
#define SS_NETQUAKE 2
|
||||||
#define SS_DARKPLACES 3
|
#define SS_QUAKE2 3
|
||||||
#define SS_QUAKE2 4
|
#define SS_QUAKE3 4
|
||||||
#define SS_QUAKE3 5
|
#define SS_QEPROT 5 //needs dtls and a different ccreq version
|
||||||
//#define SS_UNUSED 6
|
//#define SS_UNUSED 6
|
||||||
//#define SS_UNUSED 7
|
//#define SS_UNUSED 7
|
||||||
|
|
||||||
#define SS_LOCAL (1<<3u) //local servers are ones we detected without being listed on a master server (masters will report public ips, so these may appear as dupes if they're also public)
|
#define SS_LOCAL (1<<3u) //local servers are ones we detected without being listed on a master server (masters will report public ips, so these may appear as dupes if they're also public)
|
||||||
#define SS_FTESERVER (1<<4u) //hehehe...
|
#define SS_FTESERVER (1<<4u) //just highlighting differences, to give some impression of superiority.
|
||||||
#define SS_FAVORITE (1<<5u) //filter all others.
|
#define SS_FAVORITE (1<<5u) //filter all others.
|
||||||
#define SS_KEEPINFO (1<<6u)
|
#define SS_KEEPINFO (1<<6u)
|
||||||
#define SS_PROXY (1<<7u)
|
#define SS_GETINFO (1<<7u) //explicitly query via getinfo
|
||||||
|
#define SS_PROXY (1<<8u) //qizmo/qwfwd/qtv/eztv
|
||||||
|
|
||||||
#define PING_DEAD 0xffff //default ping value to denote servers that are not responding.
|
#define PING_DEAD 0xffff //default ping value to denote servers that are not responding.
|
||||||
#define PING_UNKNOWN 0xfffe //these servers are considered up, but we can't query them directly so can't determine the final ping from here.
|
#define PING_UNKNOWN 0xfffe //these servers are considered up, but we can't query them directly so can't determine the final ping from here.
|
||||||
|
|
|
@ -145,7 +145,7 @@ static void SL_TitlesDraw (int x, int y, menucustom_t *ths, emenu_t *menu)
|
||||||
else
|
else
|
||||||
clr = 'B';
|
clr = 'B';
|
||||||
x = ths->common.width;
|
x = ths->common.width;
|
||||||
if (mx > x || mousecursor_y < y || mousecursor_y >= y+8)
|
if ((mx > x || mousecursor_y < y || mousecursor_y >= y+8) && !serverpreview)
|
||||||
filldraw = true;
|
filldraw = true;
|
||||||
if (sb_showtimelimit.value) {SL_DrawColumnTitle(&x, y, 3*8, mx, "tl", (sf==SLKEY_TIMELIMIT), clr, &filldraw);}
|
if (sb_showtimelimit.value) {SL_DrawColumnTitle(&x, y, 3*8, mx, "tl", (sf==SLKEY_TIMELIMIT), clr, &filldraw);}
|
||||||
if (sb_showfraglimit.value) {SL_DrawColumnTitle(&x, y, 3*8, mx, "fl", (sf==SLKEY_FRAGLIMIT), clr, &filldraw);}
|
if (sb_showfraglimit.value) {SL_DrawColumnTitle(&x, y, 3*8, mx, "fl", (sf==SLKEY_FRAGLIMIT), clr, &filldraw);}
|
||||||
|
@ -268,8 +268,9 @@ static servertypes_t flagstoservertype(int flags)
|
||||||
|
|
||||||
switch(flags & SS_PROTOCOLMASK)
|
switch(flags & SS_PROTOCOLMASK)
|
||||||
{
|
{
|
||||||
|
case SS_QEPROT:
|
||||||
|
return ST_NETQUAKE;
|
||||||
case SS_NETQUAKE:
|
case SS_NETQUAKE:
|
||||||
case SS_DARKPLACES:
|
|
||||||
return ST_NETQUAKE;
|
return ST_NETQUAKE;
|
||||||
case SS_QUAKE2:
|
case SS_QUAKE2:
|
||||||
return ST_QUAKE2;
|
return ST_QUAKE2;
|
||||||
|
@ -308,7 +309,7 @@ static void SL_ServerDraw (int x, int y, menucustom_t *ths, emenu_t *menu)
|
||||||
serverhighlight[(int)stype][2],
|
serverhighlight[(int)stype][2],
|
||||||
1.0));
|
1.0));
|
||||||
}
|
}
|
||||||
else if (thisone == info->scrollpos + (int)(mousecursor_y-info->servers_top)/8 && mousecursor_x < x)
|
else if (thisone == info->scrollpos + (int)(mousecursor_y-info->servers_top)/8 && mousecursor_x < x && !serverpreview)
|
||||||
R2D_ImageColours(SRGBA((sin(realtime*4.4)*0.25)+0.5, (sin(realtime*4.4)*0.25)+0.5, 0.08, sb_alpha.value));
|
R2D_ImageColours(SRGBA((sin(realtime*4.4)*0.25)+0.5, (sin(realtime*4.4)*0.25)+0.5, 0.08, sb_alpha.value));
|
||||||
else if (selectedserver.inuse && NET_CompareAdr(&si->adr, &selectedserver.adr) && !strcmp(si->brokerid, selectedserver.brokerid))
|
else if (selectedserver.inuse && NET_CompareAdr(&si->adr, &selectedserver.adr) && !strcmp(si->brokerid, selectedserver.brokerid))
|
||||||
R2D_ImageColours(SRGBA(((sin(realtime*4.4)*0.25)+0.5) * 0.5, ((sin(realtime*4.4)*0.25)+0.5)*0.5, 0.08*0.5, sb_alpha.value));
|
R2D_ImageColours(SRGBA(((sin(realtime*4.4)*0.25)+0.5) * 0.5, ((sin(realtime*4.4)*0.25)+0.5)*0.5, 0.08*0.5, sb_alpha.value));
|
||||||
|
@ -852,9 +853,11 @@ dojoin:
|
||||||
}
|
}
|
||||||
|
|
||||||
//which connect command are we using?
|
//which connect command are we using?
|
||||||
if ((server->special & SS_PROTOCOLMASK) == SS_NETQUAKE)
|
#ifdef NQPROT
|
||||||
Cbuf_AddText("nqconnect ", RESTRICT_LOCAL);
|
if ((server->special & SS_PROTOCOLMASK) == SS_QEPROT)
|
||||||
|
Cbuf_AddText("connectqe ", RESTRICT_LOCAL);
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
Cbuf_AddText("connect ", RESTRICT_LOCAL);
|
Cbuf_AddText("connect ", RESTRICT_LOCAL);
|
||||||
|
|
||||||
//output the server's address
|
//output the server's address
|
||||||
|
@ -1108,7 +1111,6 @@ static void CalcFilters(emenu_t *menu)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (info->filter[SLFILTER_HIDENETQUAKE]) Master_SetMaskInteger(false, SLKEY_BASEGAME, SS_NETQUAKE, SLIST_TEST_NOTEQUAL);
|
if (info->filter[SLFILTER_HIDENETQUAKE]) Master_SetMaskInteger(false, SLKEY_BASEGAME, SS_NETQUAKE, SLIST_TEST_NOTEQUAL);
|
||||||
if (info->filter[SLFILTER_HIDENETQUAKE]) Master_SetMaskInteger(false, SLKEY_BASEGAME, SS_DARKPLACES, SLIST_TEST_NOTEQUAL);
|
|
||||||
if (info->filter[SLFILTER_HIDEQUAKEWORLD]) Master_SetMaskInteger(false, SLKEY_BASEGAME, SS_QUAKEWORLD, SLIST_TEST_NOTEQUAL);
|
if (info->filter[SLFILTER_HIDEQUAKEWORLD]) Master_SetMaskInteger(false, SLKEY_BASEGAME, SS_QUAKEWORLD, SLIST_TEST_NOTEQUAL);
|
||||||
}
|
}
|
||||||
if (info->filter[SLFILTER_HIDEPROXIES]) Master_SetMaskInteger(false, SLKEY_FLAGS, SS_PROXY, SLIST_TEST_NOTCONTAIN);
|
if (info->filter[SLFILTER_HIDEPROXIES]) Master_SetMaskInteger(false, SLKEY_FLAGS, SS_PROXY, SLIST_TEST_NOTCONTAIN);
|
||||||
|
@ -1351,9 +1353,11 @@ static void M_QuickConnect_PreDraw(emenu_t *menu)
|
||||||
{
|
{
|
||||||
Con_Printf("Quick connect found %s (gamedir %s, players %i/%i/%i, ping %ims)\n", best->name, best->gamedir, best->numhumans, best->players, best->maxplayers, best->ping);
|
Con_Printf("Quick connect found %s (gamedir %s, players %i/%i/%i, ping %ims)\n", best->name, best->gamedir, best->numhumans, best->players, best->maxplayers, best->ping);
|
||||||
|
|
||||||
if ((best->special & SS_PROTOCOLMASK) == SS_NETQUAKE)
|
#ifdef NQPROT
|
||||||
Cbuf_AddText(va("nqconnect %s\n", Master_ServerToString(adr, sizeof(adr), best)), RESTRICT_LOCAL);
|
if ((best->special & SS_PROTOCOLMASK) == SS_QEPROT)
|
||||||
|
Cbuf_AddText(va("connectqe %s\n", Master_ServerToString(adr, sizeof(adr), best)), RESTRICT_LOCAL);
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
Cbuf_AddText(va("join %s\n", Master_ServerToString(adr, sizeof(adr), best)), RESTRICT_LOCAL);
|
Cbuf_AddText(va("join %s\n", Master_ServerToString(adr, sizeof(adr), best)), RESTRICT_LOCAL);
|
||||||
|
|
||||||
M_ToggleMenu_f();
|
M_ToggleMenu_f();
|
||||||
|
|
|
@ -1039,8 +1039,6 @@ char *Master_ServerToString (char *s, int len, serverinfo_t *a)
|
||||||
static int Master_BaseGame(serverinfo_t *a)
|
static int Master_BaseGame(serverinfo_t *a)
|
||||||
{
|
{
|
||||||
int prot = a->special&SS_PROTOCOLMASK;
|
int prot = a->special&SS_PROTOCOLMASK;
|
||||||
if (prot == SS_DARKPLACES && (a->special&SS_FTESERVER))
|
|
||||||
prot = SS_QUAKEWORLD;
|
|
||||||
return prot;
|
return prot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2256,32 +2254,32 @@ void Master_CheckPollSockets(void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef Q3CLIENT
|
//#ifdef Q3CLIENT
|
||||||
if (!strcmp(s, "statusResponse"))
|
if (!strcmp(s, "statusResponse"))
|
||||||
{
|
{
|
||||||
CL_ReadServerInfo(MSG_ReadString(), MP_QUAKE3, false);
|
CL_ReadServerInfo(MSG_ReadString(), MP_QUAKE3, false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
//#endif
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
if (!strncmp(s, "getserversResponse6", 19) && (s[19] == '\\' || s[19] == '/')) //parse a bit more...
|
if (!strncmp(s, "getserversResponse6", 19) && (s[19] == '\\' || s[19] == '/')) //parse a bit more...
|
||||||
{
|
{
|
||||||
net_message.currentbit = (c+19-1)<<3;
|
net_message.currentbit = (c+19-1)<<3;
|
||||||
CL_MasterListParse(NA_IPV6, SS_DARKPLACES, true);
|
CL_MasterListParse(NA_IPV6, SS_GETINFO, true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!strncmp(s, "getserversExtResponse", 21) && (s[21] == '\\' || s[21] == '/')) //parse a bit more...
|
if (!strncmp(s, "getserversExtResponse", 21) && (s[21] == '\\' || s[21] == '/')) //parse a bit more...
|
||||||
{
|
{
|
||||||
net_message.currentbit = (c+21-1)<<3;
|
net_message.currentbit = (c+21-1)<<3;
|
||||||
CL_MasterListParse(NA_IP, SS_DARKPLACES, true);
|
CL_MasterListParse(NA_IP, SS_GETINFO, true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strncmp(s, "getserversResponse", 18) && (s[18] == '\\' || s[18] == '/')) //parse a bit more...
|
if (!strncmp(s, "getserversResponse", 18) && (s[18] == '\\' || s[18] == '/')) //parse a bit more...
|
||||||
{
|
{
|
||||||
net_message.currentbit = (c+18-1)<<3;
|
net_message.currentbit = (c+18-1)<<3;
|
||||||
CL_MasterListParse(NA_IP, SS_DARKPLACES, true);
|
CL_MasterListParse(NA_IP, SS_GETINFO, true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(s, "infoResponse")) //parse a bit more...
|
if (!strcmp(s, "infoResponse")) //parse a bit more...
|
||||||
|
@ -2495,7 +2493,7 @@ void SListOptionChanged(serverinfo_t *newserver)
|
||||||
#if defined(NQPROT)
|
#if defined(NQPROT)
|
||||||
selectedserver.lastplayer = 0;
|
selectedserver.lastplayer = 0;
|
||||||
*selectedserver.lastrule = 0;
|
*selectedserver.lastrule = 0;
|
||||||
if ((newserver->special&SS_PROTOCOLMASK) == SS_NETQUAKE)
|
if ((newserver->special&(SS_PROTOCOLMASK|SS_GETINFO)) == SS_NETQUAKE)
|
||||||
{ //start spamming the server to get all of its details. silly protocols.
|
{ //start spamming the server to get all of its details. silly protocols.
|
||||||
SZ_Clear(&net_message);
|
SZ_Clear(&net_message);
|
||||||
net_message.packing = SZ_RAWBYTES;
|
net_message.packing = SZ_RAWBYTES;
|
||||||
|
@ -2646,7 +2644,7 @@ static void MasterInfo_ProcessHTTP(struct dl_download *dl)
|
||||||
if (protocoltype == MP_QUAKEWORLD)
|
if (protocoltype == MP_QUAKEWORLD)
|
||||||
info->special |= SS_QUAKEWORLD;
|
info->special |= SS_QUAKEWORLD;
|
||||||
else if (protocoltype == MP_DPMASTER)
|
else if (protocoltype == MP_DPMASTER)
|
||||||
info->special |= SS_DARKPLACES;
|
info->special |= SS_GETINFO;
|
||||||
#if defined(Q2CLIENT) || defined(Q2SERVER)
|
#if defined(Q2CLIENT) || defined(Q2SERVER)
|
||||||
else if (protocoltype == MP_QUAKE2)
|
else if (protocoltype == MP_QUAKE2)
|
||||||
info->special |= SS_QUAKE2;
|
info->special |= SS_QUAKE2;
|
||||||
|
@ -2925,16 +2923,17 @@ void Master_QueryServer(serverinfo_t *server)
|
||||||
return; //don't even try. we have no direct route.
|
return; //don't even try. we have no direct route.
|
||||||
server->refreshtime = Sys_DoubleTime();
|
server->refreshtime = Sys_DoubleTime();
|
||||||
|
|
||||||
switch(server->special & SS_PROTOCOLMASK)
|
if (server->special & SS_GETINFO)
|
||||||
{
|
{
|
||||||
case SS_QUAKE3:
|
|
||||||
Q_snprintfz(data, sizeof(data), "%c%c%c%cgetstatus", 255, 255, 255, 255);
|
|
||||||
break;
|
|
||||||
case SS_DARKPLACES:
|
|
||||||
if (server->moreinfo)
|
if (server->moreinfo)
|
||||||
Q_snprintfz(data, sizeof(data), "%c%c%c%cgetstatus", 255, 255, 255, 255);
|
Q_snprintfz(data, sizeof(data), "%c%c%c%cgetstatus", 255, 255, 255, 255);
|
||||||
else
|
else
|
||||||
Q_snprintfz(data, sizeof(data), "%c%c%c%cgetinfo", 255, 255, 255, 255);
|
Q_snprintfz(data, sizeof(data), "%c%c%c%cgetinfo", 255, 255, 255, 255);
|
||||||
|
}
|
||||||
|
else switch(server->special & SS_PROTOCOLMASK)
|
||||||
|
{
|
||||||
|
case SS_QUAKE3:
|
||||||
|
Q_snprintfz(data, sizeof(data), "%c%c%c%cgetstatus", 255, 255, 255, 255);
|
||||||
break;
|
break;
|
||||||
#ifdef NQPROT
|
#ifdef NQPROT
|
||||||
case SS_NETQUAKE:
|
case SS_NETQUAKE:
|
||||||
|
@ -3028,14 +3027,13 @@ qboolean CL_QueryServers(void)
|
||||||
while(server)
|
while(server)
|
||||||
{
|
{
|
||||||
qboolean enabled;
|
qboolean enabled;
|
||||||
switch(server->special & SS_PROTOCOLMASK)
|
switch(Master_BaseGame(server))
|
||||||
{
|
{
|
||||||
case SS_UNKNOWN: enabled = true; break;
|
case SS_UNKNOWN: enabled = true; break;
|
||||||
case SS_QUAKE3: enabled = sb_enablequake3; break;
|
case SS_QUAKE3: enabled = sb_enablequake3; break;
|
||||||
case SS_QUAKE2: enabled = sb_enablequake2; break;
|
case SS_QUAKE2: enabled = sb_enablequake2; break;
|
||||||
case SS_NETQUAKE: enabled = sb_enablenetquake; break;
|
case SS_NETQUAKE: enabled = sb_enablenetquake; break;
|
||||||
case SS_QUAKEWORLD: enabled = sb_enablequakeworld; break;
|
case SS_QUAKEWORLD: enabled = sb_enablequakeworld; break;
|
||||||
case SS_DARKPLACES: enabled = sb_enabledarkplaces; break;
|
|
||||||
default: enabled = false; break;
|
default: enabled = false; break;
|
||||||
}
|
}
|
||||||
if (enabled)
|
if (enabled)
|
||||||
|
@ -3057,14 +3055,13 @@ qboolean CL_QueryServers(void)
|
||||||
while (server)
|
while (server)
|
||||||
{
|
{
|
||||||
qboolean enabled;
|
qboolean enabled;
|
||||||
switch(server->special & SS_PROTOCOLMASK)
|
switch(Master_BaseGame(server))
|
||||||
{
|
{
|
||||||
case SS_UNKNOWN: enabled = true; break;
|
case SS_UNKNOWN: enabled = true; break;
|
||||||
case SS_QUAKE3: enabled = sb_enablequake3; break;
|
case SS_QUAKE3: enabled = sb_enablequake3; break;
|
||||||
case SS_QUAKE2: enabled = sb_enablequake2; break;
|
case SS_QUAKE2: enabled = sb_enablequake2; break;
|
||||||
case SS_NETQUAKE: enabled = sb_enablenetquake; break;
|
case SS_NETQUAKE: enabled = sb_enablenetquake; break;
|
||||||
case SS_QUAKEWORLD: enabled = sb_enablequakeworld; break;
|
case SS_QUAKEWORLD: enabled = sb_enablequakeworld; break;
|
||||||
case SS_DARKPLACES: enabled = sb_enabledarkplaces; break;
|
|
||||||
default: enabled = false; break;
|
default: enabled = false; break;
|
||||||
}
|
}
|
||||||
if (enabled)
|
if (enabled)
|
||||||
|
@ -3241,38 +3238,54 @@ static int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolea
|
||||||
if (!*name)
|
if (!*name)
|
||||||
name = Info_ValueForKey(msg, "sv_hostname");
|
name = Info_ValueForKey(msg, "sv_hostname");
|
||||||
Q_strncpyz(info->name, name, sizeof(info->name));
|
Q_strncpyz(info->name, name, sizeof(info->name));
|
||||||
info->special = info->special & (SS_FAVORITE | SS_KEEPINFO | SS_LOCAL); //favorite+local is never cleared
|
info->special = info->special & (SS_FAVORITE | SS_KEEPINFO | SS_LOCAL | SS_GETINFO); //favorite+local is never cleared
|
||||||
if (!strcmp(DISTRIBUTION, Info_ValueForKey(msg, "*distrib"))) //outdated
|
if (!strcmp(DISTRIBUTION, Info_ValueForKey(msg, "*distrib"))) //outdated
|
||||||
info->special |= SS_FTESERVER;
|
info->special |= SS_FTESERVER;
|
||||||
else if (!strncmp(DISTRIBUTION, Info_ValueForKey(msg, "*version"), strlen(DISTRIBUTION)))
|
else if (!strncmp(DISTRIBUTION, Info_ValueForKey(msg, "*version"), strlen(DISTRIBUTION)))
|
||||||
info->special |= SS_FTESERVER;
|
info->special |= SS_FTESERVER;
|
||||||
|
|
||||||
info->protocol = atoi(Info_ValueForKey(msg, "protocol"));
|
info->protocol = strtoul(Info_ValueForKey(msg, "protocol"), &token, 0);
|
||||||
info->special &= ~SS_PROTOCOLMASK;
|
|
||||||
if (info->protocol)
|
if (info->protocol)
|
||||||
{
|
{
|
||||||
switch(info->protocol)
|
switch(info->protocol)
|
||||||
{
|
{
|
||||||
case PROTOCOL_VERSION_QW: info->special = SS_QUAKEWORLD; break;
|
case PROTOCOL_VERSION_QW: info->special |= SS_QUAKEWORLD; break;
|
||||||
#ifdef NQPROT
|
#ifdef NQPROT
|
||||||
case PROTOCOL_VERSION_NQ: info->special = SS_NETQUAKE; break;
|
case PROTOCOL_VERSION_NQ: info->special |= SS_NETQUAKE; break;
|
||||||
case PROTOCOL_VERSION_H2: info->special = SS_NETQUAKE; break; //erk
|
case PROTOCOL_VERSION_H2: info->special |= SS_NETQUAKE; break; //erk
|
||||||
case PROTOCOL_VERSION_NEHD: info->special = SS_NETQUAKE; break;
|
case PROTOCOL_VERSION_NEHD: info->special |= SS_NETQUAKE; break;
|
||||||
case PROTOCOL_VERSION_FITZ: info->special = SS_NETQUAKE; break;
|
case PROTOCOL_VERSION_FITZ: info->special |= SS_NETQUAKE; break;
|
||||||
case PROTOCOL_VERSION_RMQ: info->special = SS_NETQUAKE; break;
|
case PROTOCOL_VERSION_RMQ: info->special |= SS_NETQUAKE; break;
|
||||||
case PROTOCOL_VERSION_DP5: info->special = SS_DARKPLACES; break; //dp actually says 3... but hey, that's dp being WEIRD.
|
case PROTOCOL_VERSION_DP5: info->special |= SS_NETQUAKE; break; //dp actually says 3... but hey, that's dp being WEIRD.
|
||||||
case PROTOCOL_VERSION_DP6: info->special = SS_DARKPLACES; break;
|
case PROTOCOL_VERSION_DP6: info->special |= SS_NETQUAKE; break;
|
||||||
case PROTOCOL_VERSION_DP7: info->special = SS_DARKPLACES; break;
|
case PROTOCOL_VERSION_DP7: info->special |= SS_NETQUAKE; break;
|
||||||
|
case NQ_NETCHAN_VERSION_QEX:info->special |= SS_QEPROT; break;
|
||||||
|
case NQ_NETCHAN_VERSION:
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
while (*token)
|
||||||
|
{
|
||||||
|
if (*token == 'w')
|
||||||
|
info->special |= SS_QUAKEWORLD;
|
||||||
|
else if (*token == 'n' || *token == 'd')
|
||||||
|
info->special |= SS_NETQUAKE;
|
||||||
|
else if (*token == 'x')
|
||||||
|
info->special |= SS_QEPROT;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((info->special&SS_PROTOCOLMASK) == SS_UNKNOWN)
|
||||||
|
{ //guesses...
|
||||||
if (PROTOCOL_VERSION_Q2 >= info->protocol && info->protocol >= PROTOCOL_VERSION_Q2_MIN)
|
if (PROTOCOL_VERSION_Q2 >= info->protocol && info->protocol >= PROTOCOL_VERSION_Q2_MIN)
|
||||||
info->special |= SS_QUAKE2; //q2 has a range!
|
info->special |= SS_QUAKE2; //q2 has a range!
|
||||||
else if (info->protocol > 60)
|
else if (info->protocol > 60)
|
||||||
info->special |= SS_QUAKE3;
|
info->special |= SS_QUAKE3;
|
||||||
else if (!strcmp(Info_ValueForKey(msg, "gamename"), "DarkPlaces-Quake"))
|
else if (!strcmp(Info_ValueForKey(msg, "gamename"), "DarkPlaces-Quake") || *Info_ValueForKey(msg, "nqprotocol"))
|
||||||
info->special |= SS_DARKPLACES;
|
info->special |= SS_NETQUAKE;
|
||||||
else
|
else
|
||||||
info->special |= SS_DARKPLACES|SS_FTESERVER; //so its listed under qw-servers (but queried using dpmaster getinfo stuff).
|
info->special |= SS_QUAKEWORLD;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3342,7 +3355,7 @@ static int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolea
|
||||||
msg = msg+strlen(msg)+1;
|
msg = msg+strlen(msg)+1;
|
||||||
|
|
||||||
//clear player info. unless its an NQ server, which have some really annoying protocol to find out the players.
|
//clear player info. unless its an NQ server, which have some really annoying protocol to find out the players.
|
||||||
if ((info->special & SS_PROTOCOLMASK) == SS_NETQUAKE)
|
if ((info->special & (SS_PROTOCOLMASK|SS_GETINFO)) == SS_NETQUAKE)
|
||||||
{
|
{
|
||||||
if (!info->moreinfo && ((slist_cacheinfo.value == 2 || NET_CompareAdr(&info->adr, &selectedserver.adr)) || (info->special & SS_KEEPINFO)))
|
if (!info->moreinfo && ((slist_cacheinfo.value == 2 || NET_CompareAdr(&info->adr, &selectedserver.adr)) || (info->special & SS_KEEPINFO)))
|
||||||
info->moreinfo = Z_Malloc(sizeof(serverdetailedinfo_t));
|
info->moreinfo = Z_Malloc(sizeof(serverdetailedinfo_t));
|
||||||
|
@ -3516,7 +3529,7 @@ static int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolea
|
||||||
msg++;
|
msg++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((info->special & SS_PROTOCOLMASK) == SS_DARKPLACES && !info->numbots)
|
if (!info->numbots)
|
||||||
{
|
{
|
||||||
info->numbots = atoi(Info_ValueForKey(details.info, "bots"));
|
info->numbots = atoi(Info_ValueForKey(details.info, "bots"));
|
||||||
if (info->numbots > info->players)
|
if (info->numbots > info->players)
|
||||||
|
@ -3624,7 +3637,7 @@ void CL_MasterListParse(netadrtype_t adrtype, int type, qboolean slashpad)
|
||||||
}
|
}
|
||||||
if ((old = Master_InfoForServer(&info->adr, NULL))) //remove if the server already exists.
|
if ((old = Master_InfoForServer(&info->adr, NULL))) //remove if the server already exists.
|
||||||
{
|
{
|
||||||
if ((old->special & (SS_PROTOCOLMASK)) != (type & (SS_PROTOCOLMASK)))
|
if ((old->special & (SS_PROTOCOLMASK|SS_GETINFO)) != (type & (SS_PROTOCOLMASK|SS_GETINFO)))
|
||||||
old->special = type | (old->special & (SS_FAVORITE|SS_LOCAL));
|
old->special = type | (old->special & (SS_FAVORITE|SS_LOCAL));
|
||||||
old->sends = 1; //reset.
|
old->sends = 1; //reset.
|
||||||
old->status |= SRVSTATUS_GLOBAL;
|
old->status |= SRVSTATUS_GLOBAL;
|
||||||
|
|
|
@ -83,7 +83,7 @@ static cvar_t pr_engine = CVARFD("pr_engine",DISTRIBUTION" "STRINGIFY(SVNREVISI
|
||||||
#endif
|
#endif
|
||||||
cvar_t fs_gamename = CVARAD("com_fullgamename", NULL, "fs_gamename", "The filesystem is trying to run this game");
|
cvar_t fs_gamename = CVARAD("com_fullgamename", NULL, "fs_gamename", "The filesystem is trying to run this game");
|
||||||
cvar_t com_protocolname = CVARAD("com_protocolname", NULL, "com_gamename", "The protocol game name used for dpmaster queries. For compatibility with DP, you can set this to 'DarkPlaces-Quake' in order to be listed in DP's master server, and to list DP servers.");
|
cvar_t com_protocolname = CVARAD("com_protocolname", NULL, "com_gamename", "The protocol game name used for dpmaster queries. For compatibility with DP, you can set this to 'DarkPlaces-Quake' in order to be listed in DP's master server, and to list DP servers.");
|
||||||
cvar_t com_protocolversion = CVARAD("com_protocolversion", "3", NULL, "The protocol version used for dpmaster queries."); //3 by default, for compat with DP/NQ, even if our QW protocol uses different versions entirely. really it only matters for master servers.
|
cvar_t com_protocolversion = CVARAD("com_protocolversion", "3", NULL, "The protocol version used for dpmaster queries."); //3 as strong default for compat with DP which uses its netchan rather than protocol version here, even if our QW protocol uses different versions entirely. really it only matters for master servers.
|
||||||
cvar_t com_parseutf8 = CVARD("com_parseutf8", "1", "Interpret console messages/playernames/etc as UTF-8. Requires special fonts. -1=iso 8859-1. 0=quakeascii(chat uses high chars). 1=utf8, revert to ascii on decode errors. 2=utf8 ignoring errors"); //1 parse. 2 parse, but stop parsing that string if a char was malformed.
|
cvar_t com_parseutf8 = CVARD("com_parseutf8", "1", "Interpret console messages/playernames/etc as UTF-8. Requires special fonts. -1=iso 8859-1. 0=quakeascii(chat uses high chars). 1=utf8, revert to ascii on decode errors. 2=utf8 ignoring errors"); //1 parse. 2 parse, but stop parsing that string if a char was malformed.
|
||||||
cvar_t com_highlightcolor = CVARD("com_highlightcolor", STRINGIFY(COLOR_RED), "ANSI colour to be used for highlighted text, used when com_parseutf8 is active.");
|
cvar_t com_highlightcolor = CVARD("com_highlightcolor", STRINGIFY(COLOR_RED), "ANSI colour to be used for highlighted text, used when com_parseutf8 is active.");
|
||||||
cvar_t com_gamedirnativecode = CVARFD("com_gamedirnativecode", "0", CVAR_NOTFROMSERVER, FULLENGINENAME" blocks all downloads of files with a .dll or .so extension, however other engines (eg: ezquake and fodquake) do not - this omission can be used to trigger delayed eremote exploits in any engine (including "DISTRIBUTION") which is later run from the same gamedir.\nQuake2, Quake3(when debugging), and KTX typically run native gamecode from within gamedirs, so if you wish to run any of these games you will need to ensure this cvar is changed to 1, as well as ensure that you don't run unsafe clients.");
|
cvar_t com_gamedirnativecode = CVARFD("com_gamedirnativecode", "0", CVAR_NOTFROMSERVER, FULLENGINENAME" blocks all downloads of files with a .dll or .so extension, however other engines (eg: ezquake and fodquake) do not - this omission can be used to trigger delayed eremote exploits in any engine (including "DISTRIBUTION") which is later run from the same gamedir.\nQuake2, Quake3(when debugging), and KTX typically run native gamecode from within gamedirs, so if you wish to run any of these games you will need to ensure this cvar is changed to 1, as well as ensure that you don't run unsafe clients.");
|
||||||
|
|
|
@ -297,7 +297,7 @@ void Net_Master_Init(void);
|
||||||
|
|
||||||
void Netchan_Init (void);
|
void Netchan_Init (void);
|
||||||
int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate);
|
int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate);
|
||||||
void Netchan_OutOfBand (netsrc_t sock, netadr_t *adr, int length, qbyte *data);
|
void Netchan_OutOfBand (netsrc_t sock, netadr_t *adr, int length, const qbyte *data);
|
||||||
void VARGS Netchan_OutOfBandPrint (netsrc_t sock, netadr_t *adr, char *format, ...) LIKEPRINTF(3);
|
void VARGS Netchan_OutOfBandPrint (netsrc_t sock, netadr_t *adr, char *format, ...) LIKEPRINTF(3);
|
||||||
void VARGS Netchan_OutOfBandTPrintf (netsrc_t sock, netadr_t *adr, int language, translation_t text, ...);
|
void VARGS Netchan_OutOfBandTPrintf (netsrc_t sock, netadr_t *adr, int language, translation_t text, ...);
|
||||||
qboolean Netchan_Process (netchan_t *chan);
|
qboolean Netchan_Process (netchan_t *chan);
|
||||||
|
|
|
@ -300,7 +300,7 @@ Netchan_OutOfBand
|
||||||
Sends an out-of-band datagram
|
Sends an out-of-band datagram
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
void Netchan_OutOfBand (netsrc_t sock, netadr_t *adr, int length, qbyte *data)
|
void Netchan_OutOfBand (netsrc_t sock, netadr_t *adr, int length, const qbyte *data)
|
||||||
{
|
{
|
||||||
sizebuf_t send;
|
sizebuf_t send;
|
||||||
qbyte send_buf[MAX_QWMSGLEN + PACKET_HEADER];
|
qbyte send_buf[MAX_QWMSGLEN + PACKET_HEADER];
|
||||||
|
|
|
@ -4349,7 +4349,7 @@ static void FTENET_ICE_Heartbeat(ftenet_ice_connection_t *b)
|
||||||
}
|
}
|
||||||
|
|
||||||
*info = 0;
|
*info = 0;
|
||||||
Info_SetValueForKey(info, "protocol", com_protocolversion.string, sizeof(info));
|
Info_SetValueForKey(info, "protocol", SV_GetProtocolVersionString(), sizeof(info));
|
||||||
Info_SetValueForKey(info, "maxclients", maxclients.string, sizeof(info));
|
Info_SetValueForKey(info, "maxclients", maxclients.string, sizeof(info));
|
||||||
Info_SetValueForKey(info, "clients", va("%i", numclients), sizeof(info));
|
Info_SetValueForKey(info, "clients", va("%i", numclients), sizeof(info));
|
||||||
Info_SetValueForKey(info, "hostname", hostname.string, sizeof(info));
|
Info_SetValueForKey(info, "hostname", hostname.string, sizeof(info));
|
||||||
|
|
|
@ -7185,7 +7185,7 @@ static void FTENET_WebRTC_Heartbeat(ftenet_websocket_connection_t *b)
|
||||||
info[1] =
|
info[1] =
|
||||||
info[2] = 0xff; //to the broker rather than any actual client
|
info[2] = 0xff; //to the broker rather than any actual client
|
||||||
info[3] = 0;
|
info[3] = 0;
|
||||||
Info_SetValueForKey(info+3, "protocol", com_protocolversion.string, sizeof(info)-3);
|
Info_SetValueForKey(info+3, "protocol", SV_GetProtocolVersionString(), sizeof(info)-3);
|
||||||
Info_SetValueForKey(info+3, "maxclients", maxclients.string, sizeof(info)-3);
|
Info_SetValueForKey(info+3, "maxclients", maxclients.string, sizeof(info)-3);
|
||||||
Info_SetValueForKey(info+3, "clients", va("%i", numclients), sizeof(info)-3);
|
Info_SetValueForKey(info+3, "clients", va("%i", numclients), sizeof(info)-3);
|
||||||
Info_SetValueForKey(info+3, "hostname", hostname.string, sizeof(info)-3);
|
Info_SetValueForKey(info+3, "hostname", hostname.string, sizeof(info)-3);
|
||||||
|
|
|
@ -1157,6 +1157,7 @@ int SV_CalcPing (client_t *cl, qboolean forcecalc);
|
||||||
void SV_FullClientUpdate (client_t *client, client_t *to);
|
void SV_FullClientUpdate (client_t *client, client_t *to);
|
||||||
char *SV_PlayerPublicAddress(client_t *cl);
|
char *SV_PlayerPublicAddress(client_t *cl);
|
||||||
|
|
||||||
|
const char *SV_GetProtocolVersionString(void); //decorate the protocol version field of server queries with extra features...
|
||||||
qboolean SVC_GetChallenge (qboolean respond_dp);
|
qboolean SVC_GetChallenge (qboolean respond_dp);
|
||||||
int SV_NewChallenge (void);
|
int SV_NewChallenge (void);
|
||||||
void SVC_DirectConnect(int expectedreliablesequence);
|
void SVC_DirectConnect(int expectedreliablesequence);
|
||||||
|
|
|
@ -1227,6 +1227,36 @@ static void SVC_Status (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1//def NQPROT
|
#if 1//def NQPROT
|
||||||
|
const char *SV_GetProtocolVersionString(void)
|
||||||
|
{
|
||||||
|
char *ret = va("%i", com_protocolversion.ival); //for compat with DP, this is basically locked at 3. our pexts allow this to be mostly graceful.
|
||||||
|
|
||||||
|
switch(svs.gametype)
|
||||||
|
{
|
||||||
|
case GT_PROGS:
|
||||||
|
case GT_Q1QVM:
|
||||||
|
if (sv_listen_qw.ival)
|
||||||
|
Q_strncatz(ret, "w", 64);
|
||||||
|
#ifdef NQPROT
|
||||||
|
if (progstype == PROG_H2)
|
||||||
|
break; //don't advertise nq protocols when they're blocked.
|
||||||
|
if (sv_listen_nq.ival)
|
||||||
|
{
|
||||||
|
Q_strncatz(ret, "n", 64);
|
||||||
|
#ifdef HAVE_DTLS
|
||||||
|
if (*dtls_psk_user.string)
|
||||||
|
Q_strncatz(ret, "x", 64);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (sv_listen_dp.ival)
|
||||||
|
Q_strncatz(ret, "d", 64);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break; //these do their own thing, with their own protocols. don't be weird.
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
static void SVC_GetInfo (const char *challenge, int fullstatus)
|
static void SVC_GetInfo (const char *challenge, int fullstatus)
|
||||||
{
|
{
|
||||||
//dpmaster support
|
//dpmaster support
|
||||||
|
@ -1289,7 +1319,7 @@ static void SVC_GetInfo (const char *challenge, int fullstatus)
|
||||||
*resp = 0;
|
*resp = 0;
|
||||||
Info_SetValueForKey(resp, "challenge", challenge, sizeof(response) - (resp-response)); //the challenge can be important for the master protocol to prevent poisoning
|
Info_SetValueForKey(resp, "challenge", challenge, sizeof(response) - (resp-response)); //the challenge can be important for the master protocol to prevent poisoning
|
||||||
Info_SetValueForKey(resp, "gamename", protocolname, sizeof(response) - (resp-response));//distinguishes it from other types of games
|
Info_SetValueForKey(resp, "gamename", protocolname, sizeof(response) - (resp-response));//distinguishes it from other types of games
|
||||||
Info_SetValueForKey(resp, "protocol", com_protocolversion.string, sizeof(response) - (resp-response)); //should be an int.
|
Info_SetValueForKey(resp, "protocol", SV_GetProtocolVersionString(), sizeof(response) - (resp-response));
|
||||||
Info_SetValueForKey(resp, "modname", FS_GetGamedir(true), sizeof(response) - (resp-response));
|
Info_SetValueForKey(resp, "modname", FS_GetGamedir(true), sizeof(response) - (resp-response));
|
||||||
Info_SetValueForKey(resp, "clients", va("%d", numclients), sizeof(response) - (resp-response));
|
Info_SetValueForKey(resp, "clients", va("%d", numclients), sizeof(response) - (resp-response));
|
||||||
Info_SetValueForKey(resp, "sv_maxclients", maxclients.string, sizeof(response) - (resp-response));
|
Info_SetValueForKey(resp, "sv_maxclients", maxclients.string, sizeof(response) - (resp-response));
|
||||||
|
@ -1549,6 +1579,33 @@ qboolean SVC_GetChallenge (qboolean respond_dp)
|
||||||
const qboolean respond_qwoverq3 = false;
|
const qboolean respond_qwoverq3 = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//ioq3clchallenge = atoi(Cmd_Argv(1));
|
||||||
|
const char *protocols = Cmd_Argv(2);
|
||||||
|
if (*protocols)
|
||||||
|
{
|
||||||
|
const char *pname;
|
||||||
|
char tprot[64], oprot[64];
|
||||||
|
while ((protocols=COM_ParseOut(protocols, tprot,sizeof(tprot))))
|
||||||
|
{
|
||||||
|
pname = com_protocolname.string;
|
||||||
|
while ((pname=COM_ParseOut(pname, oprot,sizeof(oprot))))
|
||||||
|
{
|
||||||
|
if (!strcmp(tprot, oprot))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pname)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!protocols)
|
||||||
|
{
|
||||||
|
COM_ParseOut(com_protocolname.string, oprot,sizeof(oprot));
|
||||||
|
pname = va("print\nGame mismatch: This is a %s server\n", oprot);
|
||||||
|
Netchan_OutOfBand(NS_SERVER, &net_from, strlen(pname), pname);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (sv_listen_qw.value && !sv_listen_dp.value)
|
if (sv_listen_qw.value && !sv_listen_dp.value)
|
||||||
{
|
{
|
||||||
respond_std = true;
|
respond_std = true;
|
||||||
|
@ -3318,7 +3375,7 @@ void SVC_DirectConnect(int expectedreliablesequence)
|
||||||
}
|
}
|
||||||
Q_strncpyz (info.userinfo, net_message.data + 11, sizeof(info.userinfo)-1);
|
Q_strncpyz (info.userinfo, net_message.data + 11, sizeof(info.userinfo)-1);
|
||||||
|
|
||||||
if (strcmp(Info_ValueForKey(info.userinfo, "protocol"), "darkplaces 3"))
|
if (strcmp(Info_ValueForKey(info.userinfo, "protocol"), "darkplaces "STRINGIFY(NQ_NETCHAN_VERSION)))
|
||||||
{
|
{
|
||||||
SV_RejectMessage (SCP_BAD, "Server is %s.\n", version_string());
|
SV_RejectMessage (SCP_BAD, "Server is %s.\n", version_string());
|
||||||
Con_TPrintf ("* rejected connect from incompatible client\n");
|
Con_TPrintf ("* rejected connect from incompatible client\n");
|
||||||
|
@ -4165,8 +4222,9 @@ qboolean SV_ConnectionlessPacket (void)
|
||||||
}*/
|
}*/
|
||||||
else if (!strcmp(c,"getchallenge"))
|
else if (!strcmp(c,"getchallenge"))
|
||||||
{
|
{
|
||||||
//qw+q2 always sends "\xff\xff\xff\xffgetchallenge\n"
|
//qw+q2 sends "\xff\xff\xff\xffgetchallenge\n"
|
||||||
//dp+q3 always sends "\xff\xff\xff\xffgetchallenge"
|
//dp+q3 sends "\xff\xff\xff\xffgetchallenge"
|
||||||
|
//ioq3 sends "\xff\xff\xff\xffgetchallenge <clientchallenge> <$com_gamename>"
|
||||||
//its a subtle difference, but means we can avoid wasteful spam for real qw clients.
|
//its a subtle difference, but means we can avoid wasteful spam for real qw clients.
|
||||||
SVC_GetChallenge ((net_message.cursize==16)?true:false);
|
SVC_GetChallenge ((net_message.cursize==16)?true:false);
|
||||||
}
|
}
|
||||||
|
@ -4407,13 +4465,15 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
||||||
|
|
||||||
if (SV_ChallengeRecent())
|
if (SV_ChallengeRecent())
|
||||||
return true;
|
return true;
|
||||||
else if (!strncmp(MSG_ReadString(), "getchallenge", 12) && (sv_listen_qw.ival || sv_listen_dp.ival))
|
|
||||||
|
Cmd_TokenizeString (MSG_ReadString(), false, false);
|
||||||
|
if (!strcmp(Cmd_Argv(0), "getchallenge") && (sv_listen_qw.ival || sv_listen_dp.ival))
|
||||||
{
|
{
|
||||||
/*dual-stack client, supporting either DP or QW protocols*/
|
/*dual-stack client, supporting either DP or QW protocols*/
|
||||||
SVC_GetChallenge (false);
|
SVC_GetChallenge (false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{ //legacy pure-nq (though often DP).
|
||||||
if (progstype == PROG_H2)
|
if (progstype == PROG_H2)
|
||||||
{
|
{
|
||||||
SZ_Clear(&sb);
|
SZ_Clear(&sb);
|
||||||
|
|
Loading…
Reference in a new issue