client_t *ClientReliableWrite_BeginSplit(client_t *cl, int svc, int svclen) { if (cl->controller) { //this is a slave client. //find the right number and send. client_t *sp; int pnum = 0; for (sp = cl->controller; sp; sp = sp->controlled) { if (sp == cl) break; pnum++; } sp = cl->controller; ClientReliableWrite_Begin (sp, svcfte_choosesplitclient, 2+svclen); ClientReliableWrite_Byte (sp, pnum); ClientReliableWrite_Byte (sp, svc); return sp; } else { ClientReliableWrite_Begin (cl, svc, svclen); return cl; } }
void SV_NextDownload_f (void) { byte buffer[1024]; int r; int percent; int size; if (!host_client->download) return; r = host_client->downloadsize - host_client->downloadcount; if (r > 768) r = 768; r = fread (buffer, 1, r, host_client->download); ClientReliableWrite_Begin (host_client, svc_download, 6+r); ClientReliableWrite_Short (host_client, r); host_client->downloadcount += r; size = host_client->downloadsize; if (!size) size = 1; percent = host_client->downloadcount*100/size; ClientReliableWrite_Byte (host_client, percent); ClientReliableWrite_SZ (host_client, buffer, r); if (host_client->downloadcount != host_client->downloadsize) return; fclose (host_client->download); host_client->download = NULL; }
// begin a client block, estimated maximum size void ClientReliableWrite_Begin(client_t *cl, int c, int maxsize) { if (cl->controller) Con_Printf("Writing %i to slave client's message buffer\n", c); ClientReliableCheckBlock(cl, maxsize); ClientReliableWrite_Byte(cl, c); }
void SV_Pings_f (void) { client_t *client; int j; for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++) { if (client->state != cs_spawned) continue; ClientReliableWrite_Begin (host_client, svc_updateping, 4); ClientReliableWrite_Byte (host_client, j); ClientReliableWrite_Short (host_client, SV_CalcPing(client)); ClientReliableWrite_Begin (host_client, svc_updatepl, 4); ClientReliableWrite_Byte (host_client, j); ClientReliableWrite_Byte (host_client, client->lossage); } }
void SV_TogglePause (const char *msg) { int i; client_t *cl; sv.paused ^= 1; if (msg) SV_BroadcastPrintf (PRINT_HIGH, "%s", msg); // send notification to all clients for (i=0, cl = svs.clients ; i<MAX_CLIENTS ; i++, cl++) { if (!cl->state) continue; ClientReliableWrite_Begin (cl, svc_setpause, 2); ClientReliableWrite_Byte (cl, sv.paused); } }
// begin a client block, estimated maximum size void ClientReliableWrite_Begin(client_t *cl, int c, int maxsize) { ClientReliableCheckBlock(cl, maxsize); ClientReliableWrite_Byte(cl, c); }
void SV_BeginDownload_f(void) { char *name; extern cvar_t allow_download; extern cvar_t allow_download_skins; extern cvar_t allow_download_models; extern cvar_t allow_download_sounds; extern cvar_t allow_download_maps; extern int file_from_pak; // ZOID did file come from pak? name = Cmd_Argv(1); // hacked by zoid to allow more conrol over download // first off, no .. or global allow check if (strstr (name, "..") || !allow_download.value // leading dot is no good || *name == '.' // leading slash bad as well, must be in subdir || *name == '/' // next up, skin check || (strncmp(name, "skins/", 6) == 0 && !allow_download_skins.value) // now models || (strncmp(name, "progs/", 6) == 0 && !allow_download_models.value) // now sounds || (strncmp(name, "sound/", 6) == 0 && !allow_download_sounds.value) // now maps (note special case for maps, must not be in pak) || (strncmp(name, "maps/", 6) == 0 && !allow_download_maps.value) // MUST be in a subdirectory || !strstr (name, "/") ) { // don't allow anything with .. path ClientReliableWrite_Begin (host_client, svc_download, 4); ClientReliableWrite_Short (host_client, -1); ClientReliableWrite_Byte (host_client, 0); return; } if (host_client->download) { fclose (host_client->download); host_client->download = NULL; } // lowercase name (needed for casesen file systems) { char *p; for (p = name; *p; p++) *p = (char)tolower(*p); } host_client->downloadsize = COM_FOpenFile (name, &host_client->download); host_client->downloadcount = 0; if (!host_client->download // special check for maps, if it came from a pak file, don't allow // download ZOID || (strncmp(name, "maps/", 5) == 0 && file_from_pak)) { if (host_client->download) { fclose(host_client->download); host_client->download = NULL; } Sys_Printf ("Couldn't download %s to %s\n", name, host_client->name); ClientReliableWrite_Begin (host_client, svc_download, 4); ClientReliableWrite_Short (host_client, -1); ClientReliableWrite_Byte (host_client, 0); return; } SV_NextDownload_f (); Sys_Printf ("Downloading %s to %s\n", name, host_client->name); }
void SV_Begin_f (void) { unsigned pmodel = 0, emodel = 0; int i; if (host_client->state == cs_spawned) return; // don't begin again host_client->state = cs_spawned; // handle the case of a level changing while a client was connecting if ( atoi(Cmd_Argv(1)) != svs.spawncount ) { Con_Printf ("SV_Begin_f from different level\n"); SV_New_f (); return; } if (host_client->spectator) { SV_SpawnSpectator (); if (SpectatorConnect) { // copy spawn parms out of the client_t for (i=0 ; i< NUM_SPAWN_PARMS ; i++) (&pr_global_struct->parm1)[i] = host_client->spawn_parms[i]; // call the spawn function pr_global_struct->time = sv.time; pr_global_struct->self = EDICT_TO_PROG(sv_player); PR_ExecuteProgram (SpectatorConnect); } } else { // copy spawn parms out of the client_t for (i=0 ; i< NUM_SPAWN_PARMS ; i++) (&pr_global_struct->parm1)[i] = host_client->spawn_parms[i]; // call the spawn function pr_global_struct->time = sv.time; pr_global_struct->self = EDICT_TO_PROG(sv_player); PR_ExecuteProgram (pr_global_struct->ClientConnect); // actually spawn the player pr_global_struct->time = sv.time; pr_global_struct->self = EDICT_TO_PROG(sv_player); PR_ExecuteProgram (pr_global_struct->PutClientInServer); } // clear the net statistics, because connecting gives a bogus picture host_client->netchan.frame_latency = 0; host_client->netchan.frame_rate = 0; host_client->netchan.drop_count = 0; host_client->netchan.good_count = 0; //check he's not cheating pmodel = atoi(Info_ValueForKey (host_client->userinfo, "pmodel")); emodel = atoi(Info_ValueForKey (host_client->userinfo, "emodel")); if (pmodel != sv.model_player_checksum || emodel != sv.eyes_player_checksum) SV_BroadcastPrintf (PRINT_HIGH, "%s WARNING: non standard player/eyes model detected\n", host_client->name); // if we are paused, tell the client if (sv.paused) { ClientReliableWrite_Begin (host_client, svc_setpause, 2); ClientReliableWrite_Byte (host_client, sv.paused); SV_ClientPrintf(host_client, PRINT_HIGH, "Server is paused.\n"); } #if 0 // // send a fixangle over the reliable channel to make sure it gets there // Never send a roll angle, because savegames can catch the server // in a state where it is expecting the client to correct the angle // and it won't happen if the game was just loaded, so you wind up // with a permanent head tilt ent = EDICT_NUM( 1 + (host_client - svs.clients) ); MSG_WriteByte (&host_client->netchan.message, svc_setangle); for (i=0 ; i < 2 ; i++) MSG_WriteAngle (&host_client->netchan.message, ent->v.angles[i] ); MSG_WriteAngle (&host_client->netchan.message, 0 ); #endif }
void SV_Spawn_f (void) { int i; client_t *client; edict_t *ent; eval_t *val; int n; if (host_client->state != cs_connected) { Con_Printf ("Spawn not valid -- allready spawned\n"); return; } // handle the case of a level changing while a client was connecting if ( atoi(Cmd_Argv(1)) != svs.spawncount ) { Con_Printf ("SV_Spawn_f from different level\n"); SV_New_f (); return; } n = atoi(Cmd_Argv(2)); // make sure n is valid if ( n < 0 || n > MAX_CLIENTS ) { Con_Printf ("SV_Spawn_f invalid client start\n"); SV_New_f (); return; } // send all current names, colors, and frag counts // FIXME: is this a good thing? SZ_Clear (&host_client->netchan.message); // send current status of all other players // normally this could overflow, but no need to check due to backbuf for (i=n, client = svs.clients + n ; i<MAX_CLIENTS ; i++, client++) SV_FullClientUpdateToClient (client, host_client); // send all current light styles for (i=0 ; i<MAX_LIGHTSTYLES ; i++) { ClientReliableWrite_Begin (host_client, svc_lightstyle, 3 + (sv.lightstyles[i] ? strlen(sv.lightstyles[i]) : 1)); ClientReliableWrite_Byte (host_client, (char)i); ClientReliableWrite_String (host_client, sv.lightstyles[i]); } // set up the edict ent = host_client->edict; memset (&ent->v, 0, progs->entityfields * 4); ent->v.colormap = NUM_FOR_EDICT(ent); ent->v.team = 0; // FIXME ent->v.netname = PR_SetString(host_client->name); host_client->entgravity = 1.0; val = GetEdictFieldValue(ent, "gravity"); if (val) val->_float = 1.0; host_client->maxspeed = sv_maxspeed.value; val = GetEdictFieldValue(ent, "maxspeed"); if (val) val->_float = sv_maxspeed.value; // // force stats to be updated // memset (host_client->stats, 0, sizeof(host_client->stats)); ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6); ClientReliableWrite_Byte (host_client, STAT_TOTALSECRETS); ClientReliableWrite_Long (host_client, pr_global_struct->total_secrets); ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6); ClientReliableWrite_Byte (host_client, STAT_TOTALMONSTERS); ClientReliableWrite_Long (host_client, pr_global_struct->total_monsters); ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6); ClientReliableWrite_Byte (host_client, STAT_SECRETS); ClientReliableWrite_Long (host_client, pr_global_struct->found_secrets); ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6); ClientReliableWrite_Byte (host_client, STAT_MONSTERS); ClientReliableWrite_Long (host_client, pr_global_struct->killed_monsters); // get the client to check and download skins // when that is completed, a begin command will be issued ClientReliableWrite_Begin (host_client, svc_stufftext, 8); ClientReliableWrite_String (host_client, "skins\n" ); }