/// <summary> /// SV_DropClient /// Called when the player is getting totally kicked off the host /// if (crash = true), don't bother sending signofs /// </summary> public static void DropClient(bool crash) { client_t client = Host.HostClient; if (!crash) { // send any final messages (don't check for errors) if (Net.CanSendMessage(client.netconnection)) { MsgWriter msg = client.message; msg.WriteByte(Protocol.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 = Progs.GlobalStruct.self; Progs.GlobalStruct.self = EdictToProg(client.edict); Progs.Execute(Progs.GlobalStruct.ClientDisconnect); Progs.GlobalStruct.self = saveSelf; } Con.DPrint("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 < Server.svs.maxclients; i++) { client_t cl = Server.svs.clients[i]; if (!cl.active) { continue; } cl.message.WriteByte(Protocol.svc_updatename); cl.message.WriteByte(Host.ClientNum); cl.message.WriteString(""); cl.message.WriteByte(Protocol.svc_updatefrags); cl.message.WriteByte(Host.ClientNum); cl.message.WriteShort(0); cl.message.WriteByte(Protocol.svc_updatecolors); cl.message.WriteByte(Host.ClientNum); cl.message.WriteByte(0); } }
/// <summary> /// Host_Kill_f /// </summary> static void Kill_f() { if (Cmd.Source == cmd_source_t.src_command) { Cmd.ForwardToServer(); return; } if (Server.Player.v.health <= 0) { Server.ClientPrint("Can't suicide -- allready dead!\n"); return; } Progs.GlobalStruct.time = (float)Server.sv.time; Progs.GlobalStruct.self = Server.EdictToProg(Server.Player); Progs.Execute(Progs.GlobalStruct.ClientKill); }
/// <summary> /// SV_SaveSpawnparms /// Grabs the current state of each client for saving across the /// transition to another level /// </summary> public static void SaveSpawnparms() { Server.svs.serverflags = (int)Progs.GlobalStruct.serverflags; for (int i = 0; i < svs.maxclients; i++) { Host.HostClient = Server.svs.clients[i]; if (!Host.HostClient.active) { continue; } // call the progs to get default spawn parms for the new client Progs.GlobalStruct.self = EdictToProg(Host.HostClient.edict); Progs.Execute(Progs.GlobalStruct.SetChangeParms); AssignGlobalSpawnparams(Host.HostClient); } }
/// <summary> /// Host_Spawn_f /// </summary> static void Spawn_f() { if (Cmd.Source == cmd_source_t.src_command) { Con.Print("spawn is not valid from the console\n"); return; } if (Host.HostClient.spawned) { Con.Print("Spawn not valid -- allready spawned\n"); return; } edict_t ent; // run the entrance script if (Server.sv.loadgame) { // loaded games are fully inited allready // if this is the last client to be connected, unpause Server.sv.paused = false; } else { // set up the edict ent = Host.HostClient.edict; ent.Clear(); //memset(&ent.v, 0, progs.entityfields * 4); ent.v.colormap = Server.NumForEdict(ent); ent.v.team = (Host.HostClient.colors & 15) + 1; ent.v.netname = Progs.NewString(Host.HostClient.name); // copy spawn parms out of the client_t Progs.GlobalStruct.SetParams(Host.HostClient.spawn_parms); // call the spawn function Progs.GlobalStruct.time = (float)Server.sv.time; Progs.GlobalStruct.self = Server.EdictToProg(Server.Player); Progs.Execute(Progs.GlobalStruct.ClientConnect); if ((Sys.GetFloatTime() - Host.HostClient.netconnection.connecttime) <= Server.sv.time) { Con.DPrint("{0} entered the game\n", Host.HostClient.name); } Progs.Execute(Progs.GlobalStruct.PutClientInServer); } // send all current names, colors, and frag counts MsgWriter msg = Host.HostClient.message; msg.Clear(); // send time of update msg.WriteByte(Protocol.svc_time); msg.WriteFloat((float)Server.sv.time); for (int i = 0; i < Server.svs.maxclients; i++) { client_t client = Server.svs.clients[i]; msg.WriteByte(Protocol.svc_updatename); msg.WriteByte(i); msg.WriteString(client.name); msg.WriteByte(Protocol.svc_updatefrags); msg.WriteByte(i); msg.WriteShort(client.old_frags); msg.WriteByte(Protocol.svc_updatecolors); msg.WriteByte(i); msg.WriteByte(client.colors); } // send all current light styles for (int i = 0; i < QDef.MAX_LIGHTSTYLES; i++) { msg.WriteByte(Protocol.svc_lightstyle); msg.WriteByte((char)i); msg.WriteString(Server.sv.lightstyles[i]); } // // send some stats // msg.WriteByte(Protocol.svc_updatestat); msg.WriteByte(QStats.STAT_TOTALSECRETS); msg.WriteLong((int)Progs.GlobalStruct.total_secrets); msg.WriteByte(Protocol.svc_updatestat); msg.WriteByte(QStats.STAT_TOTALMONSTERS); msg.WriteLong((int)Progs.GlobalStruct.total_monsters); msg.WriteByte(Protocol.svc_updatestat); msg.WriteByte(QStats.STAT_SECRETS); msg.WriteLong((int)Progs.GlobalStruct.found_secrets); msg.WriteByte(Protocol.svc_updatestat); msg.WriteByte(QStats.STAT_MONSTERS); msg.WriteLong((int)Progs.GlobalStruct.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 = Server.EdictNum(1 + Host.ClientNum); msg.WriteByte(Protocol.svc_setangle); msg.WriteAngle(ent.v.angles.x); msg.WriteAngle(ent.v.angles.y); msg.WriteAngle(0); Server.WriteClientDataToMessage(Server.Player, Host.HostClient.message); msg.WriteByte(Protocol.svc_signonnum); msg.WriteByte(3); Host.HostClient.sendsignon = true; }