public static Boolean SV_SendClientDatagram(client_t client) { SV_ENTS.SV_BuildClientFrame(client); SZ.Init(msg, msgbuf, msgbuf.Length); msg.allowoverflow = true; SV_ENTS.SV_WriteFrameToClient(client, msg); if (client.datagram.overflowed) { Com.Printf("WARNING: datagram overflowed for " + client.name + "\\n"); } else { SZ.Write(msg, client.datagram.data, client.datagram.cursize); } SZ.Clear(client.datagram); if (msg.overflowed) { Com.Printf("WARNING: msg overflowed for " + client.name + "\\n"); SZ.Clear(msg); } Netchan.Transmit(client.netchan, msg.cursize, msg.data); client.message_size[SV_INIT.sv.framenum % Defines.RATE_MESSAGES] = msg.cursize; return(true); }
public static void SV_FinalMessage(String message, Boolean reconnect) { Int32 i; client_t cl; SZ.Clear(Globals.net_message); MSG.WriteByte(Globals.net_message, Defines.svc_print); MSG.WriteByte(Globals.net_message, Defines.PRINT_HIGH); MSG.WriteString(Globals.net_message, message); if (reconnect) { MSG.WriteByte(Globals.net_message, Defines.svc_reconnect); } else { MSG.WriteByte(Globals.net_message, Defines.svc_disconnect); } for (i = 0; i < SV_INIT.svs.clients.Length; i++) { cl = SV_INIT.svs.clients[i]; if (cl.state >= Defines.cs_connected) { Netchan.Transmit(cl.netchan, Globals.net_message.cursize, Globals.net_message.data); } } for (i = 0; i < SV_INIT.svs.clients.Length; i++) { cl = SV_INIT.svs.clients[i]; if (cl.state >= Defines.cs_connected) { Netchan.Transmit(cl.netchan, Globals.net_message.cursize, Globals.net_message.data); } } }
public static void PF_Unicast(edict_t ent, bool reliable) { int p; client_t client; if (ent == null) { return; } p = ent.index; if (p < 1 || p > SV_MAIN.maxclients.value) { return; } client = SV_INIT.svs.clients[p - 1]; if (reliable) { SZ.Write(client.netchan.message, SV_INIT.sv.multicast.data, SV_INIT.sv.multicast.cursize); } else { SZ.Write(client.datagram, SV_INIT.sv.multicast.data, SV_INIT.sv.multicast.cursize); } SZ.Clear(SV_INIT.sv.multicast); }
public static Int32 SV_FindIndex(String name, Int32 start, Int32 max, Boolean create) { Int32 i; if (name == null || name.Length == 0) { return(0); } for (i = 1; i < max && sv.configstrings[start + i] != null; i++) { if (0 == Lib.Strcmp(sv.configstrings[start + i], name)) { return(i); } } if (!create) { return(0); } if (i == max) { Com.Error(Defines.ERR_DROP, "*Index: overflow"); } sv.configstrings[start + i] = name; if (sv.state != Defines.ss_loading) { SZ.Clear(sv.multicast); MSG.WriteChar(sv.multicast, Defines.svc_configstring); MSG.WriteShort(sv.multicast, start + i); MSG.WriteString(sv.multicast, name); SV_SEND.SV_Multicast(Globals.vec3_origin, Defines.MULTICAST_ALL_R); } return(i); }
/** * PF_Configstring */ public static void PF_Configstring(int index, string val) { if (index < 0 || index >= Defines.MAX_CONFIGSTRINGS) { Com.Error(Defines.ERR_DROP, "configstring: bad index " + index + "\n"); } if (val == null) { val = ""; } // change the string in sv SV_INIT.sv.configstrings[index] = val; if (SV_INIT.sv.state != Defines.ss_loading) { // send the update to // everyone SZ.Clear(SV_INIT.sv.multicast); MSG.WriteChar(SV_INIT.sv.multicast, Defines.svc_configstring); MSG.WriteShort(SV_INIT.sv.multicast, index); MSG.WriteString(SV_INIT.sv.multicast, val); SV_SEND.SV_Multicast(Globals.vec3_origin, Defines.MULTICAST_ALL_R); } }
/** * Save everything in the world out without deltas. Used for recording * footage for merged or assembled demos. */ public static void SV_RecordDemoMessage() { if (SV_INIT.svs.demofile == null) { return; } //memset (nostate, 0, sizeof(nostate)); entity_state_t nostate = new(null); sizebuf_t buf = new(); SZ.Init(buf, SV_ENTS.buf_data, SV_ENTS.buf_data.Length); // write a frame message that doesn't contain a player_state_t MSG.WriteByte(buf, Defines.svc_frame); MSG.WriteLong(buf, SV_INIT.sv.framenum); MSG.WriteByte(buf, Defines.svc_packetentities); var e = 1; var ent = GameBase.g_edicts[e]; while (e < GameBase.num_edicts) { // ignore ents without visible models unless they have an effect if (ent.inuse && ent.s.number != 0 && (ent.s.modelindex != 0 || ent.s.effects != 0 || ent.s.sound != 0 || ent.s.@event != 0) && 0 == (ent.svflags & Defines.SVF_NOCLIENT)) { MSG.WriteDeltaEntity(nostate, ent.s, buf, false, true); } e++; ent = GameBase.g_edicts[e]; } MSG.WriteShort(buf, 0); // end of packetentities // now add the accumulated multicast information SZ.Write(buf, SV_INIT.svs.demo_multicast.data, SV_INIT.svs.demo_multicast.cursize); SZ.Clear(SV_INIT.svs.demo_multicast); // now write the entire message to the file, prefixed by the length var len = EndianHandler.swapInt(buf.cursize); try { //fwrite (len, 4, 1, svs.demofile); SV_INIT.svs.demofile.Write(len); //fwrite (buf.data, buf.cursize, 1, svs.demofile); SV_INIT.svs.demofile.Write(buf.data, 0, buf.cursize); } catch (Exception) { Com.Printf("Error writing demo file:" + e); } }
/** * Used by SV_Shutdown to send a final message to all connected clients * before the server goes down. The messages are sent immediately, not just * stuck on the outgoing message list, because the server is going to * totally exit after returning from this function. */ public static void SV_FinalMessage(string message, bool reconnect) { int i; client_t cl; SZ.Clear(Globals.net_message); MSG.WriteByte(Globals.net_message, Defines.svc_print); MSG.WriteByte(Globals.net_message, Defines.PRINT_HIGH); MSG.WriteString(Globals.net_message, message); if (reconnect) { MSG.WriteByte(Globals.net_message, Defines.svc_reconnect); } else { MSG.WriteByte(Globals.net_message, Defines.svc_disconnect); } // send it twice // stagger the packets to crutch operating system limited buffers for (i = 0; i < SV_INIT.svs.clients.Length; i++) { cl = SV_INIT.svs.clients[i]; if (cl.state >= Defines.cs_connected) { Netchan.Transmit(cl.netchan, Globals.net_message.cursize, Globals.net_message.data); } } for (i = 0; i < SV_INIT.svs.clients.Length; i++) { cl = SV_INIT.svs.clients[i]; if (cl.state >= Defines.cs_connected) { Netchan.Transmit(cl.netchan, Globals.net_message.cursize, Globals.net_message.data); } } }
/** * SV_FindIndex. */ public static int SV_FindIndex(string name, int start, int max, bool create) { int i; if (name == null || name.Length == 0) { return(0); } for (i = 1; i < max && SV_INIT.sv.configstrings[start + i] != null; i++) { if (0 == Lib.strcmp(SV_INIT.sv.configstrings[start + i], name)) { return(i); } } if (!create) { return(0); } if (i == max) { Com.Error(Defines.ERR_DROP, "*Index: overflow"); } SV_INIT.sv.configstrings[start + i] = name; if (SV_INIT.sv.state != Defines.ss_loading) { // send the update to everyone SZ.Clear(SV_INIT.sv.multicast); MSG.WriteChar(SV_INIT.sv.multicast, Defines.svc_configstring); MSG.WriteShort(SV_INIT.sv.multicast, start + i); MSG.WriteString(SV_INIT.sv.multicast, name); SV_SEND.SV_Multicast(Globals.vec3_origin, Defines.MULTICAST_ALL_R); } return(i); }
public static void SV_RecordDemoMessage( ) { if (SV_INIT.svs.demofile == null) { return; } entity_state_t nostate = new entity_state_t(null); sizebuf_t buf = new sizebuf_t(); SZ.Init(buf, buf_data, buf_data.Length); MSG.WriteByte(buf, Defines.svc_frame); MSG.WriteLong(buf, SV_INIT.sv.framenum); MSG.WriteByte(buf, Defines.svc_packetentities); var e = 1; edict_t ent = GameBase.g_edicts[e]; while (e < GameBase.num_edicts) { if (ent.inuse && ent.s.number != 0 && (ent.s.modelindex != 0 || ent.s.effects != 0 || ent.s.sound != 0 || ent.s.event_renamed != 0) && 0 == (ent.svflags & Defines.SVF_NOCLIENT)) { MSG.WriteDeltaEntity(nostate, ent.s, buf, false, true); } e++; ent = GameBase.g_edicts[e]; } MSG.WriteShort(buf, 0); SZ.Write(buf, SV_INIT.svs.demo_multicast.data, SV_INIT.svs.demo_multicast.cursize); SZ.Clear(SV_INIT.svs.demo_multicast); var len = EndianHandler.SwapInt(buf.cursize); try { SV_INIT.svs.demofile.Write(len); SV_INIT.svs.demofile.Write(buf.data, 0, buf.cursize); } catch (Exception e1) { Com.Printf("Error writing demo file:" + e); } }
public static void SV_Multicast(Single[] origin, Int32 to) { client_t client; Byte[] mask = null; Int32 leafnum, cluster; Int32 j; Boolean reliable; Int32 area1, area2; reliable = false; if (to != Defines.MULTICAST_ALL_R && to != Defines.MULTICAST_ALL) { leafnum = CM.CM_PointLeafnum(origin); area1 = CM.CM_LeafArea(leafnum); } else { leafnum = 0; area1 = 0; } if (SV_INIT.svs.demofile != null) { SZ.Write(SV_INIT.svs.demo_multicast, SV_INIT.sv.multicast.data, SV_INIT.sv.multicast.cursize); } switch (to) { case Defines.MULTICAST_ALL_R: reliable = true; break; case Defines.MULTICAST_ALL: leafnum = 0; mask = null; break; case Defines.MULTICAST_PHS_R: reliable = true; break; case Defines.MULTICAST_PHS: leafnum = CM.CM_PointLeafnum(origin); cluster = CM.CM_LeafCluster(leafnum); mask = CM.CM_ClusterPHS(cluster); break; case Defines.MULTICAST_PVS_R: reliable = true; break; case Defines.MULTICAST_PVS: leafnum = CM.CM_PointLeafnum(origin); cluster = CM.CM_LeafCluster(leafnum); mask = CM.CM_ClusterPVS(cluster); break; default: mask = null; Com.Error(Defines.ERR_FATAL, "SV_Multicast: bad to:" + to + "\\n"); break; } for (j = 0; j < SV_MAIN.maxclients.value; j++) { client = SV_INIT.svs.clients[j]; if (client.state == Defines.cs_free || client.state == Defines.cs_zombie) { continue; } if (client.state != Defines.cs_spawned && !reliable) { continue; } if (mask != null) { leafnum = CM.CM_PointLeafnum(client.edict.s.origin); cluster = CM.CM_LeafCluster(leafnum); area2 = CM.CM_LeafArea(leafnum); if (!CM.CM_AreasConnected(area1, area2)) { continue; } if (cluster == -1) { continue; } if (mask != null && (0 == (mask[cluster >> 3] & (1 << (cluster & 7))))) { continue; } } if (reliable) { SZ.Write(client.netchan.message, SV_INIT.sv.multicast.data, SV_INIT.sv.multicast.cursize); } else { SZ.Write(client.datagram, SV_INIT.sv.multicast.data, SV_INIT.sv.multicast.cursize); } } SZ.Clear(SV_INIT.sv.multicast); }
public static void SV_SendClientMessages( ) { Int32 i; client_t c; Int32 msglen; Int32 r; msglen = 0; if (SV_INIT.sv.state == Defines.ss_demo && SV_INIT.sv.demofile != null) { if (SV_MAIN.sv_paused.value != 0) { msglen = 0; } else { try { msglen = EndianHandler.SwapInt(SV_INIT.sv.demofile.ReadInt32()); } catch (Exception e) { SV_DemoCompleted(); return; } if (msglen == -1) { SV_DemoCompleted(); return; } if (msglen > Defines.MAX_MSGLEN) { Com.Error(Defines.ERR_DROP, "SV_SendClientMessages: msglen > MAX_MSGLEN"); } r = 0; try { r = SV_INIT.sv.demofile.Read(msgbuf, 0, msglen); } catch (Exception e1) { Com.Printf("IOError: reading demo file, " + e1); } if (r != msglen) { SV_DemoCompleted(); return; } } } for (i = 0; i < SV_MAIN.maxclients.value; i++) { c = SV_INIT.svs.clients[i]; if (c.state == 0) { continue; } if (c.netchan.message.overflowed) { SZ.Clear(c.netchan.message); SZ.Clear(c.datagram); SV_BroadcastPrintf(Defines.PRINT_HIGH, c.name + " overflowed\\n"); SV_MAIN.SV_DropClient(c); } if (SV_INIT.sv.state == Defines.ss_cinematic || SV_INIT.sv.state == Defines.ss_demo || SV_INIT.sv.state == Defines.ss_pic) { Netchan.Transmit(c.netchan, msglen, msgbuf); } else if (c.state == Defines.cs_spawned) { if (SV_RateDrop(c)) { continue; } SV_SendClientDatagram(c); } else { if (c.netchan.message.cursize != 0 || Globals.curtime - c.netchan.last_sent > 1000) { Netchan.Transmit(c.netchan, 0, NULLBYTE); } } } }