void SV_Baselines_f(void) { int start; entity_state_t nullstate; entity_state_t *base; Com_DPrintf("Baselines() from %s\n", sv_client->name); if (sv_client->state != cs_connected) { Com_Printf("baselines not valid -- already spawned\n"); return; } /* handle the case of a level changing while a client was connecting */ if ((int)strtol(Cmd_Argv(1), (char **)NULL, 10) != svs.spawncount) { Com_Printf("SV_Baselines_f from different level\n"); SV_New_f(); return; } start = (int)strtol(Cmd_Argv(2), (char **)NULL, 10); memset(&nullstate, 0, sizeof(nullstate)); /* write a packet full of data */ while (sv_client->netchan.message.cursize < MAX_MSGLEN / 2 && start < MAX_EDICTS) { base = &sv.baselines[start]; if (base->modelindex || base->sound || base->effects) { MSG_WriteByte(&sv_client->netchan.message, svc_spawnbaseline); MSG_WriteDeltaEntity(&nullstate, base, &sv_client->netchan.message, true, true); } start++; } /* send next command */ if (start == MAX_EDICTS) { MSG_WriteByte(&sv_client->netchan.message, svc_stufftext); MSG_WriteString(&sv_client->netchan.message, va("precache %i\n", svs.spawncount)); } else { MSG_WriteByte(&sv_client->netchan.message, svc_stufftext); MSG_WriteString(&sv_client->netchan.message, va("cmd baselines %i %i\n", svs.spawncount, start)); } }
void SV_Configstrings_f(void) { int start; Com_DPrintf("Configstrings() from %s\n", sv_client->name); if (sv_client->state != cs_connected) { Com_Printf("configstrings not valid -- already spawned\n"); return; } /* handle the case of a level changing while a client was connecting */ if ((int)strtol(Cmd_Argv(1), (char **)NULL, 10) != svs.spawncount) { Com_Printf("SV_Configstrings_f from different level\n"); SV_New_f(); return; } start = (int)strtol(Cmd_Argv(2), (char **)NULL, 10); /* write a packet full of data */ while (sv_client->netchan.message.cursize < MAX_MSGLEN / 2 && start < MAX_CONFIGSTRINGS) { if (sv.configstrings[start][0]) { MSG_WriteByte(&sv_client->netchan.message, svc_configstring); MSG_WriteShort(&sv_client->netchan.message, start); MSG_WriteString(&sv_client->netchan.message, sv.configstrings[start]); } start++; } /* send next command */ if (start == MAX_CONFIGSTRINGS) { MSG_WriteByte(&sv_client->netchan.message, svc_stufftext); MSG_WriteString(&sv_client->netchan.message, va("cmd baselines %i 0\n", svs.spawncount)); } else { MSG_WriteByte(&sv_client->netchan.message, svc_stufftext); MSG_WriteString(&sv_client->netchan.message, va("cmd configstrings %i %i\n", svs.spawncount, start)); } }
/* * SV_Baselines_f */ static void SV_Baselines_f( client_t *client ) { int start; entity_state_t nullstate; entity_state_t *base; Com_DPrintf( "Baselines() from %s\n", client->name ); if( client->state != CS_CONNECTED ) { Com_Printf( "baselines not valid -- already spawned\n" ); return; } // handle the case of a level changing while a client was connecting if( atoi( Cmd_Argv( 1 ) ) != svs.spawncount ) { Com_Printf( "SV_Baselines_f from different level\n" ); SV_New_f( client ); return; } start = atoi( Cmd_Argv( 2 ) ); if( start < 0 ) start = 0; memset( &nullstate, 0, sizeof( nullstate ) ); // write a packet full of data SV_InitClientMessage( client, &tmpMessage, NULL, 0 ); while( tmpMessage.cursize < FRAGMENT_SIZE * 3 && start < MAX_EDICTS ) { base = &sv.baselines[start]; if( base->modelindex || base->sound || base->effects ) { MSG_WriteByte( &tmpMessage, svc_spawnbaseline ); MSG_WriteDeltaEntity( &nullstate, base, &tmpMessage, qtrue, qtrue ); } start++; } // send next command if( start == MAX_EDICTS ) SV_SendServerCommand( client, "precache %i", svs.spawncount ); else SV_SendServerCommand( client, "cmd baselines %i %i", svs.spawncount, start ); SV_AddReliableCommandsToMessage( client, &tmpMessage ); SV_SendMessageToClient( client, &tmpMessage ); }
/* ================== SV_Begin_f ================== */ void SV_Begin_f(void){ Com_DPrintf("Begin() from %s\n", sv_client->name); // handle the case of a level changing while a client was connecting if(atoi(Cmd_Argv(1)) != svs.spawncount){ Com_Printf("SV_Begin_f from different level\n"); SV_New_f(); return; } sv_client->state = cs_spawned; // call the game begin function ge->ClientBegin(sv_player); Cbuf_InsertFromDefer(); }
void SV_Soundlist_f (void) { char **s; int n; if (host_client->state != cs_connected) { Con_Printf ("soundlist 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_Soundlist_f from different level\n"); SV_New_f (); return; } n = atoi(Cmd_Argv(2)); //NOTE: This doesn't go through ClientReliableWrite since it's before the user //spawns. These functions are written to not overflow if (host_client->num_backbuf) { Con_Printf("WARNING %s: [SV_Soundlist] Back buffered (%d0, clearing", host_client->name, host_client->netchan.message.cursize); host_client->num_backbuf = 0; SZ_Clear(&host_client->netchan.message); } MSG_WriteByte (&host_client->netchan.message, svc_soundlist); MSG_WriteByte (&host_client->netchan.message, n); for (s = sv.sound_precache+1 + n ; *s && host_client->netchan.message.cursize < (MAX_MSGLEN/2); s++, n++) MSG_WriteString (&host_client->netchan.message, *s); MSG_WriteByte (&host_client->netchan.message, 0); // next msg if (*s) MSG_WriteByte (&host_client->netchan.message, n); else MSG_WriteByte (&host_client->netchan.message, 0); }
/* ================== SV_Begin_f ================== */ void SV_Begin_f (void) { Com_DPrintf ("Begin() from %s\n", sv_client->name); // r1ch: could be abused to respawn or cause spam/other mod specific problems if (sv_client->state != cs_connected) { Com_Printf ("EXPLOIT: Illegal 'begin' from %s[%s] (already spawned), client dropped.\n", sv_client->name, NET_AdrToString (sv_client->netchan.remote_address)); SV_DropClient (sv_client); return; } // handle the case of a level changing while a client was connecting if ( atoi(Cmd_Argv(1)) != svs.spawncount ) { Com_Printf ("SV_Begin_f from different level\n"); SV_New_f (); return; } sv_client->state = cs_spawned; // call the game begin function ge->ClientBegin (sv_player); // Knightmare- set default player speeds here, if // the game DLL hasn't already set them #ifdef NEW_PLAYER_STATE_MEMBERS if (!sv_player->client->ps.maxspeed) sv_player->client->ps.maxspeed = DEFAULT_MAXSPEED; if (!sv_player->client->ps.duckspeed) sv_player->client->ps.duckspeed = DEFAULT_DUCKSPEED; if (!sv_player->client->ps.waterspeed) sv_player->client->ps.waterspeed = DEFAULT_WATERSPEED; if (!sv_player->client->ps.accel) sv_player->client->ps.accel = DEFAULT_ACCELERATE; if (!sv_player->client->ps.stopspeed) sv_player->client->ps.stopspeed = DEFAULT_STOPSPEED; #endif // end Knightmare Cbuf_InsertFromDefer (); }
/* ================== SV_Modellist_f ================== */ static void SV_Modellist_f (void) { int i; if (host_client->state != cs_connected) { Con_Printf ("modellist not valid -- already spawned\n"); return; } // handle the case of a level changing while a client was connecting if ( atoi(Cmd_Argv(1)) != svs.spawncount ) { Con_Printf ("%s from different level\n", __thisfunc__); SV_New_f (); return; } MSG_WriteByte (&host_client->netchan.message, svc_modellist); for (i = 1; i < MAX_MODELS && sv.model_precache[i][0]; i++) MSG_WriteString (&host_client->netchan.message, sv.model_precache[i]); MSG_WriteByte (&host_client->netchan.message, 0); }
/* ================== SV_PreSpawn_f ================== */ static void SV_PreSpawn_f (void) { int buf; if (host_client->state != cs_connected) { Con_Printf ("prespawn not valid -- already spawned\n"); return; } // handle the case of a level changing while a client was connecting if ( atoi(Cmd_Argv(1)) != svs.spawncount ) { Con_Printf ("%s from different level\n", __thisfunc__); SV_New_f (); return; } buf = atoi(Cmd_Argv(2)); if (buf >= sv.num_signon_buffers) buf = 0; SZ_Write (&host_client->netchan.message, sv.signon_buffers[buf], sv.signon_buffer_size[buf]); buf++; if (buf == sv.num_signon_buffers) { // all done prespawning MSG_WriteByte (&host_client->netchan.message, svc_stufftext); MSG_WriteString (&host_client->netchan.message, va("cmd spawn %i\n",svs.spawncount) ); } else { // need to prespawn more MSG_WriteByte (&host_client->netchan.message, svc_stufftext); MSG_WriteString (&host_client->netchan.message, va("cmd prespawn %i %i\n", svs.spawncount, buf) ); } }
/* ================== SV_Baselines_f ================== */ void SV_Baselines_f (void) { int startPos, start; int maxLen; // Knightmare added entity_state_t nullstate; entity_state_t *base; Com_DPrintf ("Baselines() from %s\n", sv_client->name); if (sv_client->state != cs_connected) { Com_Printf ("baselines not valid -- already spawned\n"); return; } // handle the case of a level changing while a client was connecting if ( atoi(Cmd_Argv(1)) != svs.spawncount ) { Com_Printf ("SV_Baselines_f from different level\n"); SV_New_f (); return; } // Knightmare- use sv_baselines_maxlen for proper bounding in multiplayer maxLen = SV_SetMaxBaselinesSize(); // start = atoi(Cmd_Argv(2)); startPos = atoi(Cmd_Argv(2)); if (startPos < 0) // r1ch's fix for negative index { Com_Printf ("Illegal baselines request (negative index) from %s[%s], dropping client\n", sv_client->name, NET_AdrToString(sv_client->netchan.remote_address)); SV_DropClient (sv_client); return; } start = startPos; memset (&nullstate, 0, sizeof(nullstate)); // write a packet full of data // Knightmare- use maxLen for proper bounding // while ( sv_client->netchan.message.cursize < MAX_MSGLEN/2 && start < MAX_EDICTS) while ( sv_client->netchan.message.cursize < maxLen && start < MAX_EDICTS) { base = &sv.baselines[start]; if (base->modelindex || base->sound || base->effects) { MSG_WriteByte (&sv_client->netchan.message, svc_spawnbaseline); MSG_WriteDeltaEntity (&nullstate, base, &sv_client->netchan.message, true, true); } start++; } // send next command if (start == MAX_EDICTS) { MSG_WriteByte (&sv_client->netchan.message, svc_stufftext); MSG_WriteString (&sv_client->netchan.message, va("precache %i\n", svs.spawncount) ); } else { MSG_WriteByte (&sv_client->netchan.message, svc_stufftext); MSG_WriteString (&sv_client->netchan.message, va("cmd baselines %i %i\n",svs.spawncount, start) ); } }
/* ================== SV_Configstrings_f ================== */ void SV_Configstrings_f (void) { int startPos, start; int maxLen; // Knightmare added Com_DPrintf ("Configstrings() from %s\n", sv_client->name); if (sv_client->state != cs_connected) { Com_Printf ("configstrings not valid -- already spawned\n"); return; } // handle the case of a level changing while a client was connecting if ( atoi(Cmd_Argv(1)) != svs.spawncount ) { Com_Printf ("SV_Configstrings_f from different level\n"); SV_New_f (); return; } // Knightmare- use sv_baselines_maxlen for proper bounding in multiplayer maxLen = SV_SetMaxBaselinesSize(); // start = atoi(Cmd_Argv(2)); startPos = atoi(Cmd_Argv(2)); if (startPos < 0) // r1ch's fix for negative index { Com_Printf ("Illegal configstrings request (negative index) from %s[%s], dropping client\n", sv_client->name, NET_AdrToString(sv_client->netchan.remote_address)); SV_DropClient (sv_client); return; } start = startPos; // write a packet full of data // Knightmare- use maxLen for proper bounding // while ( sv_client->netchan.message.cursize < MAX_MSGLEN/2 && start < MAX_CONFIGSTRINGS) while ( sv_client->netchan.message.cursize < maxLen && start < MAX_CONFIGSTRINGS) { if (sv.configstrings[start][0]) { MSG_WriteByte (&sv_client->netchan.message, svc_configstring); MSG_WriteShort (&sv_client->netchan.message, start); MSG_WriteString (&sv_client->netchan.message, sv.configstrings[start]); } start++; } // send next command if (start == MAX_CONFIGSTRINGS) { MSG_WriteByte (&sv_client->netchan.message, svc_stufftext); MSG_WriteString (&sv_client->netchan.message, va("cmd baselines %i 0\n",svs.spawncount) ); } else { MSG_WriteByte (&sv_client->netchan.message, svc_stufftext); MSG_WriteString (&sv_client->netchan.message, va("cmd configstrings %i %i\n",svs.spawncount, start) ); } }
/* ================== SV_Begin_f ================== */ static void SV_Begin_f (void) { int i; 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 ("%s from different level\n", __thisfunc__); 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]; host_client->send_all_v = true; // 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; #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 }
/* ================== SV_Spawn_f ================== */ static void SV_Spawn_f (void) { int i; client_t *client; edict_t *ent; eval_t *val; // Con_Printf("%s\n", __thisfunc__); if (host_client->state != cs_connected) { Con_Printf ("Spawn not valid -- already spawned\n"); return; } // handle the case of a level changing while a client was connecting if ( atoi(Cmd_Argv(1)) != svs.spawncount ) { Con_Printf ("%s from different level\n", __thisfunc__); SV_New_f (); return; } // set up the edict ent = host_client->edict; memset (&ent->v, 0, progs->entityfields * 4); ent->v.colormap = NUM_FOR_EDICT(ent); if (dmMode.integer == DM_SIEGE) ent->v.team = ent->v.siege_team; // FIXME else ent->v.team = 0; // FIXME ent->v.netname = PR_SetEngineString(host_client->name); //ent->v.playerclass = host_client->playerclass = ent->v.next_playerclass = host_client->next_playerclass; ent->v.has_portals = host_client->portals; 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; // 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 for (i = 0, client = svs.clients; i < MAX_CLIENTS; i++, client++) SV_FullClientUpdate (client, &host_client->netchan.message); // send all current light styles for (i = 0; i < MAX_LIGHTSTYLES; i++) { MSG_WriteByte (&host_client->netchan.message, svc_lightstyle); MSG_WriteByte (&host_client->netchan.message, (char)i); MSG_WriteString (&host_client->netchan.message, sv.lightstyles[i]); } // // force stats to be updated // memset (host_client->stats, 0, sizeof(host_client->stats)); MSG_WriteByte (&host_client->netchan.message, svc_updatestatlong); MSG_WriteByte (&host_client->netchan.message, STAT_TOTALSECRETS); MSG_WriteLong (&host_client->netchan.message, PR_GLOBAL_STRUCT(total_secrets)); MSG_WriteByte (&host_client->netchan.message, svc_updatestatlong); MSG_WriteByte (&host_client->netchan.message, STAT_TOTALMONSTERS); MSG_WriteLong (&host_client->netchan.message, PR_GLOBAL_STRUCT(total_monsters)); MSG_WriteByte (&host_client->netchan.message, svc_updatestatlong); MSG_WriteByte (&host_client->netchan.message, STAT_SECRETS); MSG_WriteLong (&host_client->netchan.message, PR_GLOBAL_STRUCT(found_secrets)); MSG_WriteByte (&host_client->netchan.message, svc_updatestatlong); MSG_WriteByte (&host_client->netchan.message, STAT_MONSTERS); MSG_WriteLong (&host_client->netchan.message, PR_GLOBAL_STRUCT(killed_monsters)); // get the client to check and download skins // when that is completed, a begin command will be issued MSG_WriteByte (&host_client->netchan.message, svc_stufftext); MSG_WriteString (&host_client->netchan.message, va("skins\n") ); }
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" ); }
void SV_PreSpawn_f (void) { unsigned buf; unsigned check; if (host_client->state != cs_connected) { Con_Printf ("prespawn 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_PreSpawn_f from different level\n"); SV_New_f (); return; } buf = atoi(Cmd_Argv(2)); if (buf >= sv.num_signon_buffers) buf = 0; if (!buf) { // should be three numbers following containing checksums check = atoi(Cmd_Argv(3)); // Con_DPrintf("Client check = %d\n", check); if (sv_mapcheck.value && check != sv.worldmodel->checksum && check != sv.worldmodel->checksum2) { SV_ClientPrintf (host_client, PRINT_HIGH, "Map model file does not match (%s), %i != %i/%i.\n" "You may need a new version of the map, or the proper install files.\n", sv.modelname, check, sv.worldmodel->checksum, sv.worldmodel->checksum2); SV_DropClient (host_client); return; } host_client->checksum = check; } //NOTE: This doesn't go through ClientReliableWrite since it's before the user //spawns. These functions are written to not overflow if (host_client->num_backbuf) { Con_Printf("WARNING %s: [SV_PreSpawn] Back buffered (%d0, clearing", host_client->name, host_client->netchan.message.cursize); host_client->num_backbuf = 0; SZ_Clear(&host_client->netchan.message); } SZ_Write (&host_client->netchan.message, sv.signon_buffers[buf], sv.signon_buffer_size[buf]); buf++; if (buf == sv.num_signon_buffers) { // all done prespawning MSG_WriteByte (&host_client->netchan.message, svc_stufftext); MSG_WriteString (&host_client->netchan.message, va("cmd spawn %i 0\n",svs.spawncount) ); } else { // need to prespawn more MSG_WriteByte (&host_client->netchan.message, svc_stufftext); MSG_WriteString (&host_client->netchan.message, va("cmd prespawn %i %i\n", svs.spawncount, buf) ); } }