public static void Host_Name_f() { if (cmd_argc == 1) { Con_Printf("\"name\" is \"{0}\"\n", cl_name.@string); return; } string newName; if (cmd_argc == 2) { newName = Cmd_Argv(1); } else { newName = cmd_args; } if (newName.Length > 16) { newName = newName.Remove(15); } if (cmd_source == cmd_source_t.src_command) { if (cl_name.@string == newName) { return; } Cvar.Cvar_Set("_cl_name", newName); if (cls.state == cactive_t.ca_connected) { Cmd_ForwardToServer(); } return; } if (!String.IsNullOrEmpty(host_client.name) && host_client.name != "unconnected") { if (host_client.name != newName) { Con_Printf("{0} renamed to {1}\n", host_client.name, newName); } } host_client.name = newName; host_client.edict.v.netname = ED_NewString(newName); // send notification to all clients MsgWriter msg = sv.reliable_datagram; msg.MSG_WriteByte(q_shared.svc_updatename); msg.MSG_WriteByte(ClientNum); msg.MSG_WriteString(newName); }
public static void Host_Color_f() { if (cmd_argc == 1) { Con_Printf("\"color\" is \"{0} {1}\"\n", ((int)cl_color.value) >> 4, ((int)cl_color.value) & 0x0f); Con_Printf("color <0-13> [0-13]\n"); return; } int top, bottom; if (cmd_argc == 2) { top = bottom = atoi(Cmd_Argv(1)); } else { top = atoi(Cmd_Argv(1)); bottom = atoi(Cmd_Argv(2)); } top &= 15; if (top > 13) { top = 13; } bottom &= 15; if (bottom > 13) { bottom = 13; } int playercolor = top * 16 + bottom; if (cmd_source == cmd_source_t.src_command) { Cvar.Cvar_SetValue("_cl_color", playercolor); if (cls.state == cactive_t.ca_connected) { Cmd_ForwardToServer(); } return; } host_client.colors = playercolor; host_client.edict.v.team = bottom + 1; // send notification to all clients MsgWriter msg = sv.reliable_datagram; msg.MSG_WriteByte(q_shared.svc_updatecolors); msg.MSG_WriteByte(ClientNum); msg.MSG_WriteByte(host_client.colors); }
public static bool SV_SendClientDatagram(client_t client) { MsgWriter msg = new MsgWriter(q_shared.MAX_DATAGRAM); // Uze todo: make static? msg.MSG_WriteByte(q_shared.svc_time); msg.MSG_WriteFloat((float)sv.time); // add the client specific data to the datagram SV_WriteClientdataToMessage(client.edict, msg); SV_WriteEntitiesToClient(client.edict, msg); // copy the server datagram if there is space if (msg.Length + sv.datagram.Length < msg.Capacity) { msg.Write(sv.datagram.Data, 0, sv.datagram.Length); } // send the datagram if (NET_SendUnreliableMessage(client.netconnection, msg) == -1) { SV_DropClient(true);// if the message couldn't send, kick off return(false); } return(true); }
public static void Cmd_ForwardToServer() { if (cls.state != cactive_t.ca_connected) { Con_Printf("Can't \"{0}\", not connected\n", Cmd_Argv(0)); return; } if (cls.demoplayback) { return; // not really connected } MsgWriter writer = cls.message; writer.MSG_WriteByte(q_shared.clc_stringcmd); if (!Cmd_Argv(0).Equals("cmd")) { writer.SZ_Print(Cmd_Argv(0) + " "); } if (cmd_argc > 1) { writer.SZ_Print(cmd_args); } else { writer.SZ_Print("\n"); } }
public static void SV_DropClient(bool crash) { client_t client = host_client; if (!crash) { // send any final messages (don't check for errors) if (NET_CanSendMessage(client.netconnection)) { MsgWriter msg = client.message; msg.MSG_WriteByte(q_shared.svc_disconnect); NET_SendMessage(client.netconnection, msg); } if (client.edict != null && client.spawned) { // call the prog function for removing a client // this will set the body to a dead frame, among other things int saveSelf = pr_global_struct.self; pr_global_struct.self = EDICT_TO_PROG(client.edict); PR_ExecuteProgram(pr_global_struct.ClientDisconnect); pr_global_struct.self = saveSelf; } Con_DPrintf("Client {0} removed\n", client.name); } // break the net connection NET_Close(client.netconnection); client.netconnection = null; // free the client (the body stays around) client.active = false; client.name = null; client.old_frags = -999999; net_activeconnections--; // send notification to all clients for (int i = 0; i < svs.maxclients; i++) { client_t cl = svs.clients[i]; if (!cl.active) { continue; } cl.message.MSG_WriteByte(q_shared.svc_updatename); cl.message.MSG_WriteByte(ClientNum); cl.message.MSG_WriteString(""); cl.message.MSG_WriteByte(q_shared.svc_updatefrags); cl.message.MSG_WriteByte(ClientNum); cl.message.MSG_WriteShort(0); cl.message.MSG_WriteByte(q_shared.svc_updatecolors); cl.message.MSG_WriteByte(ClientNum); cl.message.MSG_WriteByte(0); } }
static void PF_makestatic() { edict_t ent = G_EDICT(q_shared.OFS_PARM0); MsgWriter msg = sv.signon; msg.MSG_WriteByte(q_shared.svc_spawnstatic); msg.MSG_WriteByte(SV_ModelIndex(GetString(ent.v.model))); msg.MSG_WriteByte((int)ent.v.frame); msg.MSG_WriteByte((int)ent.v.colormap); msg.MSG_WriteByte((int)ent.v.skin); for (int i = 0; i < 3; i++) { msg.MSG_WriteCoord(Mathlib.Comp(ref ent.v.origin, i)); msg.MSG_WriteAngle(Mathlib.Comp(ref ent.v.angles, i)); } // throw the entity away now ED_Free(ent); }
public static void Host_PreSpawn_f() { if (cmd_source == cmd_source_t.src_command) { Con_Printf("prespawn is not valid from the console\n"); return; } if (host_client.spawned) { Con_Printf("prespawn not valid -- allready spawned\n"); return; } MsgWriter msg = host_client.message; msg.Write(sv.signon.Data, 0, sv.signon.Length); msg.MSG_WriteByte(q_shared.svc_signonnum); msg.MSG_WriteByte(2); host_client.sendsignon = true; }
public static void SV_BroadcastPrint(string fmt, params object[] args) { string tmp = args.Length > 0 ? String.Format(fmt, args) : fmt; for (int i = 0; i < svs.maxclients; i++) { if (svs.clients[i].active && svs.clients[i].spawned) { MsgWriter msg = svs.clients[i].message; msg.MSG_WriteByte(q_shared.svc_print); msg.MSG_WriteString(tmp); } } }
static unsafe void PF_ambientsound() { float *pos = G_VECTOR(q_shared.OFS_PARM0); string samp = G_STRING(q_shared.OFS_PARM1); float vol = G_FLOAT(q_shared.OFS_PARM2); float attenuation = G_FLOAT(q_shared.OFS_PARM3); // check to see if samp was properly precached for (int i = 0; i < sv.sound_precache.Length; i++) { if (sv.sound_precache[i] == null) { break; } if (samp == sv.sound_precache[i]) { // add an svc_spawnambient command to the level signon packet MsgWriter msg = sv.signon; msg.MSG_WriteByte(q_shared.svc_spawnstaticsound); for (int i2 = 0; i2 < 3; i2++) { msg.MSG_WriteCoord(pos[i2]); } msg.MSG_WriteByte(i); msg.MSG_WriteByte((int)(vol * 255)); msg.MSG_WriteByte((int)(attenuation * 64)); return; } } Con_Printf("no precache: {0}\n", samp); }
public static void Host_Spawn_f() { if (cmd_source == cmd_source_t.src_command) { Con_Printf("spawn is not valid from the console\n"); return; } if (host_client.spawned) { Con_Printf("Spawn not valid -- allready spawned\n"); return; } edict_t ent; // run the entrance script if (sv.loadgame) { // loaded games are fully inited allready // if this is the last client to be connected, unpause sv.paused = false; } else { // set up the edict ent = host_client.edict; ent.Clear(); //memset(&ent.v, 0, progs.entityfields * 4); ent.v.colormap = NUM_FOR_EDICT(ent); ent.v.team = (host_client.colors & 15) + 1; ent.v.netname = ED_NewString(host_client.name); // copy spawn parms out of the client_t pr_global_struct.SetParams(host_client.spawn_parms); // call the spawn function pr_global_struct.time = (float)sv.time; pr_global_struct.self = EDICT_TO_PROG(sv_player); PR_ExecuteProgram(pr_global_struct.ClientConnect); if ((Sys_FloatTime() - host_client.netconnection.connecttime) <= sv.time) { Con_DPrintf("{0} entered the game\n", host_client.name); } PR_ExecuteProgram(pr_global_struct.PutClientInServer); } // send all current names, colors, and frag counts MsgWriter msg = host_client.message; msg.Clear(); // send time of update msg.MSG_WriteByte(q_shared.svc_time); msg.MSG_WriteFloat((float)sv.time); for (int i = 0; i < svs.maxclients; i++) { client_t client = svs.clients[i]; msg.MSG_WriteByte(q_shared.svc_updatename); msg.MSG_WriteByte(i); msg.MSG_WriteString(client.name); msg.MSG_WriteByte(q_shared.svc_updatefrags); msg.MSG_WriteByte(i); msg.MSG_WriteShort(client.old_frags); msg.MSG_WriteByte(q_shared.svc_updatecolors); msg.MSG_WriteByte(i); msg.MSG_WriteByte(client.colors); } // send all current light styles for (int i = 0; i < q_shared.MAX_LIGHTSTYLES; i++) { msg.MSG_WriteByte(q_shared.svc_lightstyle); msg.MSG_WriteByte((char)i); msg.MSG_WriteString(sv.lightstyles[i]); } // // send some stats // msg.MSG_WriteByte(q_shared.svc_updatestat); msg.MSG_WriteByte(q_shared.STAT_TOTALSECRETS); msg.MSG_WriteLong((int)pr_global_struct.total_secrets); msg.MSG_WriteByte(q_shared.svc_updatestat); msg.MSG_WriteByte(q_shared.STAT_TOTALMONSTERS); msg.MSG_WriteLong((int)pr_global_struct.total_monsters); msg.MSG_WriteByte(q_shared.svc_updatestat); msg.MSG_WriteByte(q_shared.STAT_SECRETS); msg.MSG_WriteLong((int)pr_global_struct.found_secrets); msg.MSG_WriteByte(q_shared.svc_updatestat); msg.MSG_WriteByte(q_shared.STAT_MONSTERS); msg.MSG_WriteLong((int)pr_global_struct.killed_monsters); // // send a fixangle // 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 + ClientNum); msg.MSG_WriteByte(q_shared.svc_setangle); msg.MSG_WriteAngle(ent.v.angles.x); msg.MSG_WriteAngle(ent.v.angles.y); msg.MSG_WriteAngle(0); SV_WriteClientdataToMessage(sv_player, host_client.message); msg.MSG_WriteByte(q_shared.svc_signonnum); msg.MSG_WriteByte(3); host_client.sendsignon = true; }
public static void CL_SendMove(ref usercmd_t cmd) { cl.cmd = cmd; // cl.cmd = *cmd - struct copying!!! MsgWriter msg = new MsgWriter(128); // // send the movement message // msg.MSG_WriteByte(q_shared.clc_move); msg.MSG_WriteFloat((float)cl.mtime[0]); // so server can get ping times msg.MSG_WriteAngle(cl.viewangles.X); msg.MSG_WriteAngle(cl.viewangles.Y); msg.MSG_WriteAngle(cl.viewangles.Z); msg.MSG_WriteShort((short)cmd.forwardmove); msg.MSG_WriteShort((short)cmd.sidemove); msg.MSG_WriteShort((short)cmd.upmove); // // send button bits // int bits = 0; if ((in_attack.state & 3) != 0) { bits |= 1; } in_attack.state &= ~2; if ((in_jump.state & 3) != 0) { bits |= 2; } in_jump.state &= ~2; msg.MSG_WriteByte(bits); msg.MSG_WriteByte(in_impulse); in_impulse = 0; // // deliver the message // if (cls.demoplayback) { return; } // // allways dump the first two message, because it may contain leftover inputs // from the last level // if (++cl.movemessages <= 2) { return; } if (NET_SendUnreliableMessage(cls.netcon, msg) == -1) { Con_Printf("CL_SendMove: lost server connection\n"); CL_Disconnect(); } }
public static void SV_WriteClientdataToMessage(edict_t ent, MsgWriter msg) { // // send a damage message // if (ent.v.dmg_take != 0 || ent.v.dmg_save != 0) { edict_t other = PROG_TO_EDICT(ent.v.dmg_inflictor); msg.MSG_WriteByte(q_shared.svc_damage); msg.MSG_WriteByte((int)ent.v.dmg_save); msg.MSG_WriteByte((int)ent.v.dmg_take); msg.MSG_WriteCoord(other.v.origin.x + 0.5f * (other.v.mins.x + other.v.maxs.x)); msg.MSG_WriteCoord(other.v.origin.y + 0.5f * (other.v.mins.y + other.v.maxs.y)); msg.MSG_WriteCoord(other.v.origin.z + 0.5f * (other.v.mins.z + other.v.maxs.z)); ent.v.dmg_take = 0; ent.v.dmg_save = 0; } // // send the current viewpos offset from the view entity // SV_SetIdealPitch(); // how much to look up / down ideally // a fixangle might get lost in a dropped packet. Oh well. if (ent.v.fixangle != 0) { msg.MSG_WriteByte(q_shared.svc_setangle); msg.MSG_WriteAngle(ent.v.angles.x); msg.MSG_WriteAngle(ent.v.angles.y); msg.MSG_WriteAngle(ent.v.angles.z); ent.v.fixangle = 0; } int bits = 0; if (ent.v.view_ofs.z != q_shared.DEFAULT_VIEWHEIGHT) { bits |= q_shared.SU_VIEWHEIGHT; } if (ent.v.idealpitch != 0) { bits |= q_shared.SU_IDEALPITCH; } // stuff the sigil bits into the high bits of items for sbar, or else // mix in items2 float val = GetEdictFieldFloat(ent, "items2", 0); int items; if (val != 0) { items = (int)ent.v.items | ((int)val << 23); } else { items = (int)ent.v.items | ((int)pr_global_struct.serverflags << 28); } bits |= q_shared.SU_ITEMS; if (((int)ent.v.flags & q_shared.FL_ONGROUND) != 0) { bits |= q_shared.SU_ONGROUND; } if (ent.v.waterlevel >= 2) { bits |= q_shared.SU_INWATER; } if (ent.v.punchangle.x != 0) { bits |= q_shared.SU_PUNCH1; } if (ent.v.punchangle.y != 0) { bits |= q_shared.SU_PUNCH2; } if (ent.v.punchangle.z != 0) { bits |= q_shared.SU_PUNCH3; } if (ent.v.velocity.x != 0) { bits |= q_shared.SU_VELOCITY1; } if (ent.v.velocity.y != 0) { bits |= q_shared.SU_VELOCITY2; } if (ent.v.velocity.z != 0) { bits |= q_shared.SU_VELOCITY3; } if (ent.v.weaponframe != 0) { bits |= q_shared.SU_WEAPONFRAME; } if (ent.v.armorvalue != 0) { bits |= q_shared.SU_ARMOR; } // if (ent.v.weapon) bits |= q_shared.SU_WEAPON; // send the data msg.MSG_WriteByte(q_shared.svc_clientdata); msg.MSG_WriteShort(bits); if ((bits & q_shared.SU_VIEWHEIGHT) != 0) { msg.MSG_WriteChar((int)ent.v.view_ofs.z); } if ((bits & q_shared.SU_IDEALPITCH) != 0) { msg.MSG_WriteChar((int)ent.v.idealpitch); } if ((bits & q_shared.SU_PUNCH1) != 0) { msg.MSG_WriteChar((int)ent.v.punchangle.x); } if ((bits & q_shared.SU_VELOCITY1) != 0) { msg.MSG_WriteChar((int)(ent.v.velocity.x / 16)); } if ((bits & q_shared.SU_PUNCH2) != 0) { msg.MSG_WriteChar((int)ent.v.punchangle.y); } if ((bits & q_shared.SU_VELOCITY2) != 0) { msg.MSG_WriteChar((int)(ent.v.velocity.y / 16)); } if ((bits & q_shared.SU_PUNCH3) != 0) { msg.MSG_WriteChar((int)ent.v.punchangle.z); } if ((bits & q_shared.SU_VELOCITY3) != 0) { msg.MSG_WriteChar((int)(ent.v.velocity.z / 16)); } // always sent msg.MSG_WriteLong(items); if ((bits & q_shared.SU_WEAPONFRAME) != 0) { msg.MSG_WriteByte((int)ent.v.weaponframe); } if ((bits & q_shared.SU_ARMOR) != 0) { msg.MSG_WriteByte((int)ent.v.armorvalue); } if ((bits & q_shared.SU_WEAPON) != 0) { msg.MSG_WriteByte(SV_ModelIndex(GetString(ent.v.weaponmodel))); } msg.MSG_WriteShort((int)ent.v.health); msg.MSG_WriteByte((int)ent.v.currentammo); msg.MSG_WriteByte((int)ent.v.ammo_shells); msg.MSG_WriteByte((int)ent.v.ammo_nails); msg.MSG_WriteByte((int)ent.v.ammo_rockets); msg.MSG_WriteByte((int)ent.v.ammo_cells); if (_GameKind == GameKind.StandardQuake) { msg.MSG_WriteByte((int)ent.v.weapon); } else { for (int i = 0; i < 32; i++) { if ((((int)ent.v.weapon) & (1 << i)) != 0) { msg.MSG_WriteByte(i); break; } } } }
public static void SV_WriteEntitiesToClient(edict_t clent, MsgWriter msg) { // find the client's PVS Vector3 org = ToVector(ref clent.v.origin) + ToVector(ref clent.v.view_ofs); byte[] pvs = SV_FatPVS(ref org); // send over all entities (except the client) that touch the pvs for (int e = 1; e < sv.num_edicts; e++) { edict_t ent = sv.edicts[e]; // ignore if not touching a PV leaf if (ent != clent) // clent is ALLWAYS sent { // ignore ents without visible models string mname = GetString(ent.v.model); if (String.IsNullOrEmpty(mname)) { continue; } int i; for (i = 0; i < ent.num_leafs; i++) { if ((pvs[ent.leafnums[i] >> 3] & (1 << (ent.leafnums[i] & 7))) != 0) { break; } } if (i == ent.num_leafs) { continue; // not visible } } if (msg.Capacity - msg.Length < 16) { Con_Printf("packet overflow\n"); return; } // send an update int bits = 0; v3f miss; Mathlib.VectorSubtract(ref ent.v.origin, ref ent.baseline.origin, out miss); if (miss.x < -0.1f || miss.x > 0.1f) { bits |= q_shared.U_ORIGIN1; } if (miss.y < -0.1f || miss.y > 0.1f) { bits |= q_shared.U_ORIGIN2; } if (miss.z < -0.1f || miss.z > 0.1f) { bits |= q_shared.U_ORIGIN3; } if (ent.v.angles.x != ent.baseline.angles.x) { bits |= q_shared.U_ANGLE1; } if (ent.v.angles.y != ent.baseline.angles.y) { bits |= q_shared.U_ANGLE2; } if (ent.v.angles.z != ent.baseline.angles.z) { bits |= q_shared.U_ANGLE3; } if (ent.v.movetype == q_shared.MOVETYPE_STEP) { bits |= q_shared.U_NOLERP; // don't mess up the step animation } if (ent.baseline.colormap != ent.v.colormap) { bits |= q_shared.U_COLORMAP; } if (ent.baseline.skin != ent.v.skin) { bits |= q_shared.U_SKIN; } if (ent.baseline.frame != ent.v.frame) { bits |= q_shared.U_FRAME; } if (ent.baseline.effects != ent.v.effects) { bits |= q_shared.U_EFFECTS; } if (ent.baseline.modelindex != ent.v.modelindex) { bits |= q_shared.U_MODEL; } if (e >= 256) { bits |= q_shared.U_LONGENTITY; } if (bits >= 256) { bits |= q_shared.U_MOREBITS; } // // write the message // msg.MSG_WriteByte(bits | q_shared.U_SIGNAL); if ((bits & q_shared.U_MOREBITS) != 0) { msg.MSG_WriteByte(bits >> 8); } if ((bits & q_shared.U_LONGENTITY) != 0) { msg.MSG_WriteShort(e); } else { msg.MSG_WriteByte(e); } if ((bits & q_shared.U_MODEL) != 0) { msg.MSG_WriteByte((int)ent.v.modelindex); } if ((bits & q_shared.U_FRAME) != 0) { msg.MSG_WriteByte((int)ent.v.frame); } if ((bits & q_shared.U_COLORMAP) != 0) { msg.MSG_WriteByte((int)ent.v.colormap); } if ((bits & q_shared.U_SKIN) != 0) { msg.MSG_WriteByte((int)ent.v.skin); } if ((bits & q_shared.U_EFFECTS) != 0) { msg.MSG_WriteByte((int)ent.v.effects); } if ((bits & q_shared.U_ORIGIN1) != 0) { msg.MSG_WriteCoord(ent.v.origin.x); } if ((bits & q_shared.U_ANGLE1) != 0) { msg.MSG_WriteAngle(ent.v.angles.x); } if ((bits & q_shared.U_ORIGIN2) != 0) { msg.MSG_WriteCoord(ent.v.origin.y); } if ((bits & q_shared.U_ANGLE2) != 0) { msg.MSG_WriteAngle(ent.v.angles.y); } if ((bits & q_shared.U_ORIGIN3) != 0) { msg.MSG_WriteCoord(ent.v.origin.z); } if ((bits & q_shared.U_ANGLE3) != 0) { msg.MSG_WriteAngle(ent.v.angles.z); } } }
public static void SV_SendServerinfo(client_t client) { MsgWriter writer = client.message; writer.MSG_WriteByte(q_shared.svc_print); writer.MSG_WriteString(String.Format("{0}\nVERSION {1,4:F2} SERVER ({2} CRC)", (char)2, q_shared.VERSION, pr_crc)); writer.MSG_WriteByte(q_shared.svc_serverinfo); writer.MSG_WriteLong(q_shared.PROTOCOL_VERSION); writer.MSG_WriteByte(svs.maxclients); if (!(coop.value != 0) && deathmatch.value != 0) { writer.MSG_WriteByte(q_shared.GAME_DEATHMATCH); } else { writer.MSG_WriteByte(q_shared.GAME_COOP); } string message = GetString(sv.edicts[0].v.message); writer.MSG_WriteString(message); for (int i = 1; i < sv.model_precache.Length; i++) { string tmp = sv.model_precache[i]; if (String.IsNullOrEmpty(tmp)) { break; } writer.MSG_WriteString(tmp); } writer.MSG_WriteByte(0); for (int i = 1; i < sv.sound_precache.Length; i++) { string tmp = sv.sound_precache[i]; if (tmp == null) { break; } writer.MSG_WriteString(tmp); } writer.MSG_WriteByte(0); // send music writer.MSG_WriteByte(q_shared.svc_cdtrack); writer.MSG_WriteByte((int)sv.edicts[0].v.sounds); writer.MSG_WriteByte((int)sv.edicts[0].v.sounds); // set view writer.MSG_WriteByte(q_shared.svc_setview); writer.MSG_WriteShort(NUM_FOR_EDICT(client.edict)); writer.MSG_WriteByte(q_shared.svc_signonnum); writer.MSG_WriteByte(1); client.sendsignon = true; client.spawned = false; // need prespawn, spawn, etc }
public static void Host_ShutdownServer(bool crash) { if (!sv.active) { return; } sv.active = false; // stop all client sounds immediately if (cls.state == cactive_t.ca_connected) { CL_Disconnect(); } // flush any pending messages - like the score!!! double start = Sys_FloatTime(); int count; do { count = 0; for (int i = 0; i < svs.maxclients; i++) { host_client = svs.clients[i]; if (host_client.active && !host_client.message.IsEmpty) { if (NET_CanSendMessage(host_client.netconnection)) { NET_SendMessage(host_client.netconnection, host_client.message); host_client.message.Clear(); } else { NET_GetMessage(host_client.netconnection); count++; } } } if ((Sys_FloatTime() - start) > 3.0) { break; } }while (count > 0); // make sure all the clients know we're disconnecting MsgWriter writer = new MsgWriter(4); writer.MSG_WriteByte(q_shared.svc_disconnect); count = NET_SendToAll(writer, 5); if (count != 0) { Con_Printf("Host_ShutdownServer: NET_SendToAll failed for {0} clients\n", count); } for (int i = 0; i < svs.maxclients; i++) { host_client = svs.clients[i]; if (host_client.active) { SV_DropClient(crash); } } // // clear structures // sv.Clear(); for (int i = 0; i < svs.clients.Length; i++) { svs.clients[i].Clear(); } }