+ // QuakeWorld compatibility
+ if (length >= 1 && string[0] == 'j' && cls.connect_trying)
+ {
+ // accept message
+ M_Update_Return_Reason("Accepted");
+ NetConn_ConnectionEstablished(mysocket, peeraddress, PROTOCOL_QUAKEWORLD);
+ return true;
+ }
+ if (length > 1 && string[0] == 'c' && string[1] >= '0' && string[1] <= '9' && cls.connect_trying)
+ {
+ // challenge message
+ LHNETADDRESS_ToString(peeraddress, addressstring2, sizeof(addressstring2), true);
+ Con_Printf("challenge %s received, sending connect request back to %s\n", string + 1, addressstring2);
+ M_Update_Return_Reason("Got challenge response");
+ cls.qw_qport = qport.integer;
+ InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), "*ip", addressstring2);
+ InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), "name", cl_name.string);
+ InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), "topcolor", va("%i", (cl_color.integer >> 4) & 15));
+ InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), "bottomcolor", va("%i", (cl_color.integer) & 15));
+ InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), "rate", va("%i", cl_rate.integer));
+ InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), "msg", "1");
+ InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), "*ver", engineversion);
+ NetConn_WriteString(mysocket, va("\377\377\377\377connect %i %i %i \"%s\"\n", 28, cls.qw_qport, atoi(string + 1), cls.userinfo), peeraddress);
+ return true;
+ }
+ if (length > 2 && !memcmp(string, "n\\", 2))
+ {
+ serverlist_info_t *info;
+ int n;
+ double pingtime;
+
+ // qw server status
+ if (serverlist_consoleoutput && developer_networking.integer >= 2)
+ Con_Printf("QW server status from server at %s:\n%s\n", addressstring2, string + 1);
+
+ string += 1;
+ // serverlist only uses text addresses
+ LHNETADDRESS_ToString(peeraddress, cname, sizeof(cname), true);
+ // search the cache for this server and update it
+ for( n = 0; n < serverlist_cachecount; n++ )
+ if( !strcmp( cname, serverlist_cache[n].info.cname ) )
+ break;
+ if( n == serverlist_cachecount ) {
+ // LAN search doesnt require an answer from the master server so we wont
+ // know the ping nor will it be initialized already...
+
+ // find a slot
+ if( serverlist_cachecount == SERVERLIST_TOTALSIZE )
+ return true;
+
+ memset(&serverlist_cache[serverlist_cachecount], 0, sizeof(serverlist_cache[serverlist_cachecount]));
+ // store the data the engine cares about (address and ping)
+ strlcpy (serverlist_cache[serverlist_cachecount].info.cname, cname, sizeof (serverlist_cache[serverlist_cachecount].info.cname));
+ serverlist_cache[serverlist_cachecount].info.ping = 100000;
+ //serverlist_cache[serverlist_cachecount].querytime = realtime;
+ serverlist_cache[serverlist_cachecount].querytime = Sys_DoubleTime();
+ // if not in the slist menu we should print the server to console
+ if (serverlist_consoleoutput) {
+ Con_Printf("querying %s\n", ipstring);
+ }
+
+ ++serverlist_cachecount;
+ }
+
+ info = &serverlist_cache[n].info;
+ strlcpy(info->game, "QuakeWorld", sizeof(info->game));;
+ if ((s = SearchInfostring(string, "*gamedir" )) != NULL) strlcpy(info->mod , s, sizeof (info->mod ));else info->mod[0] = 0;
+ if ((s = SearchInfostring(string, "map" )) != NULL) strlcpy(info->map , s, sizeof (info->map ));else info->map[0] = 0;
+ if ((s = SearchInfostring(string, "hostname" )) != NULL) strlcpy(info->name, s, sizeof (info->name));else info->name[0] = 0;
+ info->protocol = 0;
+ info->numplayers = 0; // updated below
+ if ((s = SearchInfostring(string, "maxclients" )) != NULL) info->maxplayers = atoi(s);else info->maxplayers = 0;
+ if ((s = SearchInfostring(string, "gameversion" )) != NULL) info->gameversion = atoi(s);else info->gameversion = 0;
+
+ // count active players on server
+ // (we could gather more info, but we're just after the number)
+ s = strchr(string, '\n');
+ if (s)
+ {
+ s++;
+ while (s < string + length)
+ {
+ for (;s < string + length && *s != '\n';s++)
+ ;
+ if (s >= string + length)
+ break;
+ info->numplayers++;
+ s++;
+ }
+ }
+
+ if (info->ping == 100000)
+ serverreplycount++;
+
+ pingtime = (int)((Sys_DoubleTime() - serverlist_cache[n].querytime) * 1000.0 + 0.5);
+ pingtime = bound(0, pingtime, 9999);
+ // update the ping
+ info->ping = (int)pingtime;
+
+ // legacy/old stuff move it to the menu ASAP
+
+ // build description strings for the things users care about
+ dpsnprintf(serverlist_cache[n].line1, sizeof(serverlist_cache[n].line1), "^%c%5d^7 ^%c%3u^7/%3u %-65.65s", pingtime >= 300 ? '1' : (pingtime >= 200 ? '3' : '7'), (int)pingtime, ((info->numplayers > 0 && info->numplayers < info->maxplayers) ? (info->numplayers >= 4 ? '7' : '3') : '1'), info->numplayers, info->maxplayers, info->name);
+ dpsnprintf(serverlist_cache[n].line2, sizeof(serverlist_cache[n].line2), "^4%-21.21s %-19.19s ^%c%-17.17s^4 %-20.20s", info->cname, info->game, (info->gameversion != gameversion.integer) ? '1' : '4', info->mod, info->map);
+ if( serverlist_cache[n].query == SQS_QUERIED ) {
+ ServerList_ViewList_Remove( &serverlist_cache[n] );
+ }
+ // if not in the slist menu we should print the server to console (if wanted)
+ else if( serverlist_consoleoutput )
+ Con_Printf("%s\n%s\n", serverlist_cache[n].line1, serverlist_cache[n].line2);
+ // and finally, update the view set
+ ServerList_ViewList_Insert( &serverlist_cache[n] );
+ serverlist_cache[n].query = SQS_QUERIED;
+
+ return true;
+ }
+ if (string[0] == 'n')
+ {
+ // qw print command
+ Con_Printf("QW print command from server at %s:\n%s\n", addressstring2, string + 1);
+ }