/* ================== Host_Changelevel_f Goes to a new map, taking all clients along ================== */ static void Host_Changelevel_f (void) { char level[MAX_QPATH]; char _startspot[MAX_QPATH]; char *startspot; if (Cmd_Argc() < 2) { Con_Printf ("changelevel <levelname> : continue game on a new level\n"); return; } if (!sv.active || cls.demoplayback) { Con_Printf ("Only the server may changelevel\n"); return; } q_snprintf (level, sizeof(level), "maps/%s.bsp", Cmd_Argv(1)); if (!FS_FileExists(level, NULL)) Host_Error ("%s: cannot find map %s", __thisfunc__, level); q_strlcpy (level, Cmd_Argv(1), sizeof(level)); if (Cmd_Argc() == 2) startspot = NULL; else { q_strlcpy (_startspot, Cmd_Argv(2), sizeof(_startspot)); startspot = _startspot; } SV_SaveSpawnparms (); SV_SpawnServer (level, startspot); if (!sv.active) Host_Error ("%s: cannot run map %s", __thisfunc__, level); }
/* ================== Host_Restart_f Restarts the current server for a dead player ================== */ static void Host_Restart_f (void) { char mapname[MAX_QPATH]; char startspot[MAX_QPATH]; if (cls.demoplayback || !sv.active) return; if (cmd_source != src_command) return; q_strlcpy (mapname, sv.name, sizeof(mapname)); // mapname gets cleared in spawnserver q_strlcpy (startspot, sv.startspot, sizeof(startspot)); if (Cmd_Argc() == 2 && q_strcasecmp(Cmd_Argv(1),"restore") == 0) { if (LoadGamestate(mapname, startspot, 3) != 0) { SV_SpawnServer (mapname, startspot); if (!sv.active) Host_Error ("%s: cannot restart map %s", __thisfunc__, mapname); RestoreClients (0); } } else { SV_SpawnServer (mapname, startspot); if (!sv.active) Host_Error ("%s: cannot restart map %s", __thisfunc__, mapname); } }
/* ================== Host_Changelevel_f Goes to a new map, taking all clients along ================== */ void Host_Changelevel_f (void) { char level[MAX_QPATH]; if (Cmd_Argc() != 2) { Con_Printf ("changelevel <levelname> : continue game on a new level\n"); return; } if (!sv.active || cls.demoplayback) { Con_Printf ("Only the server may changelevel\n"); return; } //johnfitz -- check for client having map before anything else q_snprintf (level, sizeof(level), "maps/%s.bsp", Cmd_Argv(1)); if (!COM_FileExists(level, NULL)) Host_Error ("cannot find map %s", level); //johnfitz if (cls.state != ca_dedicated) IN_Activate(); // -- S.A. key_dest = key_game; // remove console or menu SV_SaveSpawnparms (); q_strlcpy (level, Cmd_Argv(1), sizeof(level)); SV_SpawnServer (level); // also issue an error if spawn failed -- O.S. if (!sv.active) Host_Error ("cannot run map %s", level); }
void Modlist_Add (const char *name) { mod_t *mod,*cursor,*prev; //ingore duplicate for (mod = modlist; mod; mod = mod->next) { if (!Q_strcmp (name, mod->name)) return; } mod = (mod_t *) Z_Malloc(sizeof(mod_t)); q_strlcpy (mod->name, name, sizeof(mod->name)); //insert each entry in alphabetical order if (modlist == NULL || Q_strcasecmp(mod->name, modlist->name) < 0) //insert at front { mod->next = modlist; modlist = mod; } else //insert later { prev = modlist; cursor = modlist->next; while (cursor && (Q_strcasecmp(mod->name, cursor->name) > 0)) { prev = cursor; cursor = cursor->next; } mod->next = prev->next; prev->next = mod; } }
/* ============ COM_FileBase take 'somedir/otherdir/filename.ext', write only 'filename' to the output ============ */ void COM_FileBase (const char *in, char *out, size_t outsize) { const char *dot, *slash, *s; s = in; slash = in; dot = NULL; while (*s) { if (*s == '/') slash = s + 1; if (*s == '.') dot = s; s++; } if (dot == NULL) dot = s; if (dot - slash < 2) q_strlcpy (out, "?model?", outsize); else { size_t len = dot - slash; if (len >= outsize) len = outsize - 1; memcpy (out, slash, len); out[len] = '\0'; } }
/* =================== Hunk_AllocName =================== */ void *Hunk_AllocName (int size, const char *name) { hunk_t *h; #ifdef PARANOID Hunk_Check (); #endif if (size < 0) Sys_Error ("Hunk_Alloc: bad size: %i", size); size = sizeof(hunk_t) + ((size+15)&~15); if (hunk_size - hunk_low_used - hunk_high_used < size) Sys_Error ("Hunk_Alloc: failed on %i bytes",size); h = (hunk_t *)(hunk_base + hunk_low_used); hunk_low_used += size; Cache_FreeLow (hunk_low_used); memset (h, 0, size); h->size = size; h->sentinal = HUNK_SENTINAL; q_strlcpy (h->name, name, HUNKNAME_LEN); return (void *)(h+1); }
/* ================== FileList_Add ================== */ void FileList_Add (const char *name, filelist_item_t **list) { filelist_item_t *item,*cursor,*prev; // ignore duplicate for (item = *list; item; item = item->next) { if (!Q_strcmp (name, item->name)) return; } item = (filelist_item_t *) Z_Malloc(sizeof(filelist_item_t)); q_strlcpy (item->name, name, sizeof(item->name)); // insert each entry in alphabetical order if (*list == NULL || q_strcasecmp(item->name, (*list)->name) < 0) //insert at front { item->next = *list; *list = item; } else //insert later { prev = *list; cursor = (*list)->next; while (cursor && (q_strcasecmp(item->name, cursor->name) > 0)) { prev = cursor; cursor = cursor->next; } item->next = prev->next; prev->next = item; } }
/* ================== S_FindName ================== */ static sfx_t *S_FindName (const char *name) { int i; sfx_t *sfx; if (!name) Sys_Error ("S_FindName: NULL"); if (Q_strlen(name) >= MAX_QPATH) Sys_Error ("Sound name too long: %s", name); // see if already loaded for (i = 0; i < num_sfx; i++) { if (!Q_strcmp(known_sfx[i].name, name)) { return &known_sfx[i]; } } if (num_sfx == MAX_SFX) Sys_Error ("S_FindName: out of sfx_t"); sfx = &known_sfx[i]; q_strlcpy (sfx->name, name, sizeof(sfx->name)); num_sfx++; return sfx; }
/* ====================== Host_Map_f handle a map <servername> command from the console. Active clients are kicked off. ====================== */ void Host_Map_f (void) { int i; char name[MAX_QPATH], *p; if (Cmd_Argc() < 2) //no map name given { if (cls.state == ca_dedicated) { if (sv.active) Con_Printf ("Current map: %s\n", sv.name); else Con_Printf ("Server not active\n"); } else if (cls.state == ca_connected) { Con_Printf ("Current map: %s ( %s )\n", cl.levelname, cl.mapname); } else { Con_Printf ("map <levelname>: start a new server\n"); } return; } if (cmd_source != src_command) return; cls.demonum = -1; // stop demo loop in case this fails CL_Disconnect (); Host_ShutdownServer(false); if (cls.state != ca_dedicated) IN_Activate(); key_dest = key_game; // remove console or menu SCR_BeginLoadingPlaque (); svs.serverflags = 0; // haven't completed an episode yet q_strlcpy (name, Cmd_Argv(1), sizeof(name)); // remove (any) trailing ".bsp" from mapname -- S.A. p = strstr(name, ".bsp"); if (p && p[4] == '\0') *p = '\0'; SV_SpawnServer (name); if (!sv.active) return; if (cls.state != ca_dedicated) { memset (cls.spawnparms, 0, MAX_MAPSTRING); for (i = 2; i < Cmd_Argc(); i++) { q_strlcat (cls.spawnparms, Cmd_Argv(i), MAX_MAPSTRING); q_strlcat (cls.spawnparms, " ", MAX_MAPSTRING); } Cmd_ExecuteString ("connect local", src_command); } }
/* ============== Cache_Alloc ============== */ void *Cache_Alloc (cache_user_t *c, int size, const char *name) { cache_system_t *cs; if (c->data) Sys_Error ("Cache_Alloc: allready allocated"); if (size <= 0) Sys_Error ("Cache_Alloc: size %i", size); size = (size + sizeof(cache_system_t) + 15) & ~15; // find memory for it while (1) { cs = Cache_TryAlloc (size, false); if (cs) { q_strlcpy (cs->name, name, CACHENAME_LEN); c->data = (void *)(cs+1); cs->user = c; break; } // free the least recently used cahedat if (cache_head.lru_prev == &cache_head) Sys_Error ("Cache_Alloc: out of memory"); // not enough memory at all Cache_Free (cache_head.lru_prev->user, true); //johnfitz -- added second argument } return Cache_Check (c); }
/* ================== Mod_FindName ================== */ model_t *Mod_FindName (const char *name) { int i; model_t *mod; if (!name[0]) SV_Error ("%s: NULL name", __thisfunc__); // // search the currently loaded models // for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++) { if (!strcmp (mod->name, name) ) break; } if (i == mod_numknown) { if (mod_numknown == MAX_MOD_KNOWN) SV_Error ("mod_numknown == MAX_MOD_KNOWN"); q_strlcpy (mod->name, name, MAX_QPATH); mod->needload = NL_NEEDS_LOADED; mod_numknown++; } return mod; }
/* ============== Cache_Alloc ============== */ void *Cache_Alloc (cache_user_t *c, int size, const char *name) { cache_system_t *cs; if (c->data) Sys_Error ("%s: %s is already allocated", __thisfunc__, name); if (size <= 0) Sys_Error ("%s: bad size %i for %s", __thisfunc__, size, name); size = (size + sizeof(cache_system_t) + 15) & ~15; // find memory for it while (1) { cs = Cache_TryAlloc (size, false); if (cs) { q_strlcpy (cs->name, name, CACHENAME_LEN); c->data = (void *)(cs + 1); cs->user = c; break; } // free the least recently used cahedat if (cache_head.lru_prev == &cache_head) // not enough memory at all Sys_Error ("%s: out of memory", __thisfunc__); Cache_Free ( cache_head.lru_prev->user ); } return Cache_Check (c); }
/* ================== SV_SetInfo_f Allow clients to change userinfo ================== */ static void SV_SetInfo_f (void) { if (Cmd_Argc() == 1) { Con_Printf ("User info settings:\n"); Info_Print (host_client->userinfo); return; } if (Cmd_Argc() != 3) { Con_Printf ("usage: setinfo [ <key> <value> ]\n"); return; } if (Cmd_Argv(1)[0] == '*') return; // don't set priveledged values Info_SetValueForKey (host_client->userinfo, Cmd_Argv(1), Cmd_Argv(2), MAX_INFO_STRING); q_strlcpy (host_client->name, Info_ValueForKey (host_client->userinfo, "name"), sizeof(host_client->name)); // SV_FullClientUpdate (host_client, &sv.reliable_datagram); host_client->sendinfo = true; // process any changed values SV_ExtractFromUserinfo (host_client); }
/* ============ Cvar_RegisterVariable Adds a freestanding variable to the variable list. ============ */ void Cvar_RegisterVariable (cvar_t *variable) { char value[512]; qboolean set_rom; // first check to see if it has already been defined if (Cvar_FindVar (variable->name)) { Con_Printf ("Can't register variable %s, already defined\n", variable->name); return; } // check for overlap with a command if (Cmd_Exists (variable->name)) { Con_Printf ("%s: %s is a command\n", __thisfunc__, variable->name); return; } // link the variable in variable->next = cvar_vars; cvar_vars = variable; // copy the value off, because future sets will Z_Free it q_strlcpy (value, variable->string, sizeof(value)); variable->string = NULL; // set it through the function to be consistant set_rom = (variable->flags & CVAR_ROM); variable->flags &= ~CVAR_ROM; Cvar_Set (variable->name, value); if (set_rom) variable->flags |= CVAR_ROM; }
void ExtraMaps_Add (const char *name) { extralevel_t *level,*cursor,*prev; // ignore duplicate for (level = extralevels; level; level = level->next) { if (!Q_strcmp (name, level->name)) return; } level = (extralevel_t *) Z_Malloc(sizeof(extralevel_t)); q_strlcpy (level->name, name, sizeof(level->name)); // insert each entry in alphabetical order if (extralevels == NULL || Q_strcasecmp(level->name, extralevels->name) < 0) //insert at front { level->next = extralevels; extralevels = level; } else //insert later { prev = extralevels; cursor = extralevels->next; while (cursor && (Q_strcasecmp(level->name, cursor->name) > 0)) { prev = cursor; cursor = cursor->next; } level->next = prev->next; prev->next = level; } }
size_t qerr_strlcpy (const char *caller, int linenum, char *dst, const char *src, size_t size) { size_t ret = q_strlcpy (dst, src, size); if (ret >= size) Sys_Error("%s: %d: string buffer overflow!", caller, linenum); return ret; }
/* ================== Host_Changelevel2_f changing levels within a unit ================== */ static void Host_Changelevel2_f (void) { char level[MAX_QPATH]; char _startspot[MAX_QPATH]; char *startspot; if (Cmd_Argc() < 2) { Con_Printf ("changelevel2 <levelname> : continue game on a new level in the unit\n"); return; } if (!sv.active || cls.demoplayback) { Con_Printf ("Only the server may changelevel\n"); return; } q_snprintf (level, sizeof(level), "maps/%s.bsp", Cmd_Argv(1)); if (!FS_FileExists(level, NULL)) Host_Error ("%s: cannot find map %s", __thisfunc__, level); q_strlcpy (level, Cmd_Argv(1), sizeof(level)); if (Cmd_Argc() == 2) startspot = NULL; else { q_strlcpy (_startspot, Cmd_Argv(2), sizeof(_startspot)); startspot = _startspot; } SV_SaveSpawnparms (); // save the current level's state old_svtime = sv.time; if (SaveGamestate(false) != 0) return; // try to restore the new level if (LoadGamestate(level, startspot, 0) != 0) { SV_SpawnServer (level, startspot); if (!sv.active) Host_Error ("%s: cannot run map %s", __thisfunc__, level); RestoreClients (0); } }
/* ====================== Host_Name_f ====================== */ static void Host_Name_f (void) { char newName[32]; char *pdest; if (Cmd_Argc () == 1) { Con_Printf ("\"name\" is \"%s\"\n", cl_name.string); return; } if (Cmd_Argc () == 2) q_strlcpy (newName, Cmd_Argv(1), sizeof(newName)); else q_strlcpy (newName, Cmd_Args(), sizeof(newName)); newName[15] = 0; // client_t structure actually says name[32]. //this is for the fuckers who put braces in the name causing loadgame to crash. pdest = strchr(newName,'{'); if (pdest) { *pdest = 0; //zap the brace Con_Printf ("Illegal char in name removed!\n"); } if (cmd_source == src_command) { if (strcmp(cl_name.string, newName) == 0) return; Cvar_Set ("_cl_name", newName); if (cls.state == ca_connected) Cmd_ForwardToServer (); return; } if (host_client->name[0] && strcmp(host_client->name, "unconnected") ) if (strcmp(host_client->name, newName) != 0) Con_Printf ("%s renamed to %s\n", host_client->name, newName); strcpy (host_client->name, newName); host_client->edict->v.netname = PR_SetEngineString(host_client->name); // send notification to all clients MSG_WriteByte (&sv.reliable_datagram, svc_updatename); MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients); MSG_WriteString (&sv.reliable_datagram, host_client->name); }
/* ============== S_LoadSound ============== */ sfxcache_t *S_LoadSound (sfx_t *s) { char namebuffer[256]; byte *data; wavinfo_t info; int len; float stepscale; sfxcache_t *sc; byte stackbuf[1*1024]; // avoid dirtying the cache heap // see if still in memory sc = (sfxcache_t *) Cache_Check (&s->cache); if (sc) return sc; // Con_Printf ("%s: %x\n", __thisfunc__, (int)stackbuf); // load it in q_strlcpy(namebuffer, "sound/", sizeof(namebuffer)); q_strlcat(namebuffer, s->name, sizeof(namebuffer)); // Con_Printf ("loading %s\n",namebuffer); data = FS_LoadStackFile(namebuffer, stackbuf, sizeof(stackbuf)); if (!data) { Con_Printf ("Couldn't load %s\n", namebuffer); return NULL; } info = GetWavinfo (s->name, data, fs_filesize); if (info.channels != 1) { Con_Printf ("%s is a stereo sample\n",s->name); return NULL; } stepscale = (float)info.rate / shm->speed; len = info.samples / stepscale; len = len * info.width * info.channels; sc = (sfxcache_t *) Cache_Alloc ( &s->cache, len + sizeof(sfxcache_t), s->name); if (!sc) return NULL; sc->length = info.samples; sc->loopstart = info.loopstart; sc->speed = info.rate; sc->width = info.width; sc->stereo = info.channels; ResampleSfx (s, sc->speed, sc->width, data + info.dataofs); return sc; }
/* ====================== Host_Name_f ====================== */ void Host_Name_f (void) { char newName[32]; if (Cmd_Argc () == 1) { Con_Printf ("\"name\" is \"%s\"\n", cl_name.string); return; } if (Cmd_Argc () == 2) q_strlcpy(newName, Cmd_Argv(1), sizeof(newName)); else q_strlcpy(newName, Cmd_Args(), sizeof(newName)); newName[15] = 0; // client_t structure actually says name[32]. if (cmd_source == src_command) { if (Q_strcmp(cl_name.string, newName) == 0) return; Cvar_Set ("_cl_name", newName); if (cls.state == ca_connected) Cmd_ForwardToServer (); return; } if (host_client->name[0] && strcmp(host_client->name, "unconnected") ) { if (Q_strcmp(host_client->name, newName) != 0) Con_Printf ("%s renamed to %s\n", host_client->name, newName); } Q_strcpy (host_client->name, newName); host_client->edict->v.netname = PR_SetEngineString(host_client->name); // send notification to all clients MSG_WriteByte (&sv.reliable_datagram, svc_updatename); MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients); MSG_WriteString (&sv.reliable_datagram, host_client->name); }
/* ===================== Host_Connect_f User command to connect to server ===================== */ void Host_Connect_f (void) { char name[MAX_QPATH]; cls.demonum = -1; // stop demo loop in case this fails if (cls.demoplayback) { CL_StopPlayback (); CL_Disconnect (); } q_strlcpy (name, Cmd_Argv(1), sizeof(name)); CL_EstablishConnection (name); Host_Reconnect_f (); }
/* ================== Host_Restart_f Restarts the current server for a dead player ================== */ void Host_Restart_f (void) { char mapname[MAX_QPATH]; if (cls.demoplayback || !sv.active) return; if (cmd_source != src_command) return; q_strlcpy (mapname, sv.name, sizeof(mapname)); // mapname gets cleared in spawnserver SV_SpawnServer (mapname); if (!sv.active) Host_Error ("cannot restart map %s", mapname); }
static void Cache_Print (qboolean write_file) { cache_system_t *cd; FILE *FH; int count, sum; int num_mod, sum_mod; int num_wav, sum_wav; char temp[128]; FH = NULL; if (write_file) FH = fopen(va("%s/cache.txt", fs_userdir),"w"); count = sum = 0; num_mod = sum_mod = 0; num_wav = sum_wav = 0; for (cd = cache_head.next ; cd != &cache_head ; cd = cd->next) { MEM_Printf(FH,"%8i : %s\n", cd->size, cd->name); count++; sum += cd->size; q_strlcpy (temp, cd->name, sizeof(temp)); q_strlwr(temp); if (strstr(temp,".mdl")) { num_mod++; sum_mod += cd->size; } else if (strstr(temp,".wav")) { num_wav++; sum_wav += cd->size; } } MEM_Printf(FH,"-------- ------------------\n"); MEM_Printf(FH,"%8i : Total of %i items\n",sum,count); MEM_Printf(FH,"%8i : Total .MDL of %i items\n",sum_mod,num_mod); MEM_Printf(FH,"%8i : Total .WAV of %i items\n",sum_wav,num_wav); if (FH) { fclose(FH); Con_Printf ("Wrote to cache.txt\n"); } }
/* ============ COM_StripExtension ============ */ void COM_StripExtension (const char *in, char *out, size_t outsize) { int length; if (in != out) /* copy when not in-place editing */ q_strlcpy (out, in, outsize); length = (int)strlen(out) - 1; while (length > 0 && out[length] != '.') { --length; if (out[length] == '/' || out[length] == '\\') return; /* no extension */ } if (length > 0) out[length] = '\0'; }
void LoadTriangleList(const char *fileName, triangle_t **triList, int *triangleCount) { FILE *input; q_strlcpy(InputFileName, fileName, sizeof(InputFileName)); StripExtension(InputFileName); q_strlcat(InputFileName, ".asc", sizeof(InputFileName)); if ((input = fopen(InputFileName, "rb")) != NULL) { fclose(input); LoadASC(InputFileName, triList, triangleCount); return; } StripExtension(InputFileName); q_strlcat(InputFileName, ".hrc", sizeof(InputFileName)); if ((input = fopen(InputFileName, "rb")) != NULL) { fclose(input); LoadHRC(InputFileName, triList, triangleCount); return; } StripExtension(InputFileName); q_strlcat(InputFileName, ".htr", sizeof(InputFileName)); if ((input = fopen(InputFileName, "rb")) != NULL) { fclose(input); LoadHTR(InputFileName, triList, triangleCount); return; } StripExtension(InputFileName); q_strlcat(InputFileName, ".tri", sizeof(InputFileName)); if ((input = fopen(InputFileName, "rb")) != NULL) { LoadTRI(input, triList, triangleCount); fclose(input); return; } COM_Error("Could not open file '%s':\n" "No ASC, HRC, HTR, or TRI match.\n", fileName); }
static void S_Play (void) { static int hash = 345; int i; char name[256]; sfx_t *sfx; i = 1; while (i < Cmd_Argc()) { q_strlcpy(name, Cmd_Argv(i), sizeof(name)); if (!Q_strrchr(Cmd_Argv(i), '.')) { q_strlcat(name, ".wav", sizeof(name)); } sfx = S_PrecacheSound(name); S_StartSound(hash++, 0, sfx, listener_origin, 1.0, 1.0); i++; } }
/* ============ COM_FileExtension ============ */ void COM_FileExtension (const char *in, char *out, size_t outsize) { const char *src; size_t len; len = strlen(in); if (len < 2) /* nothing meaningful */ { _noext: *out = '\0'; return; } src = in + len - 1; while (src != in && src[-1] != '.') src--; if (src == in || strchr(src, '/') != NULL || strchr(src, '\\') != NULL) goto _noext; /* no extension, at not least in the file itself. */ q_strlcpy (out, src, outsize); }
// recognize ip:port (based on ProQuake) static const char *Strip_Port (const char *host) { static char noport[MAX_QPATH]; /* array size as in Host_Connect_f() */ char *p; int port; if (!host || !*host) return host; q_strlcpy (noport, host, sizeof(noport)); if ((p = Q_strrchr(noport, ':')) == NULL) return host; *p++ = '\0'; port = Q_atoi (p); if (port > 0 && port < 65536 && port != net_hostport) { net_hostport = port; Con_Printf("Port set to %d\n", net_hostport); } return noport; }
/* =================== CFG_ReadCvarOverrides convenience function, reading the "+" command line override values of cvars in the given list. doesn't do anything with the config file. =================== */ void CFG_ReadCvarOverrides (const char **vars, int num_vars) { char buff[64]; int i, j; if (num_vars < 1) return; buff[0] = '+'; for (i = 0; i < num_vars; i++) { q_strlcpy (&buff[1], vars[i], sizeof(buff) - 1); j = COM_CheckParm(buff); if (j != 0 && j < com_argc - 1) { if (com_argv[j + 1][0] != '-' && com_argv[j + 1][0] != '+') Cvar_Set(vars[i], com_argv[j + 1]); } } }
static void S_PlayVol (void) { static int hash = 543; int i; float vol; char name[256]; sfx_t *sfx; i = 1; while (i < Cmd_Argc()) { q_strlcpy(name, Cmd_Argv(i), sizeof(name)); if (!Q_strrchr(Cmd_Argv(i), '.')) { q_strlcat(name, ".wav", sizeof(name)); } sfx = S_PrecacheSound(name); vol = Q_atof(Cmd_Argv(i + 1)); S_StartSound(hash++, 0, sfx, listener_origin, vol, 1.0); i += 2; } }