mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-23 04:42:32 +00:00
rewrite the info strings to use hash tables instead of a static string.
This required changes to the api (info_t instead of char *) but should be a net gain in speed (not a lot, admittedly: it was pretty fast to begin with, but this paves the way for some other changes I have in mind).
This commit is contained in:
parent
de0b4f65fa
commit
dcd9b0040e
19 changed files with 249 additions and 298 deletions
|
@ -36,13 +36,27 @@
|
|||
#define MAX_SERVERINFO_STRING 512
|
||||
#define MAX_LOCALINFO_STRING 32768
|
||||
|
||||
typedef struct info_s {
|
||||
struct hashtab_s *tab;
|
||||
int maxsize;
|
||||
int cursize;
|
||||
} info_t;
|
||||
|
||||
typedef struct info_key_s {
|
||||
const char *key;
|
||||
const char *value;
|
||||
} info_key_t;
|
||||
|
||||
qboolean Info_FilterForKey (const char *key, const char **filter_list);
|
||||
void Info_Print (const char *s);
|
||||
void Info_RemoveKey (char *s, const char *key);
|
||||
void Info_RemovePrefixedKeys (char *start, char prefix, const char **filter_list);
|
||||
void Info_SetValueForKey (char *s, const char *key, const char *value, size_t maxsize, int flags);
|
||||
void Info_SetValueForStarKey (char *s, const char *key, const char *value, size_t maxsize, int flags);
|
||||
const char *Info_ValueForKey (const char *s, const char *key);
|
||||
qboolean Info_Validate (const char *s);
|
||||
|
||||
void Info_Print (info_t *info);
|
||||
void Info_RemoveKey (info_t *info, const char *key);
|
||||
void Info_SetValueForKey (info_t *info, const char *key, const char *value, int flags);
|
||||
void Info_SetValueForStarKey (info_t *info, const char *key, const char *value, int flags);
|
||||
const char *Info_ValueForKey (info_t *info, const char *key);
|
||||
|
||||
info_t *Info_ParseString (const char *s, int maxsize);
|
||||
void Info_Destroy (info_t *info);
|
||||
char *Info_MakeString (info_t *info, int (*filter)(const char *));
|
||||
|
||||
#endif // _INFO_H
|
||||
|
|
335
libs/util/info.c
335
libs/util/info.c
|
@ -40,8 +40,10 @@ static const char rcsid[] =
|
|||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "QF/hash.h"
|
||||
#include "QF/info.h"
|
||||
#include "QF/sys.h"
|
||||
#include "QF/zone.h"
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
|
@ -71,139 +73,31 @@ Info_FilterForKey (const char *key, const char **filter_list)
|
|||
key and returns the associated value, or an empty string.
|
||||
*/
|
||||
const char *
|
||||
Info_ValueForKey (const char *s, const char *key)
|
||||
Info_ValueForKey (info_t *info, const char *key)
|
||||
{
|
||||
char pkey[512];
|
||||
static char value[4][512]; // use two buffers so compares
|
||||
info_key_t *k = Hash_Find (info->tab, key);
|
||||
if (k)
|
||||
return k->value;
|
||||
return "";
|
||||
}
|
||||
|
||||
// work without stomping on each other
|
||||
static int valueindex;
|
||||
char *o;
|
||||
void
|
||||
Info_RemoveKey (info_t *info, const char *key)
|
||||
{
|
||||
info_key_t *k = Hash_Del (info->tab, key);
|
||||
|
||||
valueindex = (valueindex + 1) % 4;
|
||||
if (*s == '\\')
|
||||
s++;
|
||||
while (1) {
|
||||
o = pkey;
|
||||
while (*s != '\\') {
|
||||
if (!*s)
|
||||
return "";
|
||||
*o++ = *s++;
|
||||
}
|
||||
*o = 0;
|
||||
s++;
|
||||
|
||||
o = value[valueindex];
|
||||
|
||||
while (*s != '\\' && *s) {
|
||||
if (!*s)
|
||||
return "";
|
||||
*o++ = *s++;
|
||||
}
|
||||
*o = 0;
|
||||
|
||||
if (!strcmp (key, pkey))
|
||||
return value[valueindex];
|
||||
|
||||
if (!*s)
|
||||
return "";
|
||||
s++;
|
||||
if (k) {
|
||||
free ((char*)k->key);
|
||||
free ((char*)k->value);
|
||||
free (k);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Info_RemoveKey (char *s, const char *key)
|
||||
Info_SetValueForStarKey (info_t *info, const char *key, const char *value, int flags)
|
||||
{
|
||||
char *start;
|
||||
char pkey[512];
|
||||
char value[512];
|
||||
char *o;
|
||||
|
||||
if (strstr (key, "\\")) {
|
||||
Sys_Printf ("Can't use a key with a \\\n");
|
||||
return;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
start = s;
|
||||
if (*s == '\\')
|
||||
s++;
|
||||
o = pkey;
|
||||
while (*s != '\\') {
|
||||
if (!*s)
|
||||
return;
|
||||
*o++ = *s++;
|
||||
}
|
||||
*o = 0;
|
||||
s++;
|
||||
|
||||
o = value;
|
||||
while (*s != '\\' && *s) {
|
||||
if (!*s)
|
||||
return;
|
||||
*o++ = *s++;
|
||||
}
|
||||
*o = 0;
|
||||
|
||||
if (!strcmp (key, pkey)) {
|
||||
strcpy (start, s); // remove this part
|
||||
return;
|
||||
}
|
||||
|
||||
if (!*s)
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
Info_RemovePrefixedKeys (char *start, char prefix, const char **filter_list)
|
||||
{
|
||||
char *s;
|
||||
char pkey[512];
|
||||
char value[512];
|
||||
char *o;
|
||||
|
||||
s = start;
|
||||
|
||||
while (1) {
|
||||
if (*s == '\\')
|
||||
s++;
|
||||
o = pkey;
|
||||
while (*s != '\\') {
|
||||
if (!*s)
|
||||
return;
|
||||
*o++ = *s++;
|
||||
}
|
||||
*o = 0;
|
||||
s++;
|
||||
|
||||
o = value;
|
||||
while (*s != '\\' && *s) {
|
||||
if (!*s)
|
||||
return;
|
||||
*o++ = *s++;
|
||||
}
|
||||
*o = 0;
|
||||
|
||||
if (pkey[0] == prefix
|
||||
|| (filter_list && !Info_FilterForKey (pkey, filter_list))) {
|
||||
Info_RemoveKey (start, pkey);
|
||||
s = start;
|
||||
}
|
||||
|
||||
if (!*s)
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
Info_SetValueForStarKey (char *s, const char *key, const char *value, size_t maxsize, int flags)
|
||||
{
|
||||
char newstr[1024];
|
||||
const char *v;
|
||||
int c;
|
||||
info_key_t *k;
|
||||
int cursize;
|
||||
|
||||
if (strstr (key, "\\") || strstr (value, "\\")) {
|
||||
Sys_Printf ("Can't use keys or values with a \\\n");
|
||||
|
@ -219,110 +113,137 @@ Info_SetValueForStarKey (char *s, const char *key, const char *value, size_t max
|
|||
Sys_Printf ("Keys and values must be < 64 characters.\n");
|
||||
return;
|
||||
}
|
||||
// this next line is kinda trippy
|
||||
if (*(v = Info_ValueForKey (s, key))) {
|
||||
// key exists, make sure we have enough room for new value, if we
|
||||
// don't,
|
||||
// don't change it!
|
||||
if (strlen (value) - strlen (v) + strlen (s) > maxsize) {
|
||||
Sys_Printf ("Info string length exceeded\n");
|
||||
return;
|
||||
}
|
||||
k = Hash_Find (info->tab, key);
|
||||
cursize = info->cursize;
|
||||
if (k) {
|
||||
cursize -= strlen (k->key) + 1;
|
||||
cursize -= strlen (k->value) + 1;
|
||||
}
|
||||
Info_RemoveKey (s, key);
|
||||
if (!value || !strlen (value))
|
||||
return;
|
||||
|
||||
snprintf (newstr, sizeof (newstr), "\\%s\\%s", key, value);
|
||||
|
||||
if ((int) (strlen (newstr) + strlen (s)) > maxsize) {
|
||||
if (cursize + strlen (key) + 1 + strlen (value) + 1 > info->maxsize) {
|
||||
Sys_Printf ("Info string length exceeded\n");
|
||||
return;
|
||||
}
|
||||
// only copy ascii values
|
||||
s += strlen (s);
|
||||
v = newstr;
|
||||
while (*v) {
|
||||
c = (unsigned char) *v++;
|
||||
// client only allows highbits on name
|
||||
if (flags & 1) {
|
||||
c &= 127;
|
||||
if (c < 32 || c > 127)
|
||||
continue;
|
||||
// auto lowercase team
|
||||
if (flags & 2)
|
||||
c = tolower (c);
|
||||
}
|
||||
if (c > 13)
|
||||
*s++ = c;
|
||||
if (k) {
|
||||
if (strequal (k->value, value))
|
||||
return;
|
||||
free ((char*)k->value);
|
||||
} else {
|
||||
if (!(k = malloc (sizeof (info_key_t))))
|
||||
Sys_Error ("Info_SetValueForStarKey: out of memory\n");
|
||||
if (!(k->key = strdup (key)))
|
||||
Sys_Error ("Info_SetValueForStarKey: out of memory\n");
|
||||
info->cursize += strlen (key) + 1;
|
||||
Hash_Add (info->tab, k);
|
||||
}
|
||||
*s = 0;
|
||||
if (!(k->value = strdup (value)))
|
||||
Sys_Error ("Info_SetValueForStarKey: out of memory\n");
|
||||
info->cursize += strlen (value) + 1;
|
||||
}
|
||||
|
||||
void
|
||||
Info_SetValueForKey (char *s, const char *key, const char *value,
|
||||
size_t maxsize, int flags)
|
||||
Info_SetValueForKey (info_t *info, const char *key, const char *value,
|
||||
int flags)
|
||||
{
|
||||
if (key[0] == '*') {
|
||||
Sys_Printf ("Can't set * keys\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Info_SetValueForStarKey (s, key, value, maxsize, flags);
|
||||
Info_SetValueForStarKey (info, key, value, flags);
|
||||
}
|
||||
|
||||
void
|
||||
Info_Print (const char *s)
|
||||
Info_Print (info_t *info)
|
||||
{
|
||||
char key[512];
|
||||
char value[512];
|
||||
char *o;
|
||||
int l;
|
||||
info_key_t **key_list;
|
||||
info_key_t **key;
|
||||
|
||||
if (*s == '\\')
|
||||
s++;
|
||||
while (*s) {
|
||||
o = key;
|
||||
while (*s && *s != '\\')
|
||||
*o++ = *s++;
|
||||
key_list = (info_key_t **)Hash_GetList (info->tab);
|
||||
|
||||
l = o - key;
|
||||
if (l < 20) {
|
||||
memset (o, ' ', 20 - l);
|
||||
key[20] = 0;
|
||||
} else
|
||||
*o = 0;
|
||||
Sys_Printf ("%s", key);
|
||||
|
||||
if (!*s) {
|
||||
Sys_Printf ("MISSING VALUE\n");
|
||||
return;
|
||||
}
|
||||
|
||||
o = value;
|
||||
s++;
|
||||
while (*s && *s != '\\')
|
||||
*o++ = *s++;
|
||||
*o = 0;
|
||||
|
||||
if (*s)
|
||||
s++;
|
||||
Sys_Printf ("%s\n", value);
|
||||
for (key = key_list; *key; key++) {
|
||||
Sys_Printf ("%20s %s\n", (*key)->key, (*key)->value);
|
||||
}
|
||||
free (key_list);
|
||||
}
|
||||
|
||||
qboolean
|
||||
Info_Validate (const char *s)
|
||||
static const char *
|
||||
get_key (void *k, void *unused)
|
||||
{
|
||||
int count;
|
||||
const char *p;
|
||||
|
||||
if (!s || *s == '\0')
|
||||
return false;
|
||||
|
||||
for (p = s, count = 0; *p != '\0'; p++)
|
||||
if (*p == '\\')
|
||||
count++;
|
||||
|
||||
return (!(count % 2));
|
||||
return ((info_key_t *)k)->key;
|
||||
}
|
||||
|
||||
static void
|
||||
free_key (void *_k, void *unused)
|
||||
{
|
||||
info_key_t *k = (info_key_t *)_k;
|
||||
free ((char*)k->key);
|
||||
free ((char*)k->value);
|
||||
free (k);
|
||||
}
|
||||
|
||||
info_t *
|
||||
Info_ParseString (const char *s, int maxsize)
|
||||
{
|
||||
info_t *info;
|
||||
char *string = Hunk_TempAlloc (strlen (s) + 1);
|
||||
char *key, *value, *end;
|
||||
|
||||
info = malloc (sizeof (info_t));
|
||||
info->tab = Hash_NewTable (61, get_key, free_key, 0);
|
||||
info->maxsize = maxsize;
|
||||
info->cursize = 0;
|
||||
|
||||
strcpy (string, s);
|
||||
key = string;
|
||||
if (*key == '\\')
|
||||
key++;
|
||||
while (*key) {
|
||||
value = key;
|
||||
while (*value && *value != '\\')
|
||||
value++;
|
||||
if (*value) {
|
||||
*value++ = 0;
|
||||
for (end = value; *end && *end != '\\'; end++)
|
||||
;
|
||||
if (*end)
|
||||
*end++ = 0;
|
||||
} else {
|
||||
value = end = "";
|
||||
}
|
||||
Info_SetValueForStarKey (info, key, value, 0);
|
||||
key = end;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
void
|
||||
Info_Destroy (info_t *info)
|
||||
{
|
||||
Hash_DelTable (info->tab);
|
||||
free (info);
|
||||
}
|
||||
|
||||
char *
|
||||
Info_MakeString (info_t *info, int (*filter)(const char *))
|
||||
{
|
||||
char *string = Hunk_TempAlloc (info->cursize + 1);
|
||||
const char *s;
|
||||
char *d = string;;
|
||||
info_key_t **key_list;
|
||||
info_key_t **key;
|
||||
|
||||
key_list = (info_key_t **)Hash_GetList (info->tab);
|
||||
|
||||
for (key = key_list; *key; key++) {
|
||||
if (filter && filter ((*key)->key))
|
||||
continue;
|
||||
*d++ = '\\';
|
||||
for (s = (*key)->key; *s; s++)
|
||||
*d++ = *s;
|
||||
*d++ = '\\';
|
||||
for (s = (*key)->value; *s; s++)
|
||||
*d++ = *s;
|
||||
}
|
||||
free (key_list);
|
||||
return string;
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ typedef struct player_state_s {
|
|||
typedef struct player_info_s
|
||||
{
|
||||
int userid;
|
||||
char userinfo[MAX_INFO_STRING];
|
||||
struct info_s *userinfo;
|
||||
|
||||
// scoreboard information
|
||||
char name[MAX_SCOREBOARDNAME];
|
||||
|
@ -148,7 +148,7 @@ typedef struct
|
|||
netchan_t netchan;
|
||||
|
||||
// private userinfo for sending to masterless servers
|
||||
char userinfo[MAX_INFO_STRING];
|
||||
struct info_s *userinfo;
|
||||
|
||||
char servername[MAX_OSPATH]; // name of server from original connect
|
||||
|
||||
|
@ -190,7 +190,7 @@ typedef struct
|
|||
{
|
||||
int servercount; // server identification for prespawns
|
||||
|
||||
char serverinfo[MAX_SERVERINFO_STRING];
|
||||
struct info_s *serverinfo;
|
||||
|
||||
int parsecount; // server message counter
|
||||
int validsequence; // this is the sequence number of the last good
|
||||
|
|
|
@ -161,7 +161,7 @@ typedef struct client_s
|
|||
int lossage; // loss percentage
|
||||
|
||||
int userid; // identifying number
|
||||
char userinfo[MAX_INFO_STRING]; // infostring
|
||||
struct info_s *userinfo; // infostring
|
||||
|
||||
usercmd_t lastcmd; // for filling in big drops and partial predictions
|
||||
double localtime; // of last message
|
||||
|
@ -276,7 +276,7 @@ typedef struct
|
|||
int heartbeat_sequence;
|
||||
svstats_t stats;
|
||||
|
||||
char info[MAX_SERVERINFO_STRING];
|
||||
info_t *info;
|
||||
|
||||
// log messages are used so that fraglog processes can get stats
|
||||
int logsequence; // the message currently being filled
|
||||
|
@ -397,7 +397,7 @@ extern struct cvar_s *fraglimit;
|
|||
extern struct cvar_s *timelimit;
|
||||
|
||||
extern server_static_t svs; // persistant server info
|
||||
extern char *svs_info; // evil memory saving hack :)
|
||||
extern struct info_s **svs_info;
|
||||
extern server_t sv; // local server
|
||||
|
||||
extern client_t *host_client;
|
||||
|
@ -406,7 +406,7 @@ extern struct edict_s *sv_player;
|
|||
|
||||
extern char localmodels[MAX_MODELS][5]; // inline model names for precache
|
||||
|
||||
extern char localinfo[MAX_LOCALINFO_STRING+1];
|
||||
extern struct info_s *localinfo;
|
||||
|
||||
extern int host_hunklevel;
|
||||
extern VFile *sv_logfile;
|
||||
|
|
|
@ -49,7 +49,6 @@ Cvar_Info (cvar_t *var)
|
|||
{
|
||||
if (var->flags & CVAR_USERINFO) {
|
||||
Info_SetValueForKey (cls.userinfo, var->name, var->string,
|
||||
MAX_INFO_STRING,
|
||||
((!strequal(var->name, "name"))
|
||||
|(strequal(var->name, "team") << 1)));
|
||||
if (cls.state >= ca_connected) {
|
||||
|
|
|
@ -483,7 +483,8 @@ CL_Record_f (void)
|
|||
|
||||
// send server info string
|
||||
MSG_WriteByte (&buf, svc_stufftext);
|
||||
MSG_WriteString (&buf, va ("fullserverinfo \"%s\"\n", cl.serverinfo));
|
||||
MSG_WriteString (&buf, va ("fullserverinfo \"%s\"\n",
|
||||
Info_MakeString (cl.serverinfo, 0)));
|
||||
|
||||
// flush packet
|
||||
CL_WriteRecordDemoMessage (&buf, seq++);
|
||||
|
@ -626,7 +627,7 @@ CL_Record_f (void)
|
|||
MSG_WriteByte (&buf, svc_updateuserinfo);
|
||||
MSG_WriteByte (&buf, i);
|
||||
MSG_WriteLong (&buf, player->userid);
|
||||
MSG_WriteString (&buf, player->userinfo);
|
||||
MSG_WriteString (&buf, Info_MakeString (player->userinfo, 0));
|
||||
|
||||
if (buf.cursize > MAX_MSGLEN / 2) {
|
||||
CL_WriteRecordDemoMessage (&buf, seq++);
|
||||
|
|
|
@ -294,7 +294,7 @@ CL_SendConnectPacket (void)
|
|||
// Con_Printf ("Connecting to %s...\n", cls.servername);
|
||||
snprintf (data, sizeof (data), "%c%c%c%cconnect %i %i %i \"%s\"\n",
|
||||
255, 255, 255, 255, PROTOCOL_VERSION, cls.qport, cls.challenge,
|
||||
cls.userinfo);
|
||||
Info_MakeString (cls.userinfo, 0));
|
||||
NET_SendPacket (strlen (data), data, adr);
|
||||
}
|
||||
|
||||
|
@ -419,7 +419,9 @@ CL_ClearState (void)
|
|||
R_ClearFires ();
|
||||
|
||||
// wipe the entire cl structure
|
||||
Info_Destroy (cl.serverinfo);
|
||||
memset (&cl, 0, sizeof (cl));
|
||||
cl.serverinfo = Info_ParseString ("", MAX_INFO_STRING);
|
||||
|
||||
SZ_Clear (&cls.netchan.message);
|
||||
|
||||
|
@ -572,8 +574,9 @@ CL_FullServerinfo_f (void)
|
|||
}
|
||||
|
||||
Con_DPrintf ("Cmd_Argv(1): '%s'\n", Cmd_Argv (1));
|
||||
strcpy (cl.serverinfo, Cmd_Argv (1));
|
||||
Con_DPrintf ("cl.serverinfo: '%s'\n", cl.serverinfo);
|
||||
Info_Destroy (cl.serverinfo);
|
||||
cl.serverinfo = Info_ParseString (Cmd_Argv (1), MAX_SERVERINFO_STRING);
|
||||
Con_DPrintf ("cl.serverinfo: '%s'\n", Info_MakeString (cl.serverinfo, 0));
|
||||
|
||||
if ((p = Info_ValueForKey (cl.serverinfo, "*qf_version")) && *p) {
|
||||
if (server_version == NULL)
|
||||
|
@ -620,11 +623,9 @@ CL_AddQFInfoKeys (void)
|
|||
#ifdef HAVE_ZLIB
|
||||
strncat (cap, "z", sizeof (cap) - strlen (cap) - 1);
|
||||
#endif
|
||||
Info_SetValueForStarKey (cls.userinfo, "*cap", cap, MAX_INFO_STRING, 0);
|
||||
Info_SetValueForStarKey (cls.userinfo, "*qf_version", VERSION,
|
||||
MAX_INFO_STRING, 0);
|
||||
Info_SetValueForStarKey (cls.userinfo, "*qsg_version", QW_QSG_VERSION,
|
||||
MAX_INFO_STRING, 0);
|
||||
Info_SetValueForStarKey (cls.userinfo, "*cap", cap, 0);
|
||||
Info_SetValueForStarKey (cls.userinfo, "*qf_version", VERSION, 0);
|
||||
Info_SetValueForStarKey (cls.userinfo, "*qsg_version", QW_QSG_VERSION, 0);
|
||||
Con_Printf ("QuakeForge server detected\n");
|
||||
}
|
||||
|
||||
|
@ -680,7 +681,7 @@ CL_FullInfo_f (void)
|
|||
if (strcaseequal (key, pmodel_name) || strcaseequal (key, emodel_name))
|
||||
continue;
|
||||
|
||||
Info_SetValueForKey (cls.userinfo, key, value, MAX_INFO_STRING,
|
||||
Info_SetValueForKey (cls.userinfo, key, value,
|
||||
(!strequal (key, "name"))
|
||||
| (strequal (key, "team") << 1));
|
||||
}
|
||||
|
@ -707,7 +708,6 @@ CL_SetInfo_f (void)
|
|||
return;
|
||||
|
||||
Info_SetValueForKey (cls.userinfo, Cmd_Argv (1), Cmd_Argv (2),
|
||||
MAX_INFO_STRING,
|
||||
(!strequal (Cmd_Argv (1), "name"))
|
||||
| (strequal (Cmd_Argv (2), "team") << 1));
|
||||
if (cls.state >= ca_connected)
|
||||
|
@ -1092,14 +1092,14 @@ CL_Init (void)
|
|||
|
||||
CL_SetState (ca_disconnected);
|
||||
|
||||
Info_SetValueForKey (cls.userinfo, "name", "unnamed", MAX_INFO_STRING, 0);
|
||||
Info_SetValueForKey (cls.userinfo, "topcolor", "0", MAX_INFO_STRING, 0);
|
||||
Info_SetValueForKey (cls.userinfo, "bottomcolor", "0", MAX_INFO_STRING, 0);
|
||||
Info_SetValueForKey (cls.userinfo, "rate", "2500", MAX_INFO_STRING, 0);
|
||||
Info_SetValueForKey (cls.userinfo, "msg", "1", MAX_INFO_STRING, 0);
|
||||
Info_SetValueForKey (cls.userinfo, "name", "unnamed", 0);
|
||||
Info_SetValueForKey (cls.userinfo, "topcolor", "0", 0);
|
||||
Info_SetValueForKey (cls.userinfo, "bottomcolor", "0", 0);
|
||||
Info_SetValueForKey (cls.userinfo, "rate", "2500", 0);
|
||||
Info_SetValueForKey (cls.userinfo, "msg", "1", 0);
|
||||
// snprintf (st, sizeof(st), "%s-%04d", QW_VERSION, build_number());
|
||||
snprintf (st, sizeof (st), "%s", QW_VERSION);
|
||||
Info_SetValueForStarKey (cls.userinfo, "*ver", st, MAX_INFO_STRING, 0);
|
||||
Info_SetValueForStarKey (cls.userinfo, "*ver", st, 0);
|
||||
|
||||
CL_Input_Init ();
|
||||
CL_Ents_Init ();
|
||||
|
@ -1577,6 +1577,9 @@ Host_Init (void)
|
|||
Sys_Init_Cvars ();
|
||||
Sys_Init ();
|
||||
|
||||
cls.userinfo = Info_ParseString ("", MAX_INFO_STRING);
|
||||
cl.serverinfo = Info_ParseString ("", MAX_INFO_STRING);
|
||||
|
||||
Cbuf_Init ();
|
||||
Cmd_Init ();
|
||||
Locs_Init ();
|
||||
|
|
|
@ -300,7 +300,7 @@ Model_NextDownload (void)
|
|||
aliashdr_t *ahdr = Cache_Get
|
||||
(&cl.model_precache[i]->cache);
|
||||
Info_SetValueForKey (cls.userinfo, info_key, va ("%d", ahdr->crc),
|
||||
MAX_INFO_STRING, 0);
|
||||
0);
|
||||
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
|
||||
SZ_Print (&cls.netchan.message, va ("setinfo %s %d", info_key,
|
||||
ahdr->crc));
|
||||
|
@ -1039,8 +1039,10 @@ CL_ParseUpdateUserInfo (void)
|
|||
|
||||
player = &cl.players[updateuserinfo.slot];
|
||||
player->userid = updateuserinfo.userid;
|
||||
strncpy (player->userinfo, updateuserinfo.userinfo,
|
||||
sizeof (player->userinfo) - 1);
|
||||
if (player->userinfo)
|
||||
Info_Destroy (player->userinfo);
|
||||
player->userinfo = Info_ParseString (updateuserinfo.userinfo,
|
||||
MAX_INFO_STRING);
|
||||
|
||||
CL_ProcessUserInfo (updateuserinfo.slot, player);
|
||||
}
|
||||
|
@ -1063,14 +1065,15 @@ CL_SetInfo (void)
|
|||
}
|
||||
|
||||
player = &cl.players[setinfo.slot];
|
||||
if (!player->userinfo)
|
||||
player->userinfo = Info_ParseString ("", MAX_INFO_STRING);
|
||||
|
||||
Con_DPrintf ("SETINFO %s: %s=%s\n", player->name, setinfo.key,
|
||||
setinfo.value);
|
||||
|
||||
flags = !strequal (setinfo.key, "name");
|
||||
flags |= strequal (setinfo.key, "team") << 1;
|
||||
Info_SetValueForKey (player->userinfo, setinfo.key, setinfo.value,
|
||||
MAX_INFO_STRING, flags);
|
||||
Info_SetValueForKey (player->userinfo, setinfo.key, setinfo.value, flags);
|
||||
|
||||
CL_ProcessUserInfo (setinfo.slot, player);
|
||||
}
|
||||
|
@ -1087,8 +1090,7 @@ CL_ServerInfo (void)
|
|||
|
||||
Con_DPrintf ("SERVERINFO: %s=%s\n", block.key, block.value);
|
||||
|
||||
Info_SetValueForKey (cl.serverinfo, block.key, block.value,
|
||||
MAX_SERVERINFO_STRING, 0);
|
||||
Info_SetValueForKey (cl.serverinfo, block.key, block.value, 0);
|
||||
if (strequal (block.key, "chase")) {
|
||||
cl.chase = atoi (block.value);
|
||||
} else if (strequal (block.key, "watervis")) {
|
||||
|
|
|
@ -75,7 +75,7 @@ static const char rcsid[] =
|
|||
typedef struct server_entry_s {
|
||||
char *server;
|
||||
char *desc;
|
||||
char *status;
|
||||
info_t *status;
|
||||
int waitstatus;
|
||||
double pingsent;
|
||||
double pongback;
|
||||
|
@ -480,11 +480,15 @@ SL_Con_Details (server_entry_t *sldata, int slitemno)
|
|||
Con_Printf("N/A\n");
|
||||
if (cp->status)
|
||||
{
|
||||
char *s;
|
||||
|
||||
Con_Printf("Name: %s\n", cp->desc);
|
||||
Con_Printf("Game: %s\n", Info_ValueForKey (cp->status, "*gamedir"));
|
||||
Con_Printf("Map: %s\n", Info_ValueForKey (cp->status, "map"));
|
||||
for (i = 0; i < strlen(cp->status); i++)
|
||||
if (cp->status[i] == '\n')
|
||||
|
||||
s = Info_MakeString (cp->status, 0);
|
||||
for (i = 0; i < strlen (s); i++)
|
||||
if (s[i] == '\n')
|
||||
playercount++;
|
||||
Con_Printf("Players: %i/%s\n", playercount,
|
||||
Info_ValueForKey(cp->status, "maxclients"));
|
||||
|
@ -693,13 +697,14 @@ SL_CheckStatus (const char *cs_from, const char *cs_data)
|
|||
{
|
||||
if (strcmp (cs_from, temp->server) == 0)
|
||||
{
|
||||
int i;
|
||||
temp->status = realloc(temp->status, strlen(cs_data) + 1);
|
||||
strcpy(temp->status, cs_data);
|
||||
//int i;
|
||||
if (temp->status)
|
||||
Info_Destroy (temp->status);
|
||||
temp->status = Info_ParseString (cs_data, strlen (cs_data));
|
||||
temp->waitstatus = 0;
|
||||
tmp_desc = Info_ValueForKey (temp->status, "hostname");
|
||||
if (tmp_desc[0] != '\0')
|
||||
{
|
||||
/*FIXME update for new info api
|
||||
if (tmp_desc[0] != '\0') {
|
||||
temp->desc = realloc(temp->desc, strlen(tmp_desc) + 1);
|
||||
strcpy(temp->desc, tmp_desc);
|
||||
} else {
|
||||
|
@ -707,11 +712,11 @@ SL_CheckStatus (const char *cs_from, const char *cs_data)
|
|||
strcpy(temp->desc, temp->server);
|
||||
}
|
||||
for (i = 0; i < strlen(temp->status); i++)
|
||||
if (temp->status[i] == '\n')
|
||||
{
|
||||
if (temp->status[i] == '\n') {
|
||||
temp->status[i] = '\\';
|
||||
break;
|
||||
}
|
||||
*/
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,8 +82,7 @@ SV_Gamedir_f (void)
|
|||
COM_Gamedir (dir);
|
||||
|
||||
if (is_server) {
|
||||
Info_SetValueForStarKey (svs_info, "*gamedir", dir,
|
||||
MAX_SERVERINFO_STRING, 0);
|
||||
Info_SetValueForStarKey (*svs_info, "*gamedir", dir, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ Skin_Find (player_info_t *sc)
|
|||
strcpy (name, "base");
|
||||
|
||||
if (!allskins[0] && (!s || !strcaseequal (name, s)))
|
||||
Info_SetValueForKey (sc->userinfo, "skin", name, MAX_INFO_STRING, 1);
|
||||
Info_SetValueForKey (sc->userinfo, "skin", name, 1);
|
||||
|
||||
COM_StripExtension (name, name);
|
||||
|
||||
|
|
|
@ -866,7 +866,7 @@ SV_Serverinfo_f (void)
|
|||
return;
|
||||
}
|
||||
Info_SetValueForKey (svs.info, Cmd_Argv (1), Cmd_Argv (2),
|
||||
MAX_SERVERINFO_STRING, !sv_highchars->int_val);
|
||||
!sv_highchars->int_val);
|
||||
|
||||
// if this is a cvar, change it too
|
||||
var = Cvar_FindVar (Cmd_Argv (1));
|
||||
|
@ -902,7 +902,7 @@ SV_Localinfo_f (void)
|
|||
return;
|
||||
}
|
||||
Info_SetValueForKey (localinfo, Cmd_Argv (1), Cmd_Argv (2),
|
||||
MAX_LOCALINFO_STRING, !sv_highchars->int_val);
|
||||
!sv_highchars->int_val);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -953,7 +953,7 @@ SV_Gamedir (void)
|
|||
return;
|
||||
}
|
||||
|
||||
Info_SetValueForStarKey (svs.info, "*gamedir", dir, MAX_SERVERINFO_STRING,
|
||||
Info_SetValueForStarKey (svs.info, "*gamedir", dir,
|
||||
!sv_highchars->int_val);
|
||||
}
|
||||
|
||||
|
@ -1102,8 +1102,7 @@ SV_InitOperatorCommands (void)
|
|||
{
|
||||
if (COM_CheckParm ("-cheats")) {
|
||||
sv_allow_cheats = true;
|
||||
Info_SetValueForStarKey (svs.info, "*cheats", "ON",
|
||||
MAX_SERVERINFO_STRING, 0);
|
||||
Info_SetValueForStarKey (svs.info, "*cheats", "ON", 0);
|
||||
}
|
||||
|
||||
Cmd_AddCommand ("logfile", SV_Logfile_f, "Toggles logging of console text "
|
||||
|
|
|
@ -62,11 +62,9 @@ Cvar_Info (cvar_t *var)
|
|||
}
|
||||
*p = 0;
|
||||
Info_SetValueForKey (svs.info, var->name, info,
|
||||
MAX_SERVERINFO_STRING,
|
||||
(sv_highchars && !sv_highchars->int_val));
|
||||
} else
|
||||
Info_SetValueForKey (svs.info, var->name, var->string,
|
||||
MAX_SERVERINFO_STRING,
|
||||
(sv_highchars && !sv_highchars->int_val));
|
||||
|
||||
SV_SendServerInfoChange (var->name, var->string);
|
||||
|
|
|
@ -39,6 +39,7 @@ static const char rcsid[] =
|
|||
|
||||
#include "QF/crc.h"
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/info.h"
|
||||
#include "QF/msg.h"
|
||||
#include "QF/va.h"
|
||||
#include "QF/vfs.h"
|
||||
|
@ -50,7 +51,7 @@ static const char rcsid[] =
|
|||
#include "sv_progs.h"
|
||||
#include "world.h"
|
||||
|
||||
char localinfo[MAX_LOCALINFO_STRING + 1]; // local game info
|
||||
info_t *localinfo; // local game info
|
||||
char localmodels[MAX_MODELS][5]; // inline model names for precache
|
||||
|
||||
entity_state_t baselines[MAX_EDICTS];
|
||||
|
@ -332,7 +333,7 @@ SV_SpawnServer (const char *server)
|
|||
// edict is
|
||||
SV_LoadProgs ();
|
||||
Info_SetValueForStarKey (svs.info, "*progs", va ("%i", sv_pr_state.crc),
|
||||
MAX_SERVERINFO_STRING, !sv_highchars->int_val);
|
||||
!sv_highchars->int_val);
|
||||
|
||||
// allocate edicts
|
||||
sv.edicts = PR_InitEdicts (&sv_pr_state, MAX_EDICTS);
|
||||
|
@ -423,7 +424,6 @@ SV_SpawnServer (const char *server)
|
|||
SV_CreateBaseline ();
|
||||
sv.signon_buffer_size[sv.num_signon_buffers - 1] = sv.signon.cursize;
|
||||
|
||||
Info_SetValueForKey (svs.info, "map", sv.name, MAX_SERVERINFO_STRING,
|
||||
!sv_highchars->int_val);
|
||||
Info_SetValueForKey (svs.info, "map", sv.name, !sv_highchars->int_val);
|
||||
Con_DPrintf ("Server spawned.\n");
|
||||
}
|
||||
|
|
|
@ -327,7 +327,9 @@ SV_DropClient (client_t *drop)
|
|||
drop->old_frags = 0;
|
||||
SVfloat (drop->edict, frags) = 0;
|
||||
drop->name[0] = 0;
|
||||
memset (drop->userinfo, 0, sizeof (drop->userinfo));
|
||||
|
||||
Info_Destroy (drop->userinfo);
|
||||
drop->userinfo = 0;
|
||||
|
||||
// send notification to all remaining clients
|
||||
SV_FullClientUpdate (drop, &sv.reliable_datagram);
|
||||
|
@ -355,6 +357,12 @@ SV_CalcPing (client_t *cl)
|
|||
return ping * 1000;
|
||||
}
|
||||
|
||||
static int
|
||||
make_info_string_filter (const char *key)
|
||||
{
|
||||
return *key == '_' || Info_FilterForKey (key, client_info_filters);
|
||||
}
|
||||
|
||||
/*
|
||||
SV_FullClientUpdate
|
||||
|
||||
|
@ -363,7 +371,7 @@ SV_CalcPing (client_t *cl)
|
|||
void
|
||||
SV_FullClientUpdate (client_t *client, sizebuf_t *buf)
|
||||
{
|
||||
char info[MAX_INFO_STRING];
|
||||
char *info;
|
||||
int i;
|
||||
net_svc_updateuserinfo_t block;
|
||||
|
||||
|
@ -387,8 +395,8 @@ SV_FullClientUpdate (client_t *client, sizebuf_t *buf)
|
|||
MSG_WriteByte (buf, i);
|
||||
MSG_WriteFloat (buf, realtime - client->connection_started);
|
||||
|
||||
strncpy (info, client->userinfo, sizeof (info));
|
||||
Info_RemovePrefixedKeys (info, '_', client_info_filters); // server passwords, etc
|
||||
info = client->userinfo ? Info_MakeString (client->userinfo,
|
||||
make_info_string_filter) : "";
|
||||
|
||||
block.slot = i;
|
||||
block.userid = client->userid;
|
||||
|
@ -405,7 +413,9 @@ SV_FullClientUpdate (client_t *client, sizebuf_t *buf)
|
|||
void
|
||||
SV_FullClientUpdateToClient (client_t *client, client_t *cl)
|
||||
{
|
||||
ClientReliableCheckBlock (cl, 24 + strlen (client->userinfo));
|
||||
if (client->state < cs_connected)
|
||||
return;
|
||||
ClientReliableCheckBlock (cl, 24 + client->userinfo->cursize);
|
||||
if (cl->num_backbuf) {
|
||||
SV_FullClientUpdate (client, &cl->backbuf);
|
||||
ClientReliable_FinishWrite (cl);
|
||||
|
@ -507,7 +517,7 @@ SVC_Status (void)
|
|||
con_printf_no_log = 1;
|
||||
Cmd_TokenizeString ("status");
|
||||
SV_BeginRedirect (RD_PACKET);
|
||||
SV_Printf ("%s\n", svs.info);
|
||||
SV_Printf ("%s\n", Info_MakeString (svs.info, 0));
|
||||
for (i = 0; i < MAX_CLIENTS; i++) {
|
||||
cl = &svs.clients[i];
|
||||
if ((cl->state == cs_connected || cl->state == cs_spawned)
|
||||
|
@ -670,7 +680,7 @@ SVC_GetChallenge (void)
|
|||
void
|
||||
SVC_DirectConnect (void)
|
||||
{
|
||||
char userinfo[1024];
|
||||
info_t *userinfo;
|
||||
const char *s;
|
||||
client_t *cl, *newcl;
|
||||
client_t temp;
|
||||
|
@ -695,12 +705,10 @@ SVC_DirectConnect (void)
|
|||
|
||||
challenge = atoi (Cmd_Argv (3));
|
||||
|
||||
// note an extra byte is needed to replace spectator key
|
||||
strncpy (userinfo, Cmd_Argv (4), sizeof (userinfo) - 2);
|
||||
userinfo[sizeof (userinfo) - 2] = 0;
|
||||
userinfo = Info_ParseString (Cmd_Argv (4), 1023);
|
||||
|
||||
// Validate the userinfo string.
|
||||
if (!Info_Validate(userinfo)) {
|
||||
if (!userinfo) {
|
||||
Netchan_OutOfBandPrint (net_from, "%c\nInvalid userinfo string.\n",
|
||||
A2C_PRINT);
|
||||
return;
|
||||
|
@ -750,7 +758,7 @@ SVC_DirectConnect (void)
|
|||
return;
|
||||
}
|
||||
Info_RemoveKey (userinfo, "spectator"); // remove passwd
|
||||
Info_SetValueForStarKey (userinfo, "*spectator", "1", MAX_INFO_STRING,
|
||||
Info_SetValueForStarKey (userinfo, "*spectator", "1",
|
||||
!sv_highchars->int_val);
|
||||
spectator = true;
|
||||
} else {
|
||||
|
@ -786,7 +794,7 @@ SVC_DirectConnect (void)
|
|||
if (*q > 31 && *q <= 127)
|
||||
*p++ = *q;
|
||||
} else
|
||||
strncpy (newcl->userinfo, userinfo, sizeof (newcl->userinfo) - 1);
|
||||
newcl->userinfo = userinfo;
|
||||
|
||||
// if there is allready a slot for this ip, drop it
|
||||
for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) {
|
||||
|
@ -1801,11 +1809,11 @@ SV_CheckVars (void)
|
|||
|
||||
SV_Printf ("Updated needpass.\n");
|
||||
if (!v)
|
||||
Info_SetValueForKey (svs.info, "needpass", "", MAX_SERVERINFO_STRING,
|
||||
Info_SetValueForKey (svs.info, "needpass", "",
|
||||
!sv_highchars->int_val);
|
||||
else
|
||||
Info_SetValueForKey (svs.info, "needpass", va ("%i", v),
|
||||
MAX_SERVERINFO_STRING, !sv_highchars->int_val);
|
||||
!sv_highchars->int_val);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2083,13 +2091,13 @@ SV_InitLocal (void)
|
|||
snprintf (localmodels[i], sizeof (localmodels[i]), "*%i", i);
|
||||
|
||||
Info_SetValueForStarKey (svs.info, "*version", QW_VERSION,
|
||||
MAX_SERVERINFO_STRING, !sv_highchars->int_val);
|
||||
!sv_highchars->int_val);
|
||||
|
||||
// Brand server as QF, with appropriate QSG standards version --KB
|
||||
Info_SetValueForStarKey (svs.info, "*qf_version", VERSION,
|
||||
MAX_SERVERINFO_STRING, !sv_highchars->int_val);
|
||||
!sv_highchars->int_val);
|
||||
Info_SetValueForStarKey (svs.info, "*qsg_version", QW_QSG_VERSION,
|
||||
MAX_SERVERINFO_STRING, !sv_highchars->int_val);
|
||||
!sv_highchars->int_val);
|
||||
|
||||
CF_Init ();
|
||||
|
||||
|
@ -2242,7 +2250,7 @@ SV_ExtractFromUserinfo (client_t *cl)
|
|||
|
||||
// set the name
|
||||
if (strcmp (newname, val) || strcmp (cl->name, newname)) {
|
||||
Info_SetValueForKey (cl->userinfo, "name", newname, MAX_INFO_STRING,
|
||||
Info_SetValueForKey (cl->userinfo, "name", newname,
|
||||
!sv_highchars->int_val);
|
||||
val = Info_ValueForKey (cl->userinfo, "name");
|
||||
SVstring (cl->edict, netname) = PR_SetString (&sv_pr_state, newname);
|
||||
|
@ -2353,6 +2361,9 @@ SV_Init (void)
|
|||
Sys_Init_Cvars ();
|
||||
Sys_Init ();
|
||||
|
||||
svs.info = Info_ParseString ("", MAX_SERVERINFO_STRING);
|
||||
localinfo = Info_ParseString ("", MAX_LOCALINFO_STRING);
|
||||
|
||||
Cbuf_Init ();
|
||||
Cmd_Init ();
|
||||
SV_InitOperatorCommands ();
|
||||
|
|
|
@ -1361,11 +1361,10 @@ PF_setinfokey (progs_t *pr)
|
|||
net_svc_setinfo_t block;
|
||||
|
||||
if (e1 == 0) {
|
||||
Info_SetValueForKey (localinfo, key, value, MAX_LOCALINFO_STRING,
|
||||
!sv_highchars->int_val);
|
||||
Info_SetValueForKey (localinfo, key, value, !sv_highchars->int_val);
|
||||
} else if (e1 <= MAX_CLIENTS) {
|
||||
Info_SetValueForKey (svs.clients[e1 - 1].userinfo, key, value,
|
||||
MAX_INFO_STRING, !sv_highchars->int_val);
|
||||
!sv_highchars->int_val);
|
||||
SV_ExtractFromUserinfo (&svs.clients[e1 - 1]);
|
||||
|
||||
if (Info_FilterForKey (key, client_info_filters)) {
|
||||
|
|
|
@ -155,8 +155,7 @@ parse_field (progs_t *pr, const char *key, const char *value)
|
|||
if (strcaseequal (key, "skyname") // QuakeForge
|
||||
|| strcaseequal (key, "sky") // Q2/DarkPlaces
|
||||
|| strcaseequal (key, "qlsky")) { // QuakeLives
|
||||
Info_SetValueForKey (svs.info, "skybox", "1", MAX_SERVERINFO_STRING,
|
||||
!sv_highchars->int_val);
|
||||
Info_SetValueForKey (svs.info, "skybox", "1", !sv_highchars->int_val);
|
||||
Cvar_Set (r_skyname, value);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ static const char rcsid[] =
|
|||
qboolean is_server = true;
|
||||
qboolean stdin_ready;
|
||||
server_static_t svs;
|
||||
char *svs_info = svs.info;
|
||||
info_t **svs_info = &svs.info;
|
||||
|
||||
void
|
||||
Sys_Init (void)
|
||||
|
|
|
@ -141,7 +141,8 @@ SV_New_f (void)
|
|||
// send server info string
|
||||
MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
|
||||
MSG_WriteString (&host_client->netchan.message,
|
||||
va ("fullserverinfo \"%s\"\n", svs.info));
|
||||
va ("fullserverinfo \"%s\"\n",
|
||||
Info_MakeString (svs.info, 0)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1165,7 +1166,7 @@ SV_SetInfo_f (void)
|
|||
|
||||
strcpy (oldval, Info_ValueForKey (host_client->userinfo, Cmd_Argv (1)));
|
||||
Info_SetValueForKey (host_client->userinfo, Cmd_Argv (1), Cmd_Argv (2),
|
||||
MAX_INFO_STRING, !sv_highchars->int_val);
|
||||
!sv_highchars->int_val);
|
||||
if (strequal
|
||||
(Info_ValueForKey (host_client->userinfo, Cmd_Argv (1)), oldval))
|
||||
return; // key hasn't changed
|
||||
|
|
Loading…
Reference in a new issue