static edict_t * KK_Match_Str2 (const char *substr) { int i, j, count; dstring_t *lstr = dstring_new (); dstring_t *lname = dstring_new (); client_t *cl; edict_t *retedict = 0; dstring_copystr (lstr, substr); for (j = 0; lstr->str[j]; j++) lstr->str[j] = KK_qwchar (lstr->str[j]); for (i = count = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) { if (!cl->state) continue; dstring_copystr (lname, cl->name); for (j = 0; lname->str[j]; j++) lname->str[j] = KK_qwchar (lname->str[j]); if (strstr (lname->str, lstr->str)) { retedict = cl->edict; count++; } } if (count > 1) retedict = 0; dstring_delete (lstr); dstring_delete (lname); return retedict; }
VISIBLE void Cmd_StuffCmds (cbuf_t *cbuf) { int i, j; dstring_t *build; if (!*com_cmdline) return; build = dstring_newstr (); // pull out the commands for (i = 0; com_cmdline[i]; i++) { if (com_cmdline[i] == '+') { i++; for (j = i; (com_cmdline[j] && !((j == 0 || isspace((byte) com_cmdline[j - 1])) && ((com_cmdline[j] == '+') || (com_cmdline[j] == '-')))); j++) ; dstring_appendsubstr (build, com_cmdline + i, j - i); dstring_appendstr (build, "\n"); i = j - 1; } } if (build->str[0]) Cbuf_InsertText (cbuf, build->str); dstring_delete (build); }
void glsl_SCR_ScreenShot_f (void) { dstring_t *name = dstring_new (); // find a file name to save it to if (!QFS_NextFilename (name, va ("%s/qf", qfs_gamedir->dir.shots), ".png")) { Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PNG file\n"); } else { tex_t *tex; tex = glsl_SCR_CaptureBGR (); WritePNGqfs (name->str, tex->data, tex->width, tex->height); free (tex); Sys_Printf ("Wrote %s/%s\n", qfs_userpath, name->str); } dstring_delete (name); }
void sw32_SCR_ScreenShot_f (void) { dstring_t *pcxname = dstring_new (); pcx_t *pcx = 0; int pcx_len; // find a file name to save it to if (!QFS_NextFilename (pcxname, va ("%s/qf", qfs_gamedir->dir.shots), ".pcx")) { Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PCX"); } else { // enable direct drawing of console to back buffer sw32_D_EnableBackBufferAccess (); // save the pcx file switch(sw32_r_pixbytes) { case 1: pcx = EncodePCX (vid.buffer, vid.width, vid.height, vid.rowbytes, vid.basepal, false, &pcx_len); break; case 2: Sys_Printf("SCR_ScreenShot_f: FIXME - add 16bit support\n"); break; case 4: Sys_Printf("SCR_ScreenShot_f: FIXME - add 32bit support\n"); break; default: Sys_Error("SCR_ScreenShot_f: unsupported r_pixbytes %i", sw32_r_pixbytes); } // for adapters that can't stay mapped in for linear writes all the time sw32_D_DisableBackBufferAccess (); if (pcx) { QFS_WriteFile (pcxname->str, pcx, pcx_len); Sys_Printf ("Wrote %s/%s\n", qfs_userpath, pcxname->str); } } dstring_delete (pcxname); }
static void SV_Fraglogfile_f (void) { dstring_t *name; if (sv_fraglogfile) { SV_Printf ("Frag file logging off.\n"); Qclose (sv_fraglogfile); sv_fraglogfile = NULL; return; } name = dstring_new (); if (!QFS_NextFilename (name, va ("%s/frag_", qfs_gamedir->dir.def), ".log")) { SV_Printf ("Can't open any logfiles.\n"); sv_fraglogfile = NULL; } else { SV_Printf ("Logging frags to %s.\n", name->str); sv_fraglogfile = QFS_WOpen (name->str, 0); } dstring_delete (name); }
static void SV_Snap (int uid) { client_t *cl; int i; for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) { if (cl->state < cs_zombie) continue; if (cl->userid == uid) break; } if (i >= MAX_CLIENTS) { SV_Printf ("userid not found\n"); return; } if (!cl->uploadfn) cl->uploadfn = dstring_new (); if (!QFS_NextFilename (cl->uploadfn, va ("%s/snap/%d-", qfs_gamedir->dir.def, uid), ".pcx")) { SV_Printf ("Snap: Couldn't create a file, clean some out.\n"); dstring_delete (cl->uploadfn); cl->uploadfn = 0; return; } memcpy (&cl->snap_from, &net_from, sizeof (net_from)); if (sv_redirected != RD_NONE) cl->remote_snap = true; else cl->remote_snap = false; MSG_ReliableWrite_Begin (&cl->backbuf, svc_stufftext, 24); MSG_ReliableWrite_String (&cl->backbuf, "cmd snap\n"); SV_Printf ("Requesting snap from user %d...\n", uid); }
/* CL_SendConnectPacket called by CL_Connect_f and CL_CheckResend */ static void CL_SendConnectPacket (void) { dstring_t *data; double t1, t2; // JACK: Fixed bug where DNS lookups would cause two connects real fast // Now, adds lookup time to the connect time. // Should I add it to realtime instead?!?! if (cls.state != ca_disconnected) return; t1 = Sys_DoubleTime (); if (!NET_StringToAdr (cls.servername->str, &cls.server_addr)) { Sys_Printf ("Bad server address\n"); connect_time = -1; return; } if (cls.server_addr.port == 0) cls.server_addr.port = BigShort (27500); t2 = Sys_DoubleTime (); connect_time = realtime + t2 - t1; // for retransmit requests cls.qport = qport->int_val; data = dstring_new (); dsprintf (data, "%c%c%c%cconnect %i %i %i \"%s\"\n", 255, 255, 255, 255, PROTOCOL_VERSION, cls.qport, cls.challenge, Info_MakeString (cls.userinfo, 0)); Netchan_SendPacket (strlen (data->str), data->str, cls.server_addr); dstring_delete (data); }
VISIBLE tex_t * LoadImage (const char *imageFile) { int tmp; dstring_t *tmpFile; char *ext; tex_t *tex = NULL; QFile *fp; // Get the file name without extension tmpFile = dstring_new (); dstring_copystr (tmpFile, imageFile); ext = strrchr (tmpFile->str, '.'); if (ext) tmp = ext - tmpFile->str; else tmp = tmpFile->size - 1; // Check for a .png dstring_replace (tmpFile, tmp, tmpFile->size, ".png", 5); QFS_FOpenFile (tmpFile->str, &fp); if (fp) { tex = LoadPNG (fp); Qclose (fp); dstring_delete (tmpFile); return (tex); } // Check for a .tga dstring_replace (tmpFile, tmp, tmpFile->size, ".tga", 5); QFS_FOpenFile (tmpFile->str, &fp); if (fp) { tex = LoadTGA (fp); Qclose (fp); dstring_delete (tmpFile); return (tex); } /* // Check for a .jpg dstring_replace (tmpFile, tmp, tmpFile->size, ".jpg", 5); QFS_FOpenFile (tmpFile->str, &fp); if (fp) { tex = LoadJPG (fp); Qclose (fp); dstring_delete (tmpFile); return (tex); } */ // Check for a .pcx dstring_replace (tmpFile, tmp, tmpFile->size, ".pcx", 5); QFS_FOpenFile (tmpFile->str, &fp); if (fp) { tex = LoadPCX (fp, 1, NULL); // Convert, some users don't grok paletted Qclose (fp); dstring_delete (tmpFile); return (tex); } dstring_delete (tmpFile); return (tex); }
void gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int _s, int extra) { dstring_t *cache, *fullpath; unsigned char model_digest[MDFOUR_DIGEST_BYTES]; unsigned char mesh_digest[MDFOUR_DIGEST_BYTES]; int i, j; int *cmds; QFile *f; qboolean remesh = true; qboolean do_cache = false; aliasmodel = m; paliashdr = hdr; cache = dstring_new (); fullpath = dstring_new (); if (!gl_alias_render_tri->int_val) { if (gl_mesh_cache->int_val && gl_mesh_cache->int_val <= paliashdr->mdl.numtris) { do_cache = true; mdfour (model_digest, (unsigned char *) _m, _s); // look for a cached version dstring_copystr (cache, "glquake/"); dstring_appendstr (cache, m->name); QFS_StripExtension (m->name + strlen ("progs/"), cache->str + strlen ("glquake/")); dstring_appendstr (cache, ".qfms"); QFS_FOpenFile (cache->str, &f); if (f) { unsigned char d1[MDFOUR_DIGEST_BYTES]; unsigned char d2[MDFOUR_DIGEST_BYTES]; struct mdfour md; int len, vers; int nc = 0, no = 0; int *c = 0, *vo = 0; memset (d1, 0, sizeof (d1)); memset (d2, 0, sizeof (d2)); Qread (f, &vers, sizeof (int)); Qread (f, &len, sizeof (int)); Qread (f, &nc, sizeof (int)); Qread (f, &no, sizeof (int)); if (vers == 1 && (nc + no) == len) { c = malloc (((nc + 1023) & ~1023) * sizeof (c[0])); vo = malloc (((no + 1023) & ~1023) * sizeof (vo[0])); if (!c || !vo) Sys_Error ("gl_mesh.c: out of memory"); Qread (f, c, nc * sizeof (c[0])); Qread (f, vo, no * sizeof (vo[0])); Qread (f, d1, MDFOUR_DIGEST_BYTES); Qread (f, d2, MDFOUR_DIGEST_BYTES); Qclose (f); mdfour_begin (&md); mdfour_update (&md, (unsigned char *) &vers, sizeof(int)); mdfour_update (&md, (unsigned char *) &len, sizeof(int)); mdfour_update (&md, (unsigned char *) &nc, sizeof(int)); mdfour_update (&md, (unsigned char *) &no, sizeof(int)); mdfour_update (&md, (unsigned char *) c, nc * sizeof (c[0])); mdfour_update (&md, (unsigned char *) vo, no * sizeof (vo[0])); mdfour_update (&md, d1, MDFOUR_DIGEST_BYTES); mdfour_result (&md, mesh_digest); if (memcmp (d2, mesh_digest, MDFOUR_DIGEST_BYTES) == 0 && memcmp (d1, model_digest, MDFOUR_DIGEST_BYTES) == 0) { remesh = false; numcommands = nc; numorder = no; if (numcommands > commands_size) { if (commands) free (commands); commands_size = (numcommands + 1023) & ~1023; commands = c; } else { memcpy (commands, c, numcommands * sizeof (c[0])); free(c); } if (numorder > vertexorder_size) { if (vertexorder) free (vertexorder); vertexorder_size = (numorder + 1023) & ~1023; vertexorder = vo; } else { memcpy (vertexorder, vo, numorder * sizeof (vo[0])); free (vo); } } } } } if (remesh) { // build it from scratch Sys_MaskPrintf (SYS_DEV, "meshing %s...\n", m->name); BuildTris (); // trifans or lists if (do_cache) { // save out the cached version dsprintf (fullpath, "%s/%s", qfs_gamedir->dir.def, cache->str); f = QFS_WOpen (fullpath->str, 9); if (f) { struct mdfour md; int vers = 1; int len = numcommands + numorder; mdfour_begin (&md); mdfour_update (&md, (unsigned char *) &vers, sizeof (int)); mdfour_update (&md, (unsigned char *) &len, sizeof (int)); mdfour_update (&md, (unsigned char *) &numcommands, sizeof (int)); mdfour_update (&md, (unsigned char *) &numorder, sizeof (int)); mdfour_update (&md, (unsigned char *) commands, numcommands * sizeof (commands[0])); mdfour_update (&md, (unsigned char *) vertexorder, numorder * sizeof (vertexorder[0])); mdfour_update (&md, model_digest, MDFOUR_DIGEST_BYTES); mdfour_result (&md, mesh_digest); Qwrite (f, &vers, sizeof (int)); Qwrite (f, &len, sizeof (int)); Qwrite (f, &numcommands, sizeof (int)); Qwrite (f, &numorder, sizeof (int)); Qwrite (f, commands, numcommands * sizeof (commands[0])); Qwrite (f, vertexorder, numorder * sizeof (vertexorder[0])); Qwrite (f, model_digest, MDFOUR_DIGEST_BYTES); Qwrite (f, mesh_digest, MDFOUR_DIGEST_BYTES); Qclose (f); } } } // save the data out paliashdr->poseverts = numorder; cmds = Hunk_Alloc (numcommands * sizeof (int)); paliashdr->commands = (byte *) cmds - (byte *) paliashdr; memcpy (cmds, commands, numcommands * sizeof (int)); } else { tex_coord_t *tex_coord; numorder = 0; for (i=0; i < pheader->mdl.numtris; i++) { add_vertex(triangles[i].vertindex[0]); add_vertex(triangles[i].vertindex[1]); add_vertex(triangles[i].vertindex[2]); } paliashdr->poseverts = numorder; tex_coord = Hunk_Alloc (numorder * sizeof(tex_coord_t)); paliashdr->tex_coord = (byte *) tex_coord - (byte *) paliashdr; for (i=0; i < numorder; i++) { float s, t; int k; k = vertexorder[i]; s = stverts[k].s; t = stverts[k].t; if (!triangles[i/3].facesfront && stverts[k].onseam) s += pheader->mdl.skinwidth / 2; // on back side s = (s + 0.5) / pheader->mdl.skinwidth; t = (t + 0.5) / pheader->mdl.skinheight; tex_coord[i].st[0] = s; tex_coord[i].st[1] = t; } } if (extra) { trivertx16_t *verts; verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts * sizeof (trivertx16_t)); paliashdr->posedata = (byte *) verts - (byte *) paliashdr; for (i = 0; i < paliashdr->numposes; i++) { trivertx_t *pv = poseverts[i]; for (j = 0; j < numorder; j++) { trivertx16_t v; // convert MD16's split coordinates into something a little // saner. The first chunk of vertices is fully compatible with // IDPO alias models (even the scale). The second chunk is the // fractional bits of the vertex, giving 8.8. However, it's // easier for us to multiply everything by 256 and adjust the // model scale appropriately VectorMultAdd (pv[vertexorder[j] + hdr->mdl.numverts].v, 256, pv[vertexorder[j]].v, v.v); v.lightnormalindex = poseverts[i][vertexorder[j]].lightnormalindex; *verts++ = v; } } } else { trivertx_t *verts; verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts * sizeof (trivertx_t)); paliashdr->posedata = (byte *) verts - (byte *) paliashdr; for (i = 0; i < paliashdr->numposes; i++) { for (j = 0; j < numorder; j++) *verts++ = poseverts[i][vertexorder[j]]; } } dstring_delete (cache); dstring_delete (fullpath); }
/* CF_Open cfopen opens a file, either for reading or writing (not both). returns a file descriptor >= 0 on success, < 0 on failure. mode is either r or w. */ int CF_Open (const char *path, const char *mode) { char *j; dstring_t *fullpath = dstring_new (); int desc, oldsize, i; QFile *file; if (cf_openfiles >= CF_MAXFILES) { return -1; } // check for paths with .. if (strequal (path, "..") || !strncmp (path, "../", 3) || strstr (path, "/../") || (strlen (path) >= 3 && strequal (path + strlen (path) - 3, "/.."))) { return -1; } if (!(strequal(mode, "w") || strequal(mode, "r") || strequal(mode, "a"))) { return -1; } if (mode[0] == 'w' && cf_maxsize < 0) { // can't even delete if quota < 0 return -1; } dsprintf (fullpath, "%s/%s/%s", qfs_gamedir->dir.def, CF_DIR, path); j = fullpath->str + strlen (fullpath->str) - strlen (path); for (i = 0; path[i]; i++, j++) // strcpy, but force lowercase *j = tolower ((byte) path[i]); *j = '\0'; if (CF_AlreadyOpen (fullpath->str, mode[0])) { dstring_delete (fullpath); return -1; } if (mode[0] == 'w') oldsize = CF_GetFileSize (fullpath->str); else oldsize = 0; file = QFS_Open (fullpath->str, mode); if (file) { if (cf_openfiles >= cf_filepcount) { cf_filepcount++; cf_filep = realloc (cf_filep, sizeof (cf_file_t) * cf_filepcount); if (!cf_filep) { Sys_Error ("CF_Open: memory allocation error!"); } cf_filep[cf_filepcount - 1].file = 0; } for (desc = 0; cf_filep[desc].file; desc++) ; cf_filep[desc].path = fullpath->str; cf_filep[desc].file = file; cf_filep[desc].buf = 0; cf_filep[desc].size = 0; cf_filep[desc].writtento = 0; cf_filep[desc].mode = mode[0]; cf_cursize -= oldsize; cf_openfiles++; return desc; } return -1; }
static void Host_Loadgame_f (void) { dstring_t *name = 0; QFile *f; char *mapname = 0; script_t *script = 0; plitem_t *game = 0; plitem_t *list; plitem_t *item; char *script_data = 0; int i; int entnum; int count; int version; float spawn_parms[NUM_SPAWN_PARMS]; if (cmd_source != src_command) goto end; if (Cmd_Argc () != 2) { Sys_Printf ("load <savename> : load a game\n"); goto end; } cls.demonum = -1; // stop demo loop in case this fails name = dstring_newstr (); dsprintf (name, "%s/%s", qfs_gamedir->dir.def, Cmd_Argv (1)); QFS_DefaultExtension (name, ".sav"); cl.loading = true; CL_UpdateScreen (cl.time); Sys_Printf ("Loading game from %s...\n", name->str); f = QFS_Open (name->str, "rz"); if (!f) { Sys_Printf ("ERROR: couldn't open.\n"); goto end; } script_data = malloc (Qfilesize (f) + 1); i = Qread (f, script_data, Qfilesize (f)); script_data[i] = 0; Qclose (f); script = Script_New (); script->single = ""; // disable {}()': lexing Script_Start (script, name->str, script_data); Script_GetToken (script, 1); if (strequal (script->token->str, PACKAGE_NAME)) { if (!Script_TokenAvailable (script, 1)) { Sys_Printf ("Unexpected EOF reading %s\n", name->str); goto end; } game = PL_GetPropertyList (script->p); } else { sscanf (script->token->str, "%i", &version); if (version != SAVEGAME_VERSION) { Sys_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION); goto end; } game = convert_to_game_dict (script); } item = PL_ObjectForKey (game, "spawn_parms"); for (i = 0; i < NUM_SPAWN_PARMS; i++) { if (i >= PL_A_NumObjects (item)) break; spawn_parms[i] = atof (PL_String (PL_ObjectAtIndex (item, i))); } current_skill = atoi (PL_String (PL_ObjectForKey (game, "current_skill"))); Cvar_SetValue (skill, current_skill); mapname = strdup (PL_String (PL_ObjectForKey (game, "name"))); CL_Disconnect_f (); SV_SpawnServer (mapname); if (!sv.active) { Sys_Printf ("Couldn't load map %s\n", mapname); goto end; } sv.paused = true; // pause until all clients connect sv.loadgame = true; list = PL_ObjectForKey (game, "lightstyles"); for (i = 0; i < MAX_LIGHTSTYLES; i++) { const char *style; char *str; if (i >= PL_A_NumObjects (list)) break; item = PL_ObjectAtIndex (list, i); style = PL_String (item); sv.lightstyles[i] = str = Hunk_Alloc (strlen (style) + 1); strcpy (str, style); } ED_InitGlobals (&sv_pr_state, PL_ObjectForKey (game, "globals")); list = PL_ObjectForKey (game, "entities"); entnum = 0; count = PL_A_NumObjects (list); if (count > sv.max_edicts) Host_Error ("too many entities in saved game. adjust max_edicts\n"); for (entnum = 0; entnum < count; entnum++) { plitem_t *entity = PL_ObjectAtIndex (list, entnum); edict_t *ent = EDICT_NUM (&sv_pr_state, entnum); memset (&ent->v, 0, sv_pr_state.progs->entityfields * 4); ent->free = false; ED_InitEntity (&sv_pr_state, entity, ent); // link it into the bsp tree if (!ent->free) SV_LinkEdict (ent, false); } sv.num_edicts = entnum; sv.time = atof (PL_String (PL_ObjectForKey (game, "time"))); for (i = 0; i < NUM_SPAWN_PARMS; i++) svs.clients->spawn_parms[i] = spawn_parms[i]; if (cls.state != ca_dedicated) { CL_EstablishConnection ("local"); Host_Reconnect_f (); } end: if (game) PL_Free (game); if (mapname) free (mapname); if (script) Script_Delete (script); if (script_data) free (script_data); if (name) dstring_delete (name); }
static void Host_Savegame_f (void) { dstring_t *name; const char *save_name; char *save_text; QFile *f; int i; char *bup1, *bup2 = 0; if (cmd_source != src_command) return; if (!sv.active) { Sys_Printf ("Not playing a local game.\n"); return; } if (cl.intermission) { Sys_Printf ("Can't save in intermission.\n"); return; } if (svs.maxclients != 1) { Sys_Printf ("Can't save multiplayer games.\n"); return; } if (Cmd_Argc () != 2) { Sys_Printf ("save <savename> : save a game\n"); return; } if (strstr (Cmd_Argv (1), "..")) { Sys_Printf ("Relative pathnames are not allowed.\n"); return; } for (i = 0; i < svs.maxclients; i++) { if (svs.clients[i].active && (SVfloat (svs.clients[i].edict, health) <= 0)) { Sys_Printf ("Can't savegame with a dead player\n"); return; } } save_name = Cmd_Argv (1); name = dstring_newstr (); if (strcmp (save_name, "quick") == 0) { bup2 = nva ("%s/%s%d.sav", qfs_gamedir->dir.def, save_name, MAX_QUICK); QFS_Remove (bup2); for (i = MAX_QUICK - 1; i > 0; i--) { bup1 = nva ("%s/%s%d.sav", qfs_gamedir->dir.def, save_name, i); QFS_Rename (bup1, bup2); free (bup2); bup2 = bup1; } } dsprintf (name, "%s/%s", qfs_gamedir->dir.def, save_name); QFS_DefaultExtension (name, ".sav"); if (bup2) { QFS_Rename (name->str, bup2); free (bup2); } Sys_Printf ("Saving game to %s...\n", name->str); f = QFS_WOpen (name->str, 0); dstring_delete (name); if (!f) { Sys_Printf ("ERROR: couldn't open.\n"); return; } save_text = PL_WritePropertyList (game_dict ()); Qprintf (f, "%s\n%s", PACKAGE_NAME, save_text); free (save_text); Qclose (f); Sys_Printf ("done.\n"); }
static void SV_Punish (int mode) { int i; double mins = 0.5; qboolean all = false, done = false; client_t *cl = 0; dstring_t *text = dstring_new(); const char *cmd = 0; const char *cmd_do = 0; //FIXME const char *cmd_undo = 0; int field_offs = 0; switch (mode) { case 0: cmd = "cuff"; cmd_do = "cuffed"; //FIXME cmd_undo = "un-cuffed"; field_offs = field_offset (client_t, cuff_time); break; case 1: cmd = "mute"; cmd_do = "muted"; //FIXME cmd_undo = "can speak"; field_offs = field_offset (client_t, lockedtill); break; } if (Cmd_Argc () != 2 && Cmd_Argc () != 3) { SV_Printf ("usage: %s <name/userid/ALL> [minutes]\n" " (default = 0.5, 0 = cancel cuff).\n", cmd); return; } if (strequal (Cmd_Argv (1), "ALL")) { all = true; } else { cl = SV_Match_User (Cmd_Argv (1)); } if (!all && !cl) return; if (Cmd_Argc () == 3) { mins = atof (Cmd_Argv (2)); if (mins < 0.0 || mins > MAXPENALTY) mins = MAXPENALTY; } if (cl) { *(double *)((char *)cl + field_offs) = realtime + mins * 60.0; if (mins) { dsprintf (text, "You are %s for %.1f minutes\n\n" "reconnecting won't help...\n", cmd_do, mins); MSG_ReliableWrite_Begin (&cl->backbuf, svc_centerprint, 2 + strlen (text->str)); MSG_ReliableWrite_String (&cl->backbuf, text->str); } } if (all) { for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) { if (cl->state < cs_zombie) continue; *(double *)((char *)cl + field_offs) = realtime + mins * 60.0; done = true; if (mins) { dsprintf (text, "You are %s for %.1f minutes\n\n" "reconnecting won't help...\n", cmd_do, mins); MSG_ReliableWrite_Begin (&cl->backbuf, svc_centerprint, 2 + strlen (text->str)); MSG_ReliableWrite_String (&cl->backbuf, text->str); } } } if (done) { if (mins) SV_BroadcastPrintf (PRINT_HIGH, "%s %s for %.1f minutes.\n", all? "All Users" : cl->name, cmd_do, mins); else SV_BroadcastPrintf (PRINT_HIGH, "%s %s.\n", all? "All Users" : cl->name, cmd_do); } dstring_delete (text); }