/// <summary> /// ED_ParseGlobals /// </summary> public static void ParseGlobals(string data) { while (true) { // parse key data = Common.Parse(data); if (Common.Token.StartsWith("}")) { break; } if (String.IsNullOrEmpty(data)) { Sys.Error("ED_ParseEntity: EOF without closing brace"); } string keyname = Common.Token; // parse value data = Common.Parse(data); if (String.IsNullOrEmpty(data)) { Sys.Error("ED_ParseEntity: EOF without closing brace"); } if (Common.Token.StartsWith("}")) { Sys.Error("ED_ParseEntity: closing brace without data"); } ddef_t key = FindGlobal(keyname); if (key == null) { Con.Print("'{0}' is not a global\n", keyname); continue; } if (!ParseGlobalPair(key, Common.Token)) { Host.Error("ED_ParseGlobals: parse error"); } } }
// CL_ParseStartSoundPacket private void ParseStartSoundPacket( ) { var field_mask = Host.Network.Reader.ReadByte(); Int32 volume; Single attenuation; if ((field_mask & ProtocolDef.SND_VOLUME) != 0) { volume = Host.Network.Reader.ReadByte(); } else { volume = snd.DEFAULT_SOUND_PACKET_VOLUME; } if ((field_mask & ProtocolDef.SND_ATTENUATION) != 0) { attenuation = Host.Network.Reader.ReadByte() / 64.0f; } else { attenuation = snd.DEFAULT_SOUND_PACKET_ATTENUATION; } var channel = Host.Network.Reader.ReadShort(); var sound_num = Host.Network.Reader.ReadByte(); var ent = channel >> 3; channel &= 7; if (ent > QDef.MAX_EDICTS) { Host.Error("CL_ParseStartSoundPacket: ent = {0}", ent); } var pos = Host.Network.Reader.ReadCoords(); Host.Sound.StartSound(ent, channel, cl.sound_precache[sound_num], ref pos, volume / 255.0f, attenuation); }
// CL_ParseStartSoundPacket private static void ParseStartSoundPacket() { int field_mask = Net.Reader.ReadByte(); int volume; float attenuation; if ((field_mask & Protocol.SND_VOLUME) != 0) { volume = Net.Reader.ReadByte(); } else { volume = Sound.DEFAULT_SOUND_PACKET_VOLUME; } if ((field_mask & Protocol.SND_ATTENUATION) != 0) { attenuation = Net.Reader.ReadByte() / 64.0f; } else { attenuation = Sound.DEFAULT_SOUND_PACKET_ATTENUATION; } int channel = Net.Reader.ReadShort(); int sound_num = Net.Reader.ReadByte(); int ent = channel >> 3; channel &= 7; if (ent > QDef.MAX_EDICTS) { Host.Error("CL_ParseStartSoundPacket: ent = {0}", ent); } Vector3 pos = Net.Reader.ReadCoords(); Sound.StartSound(ent, channel, cl.sound_precache[sound_num], ref pos, volume / 255.0f, attenuation); }
// CL_ReadFromServer // // Read all incoming data from the server public static int ReadFromServer() { Cl.oldtime = Cl.time; Cl.time += Host.FrameTime; int ret; do { ret = GetMessage(); if (ret == -1) { Host.Error("CL_ReadFromServer: lost server connection"); } if (ret == 0) { break; } Cl.last_received_message = (float)Host.RealTime; ParseServerMessage(); } while (ret != 0 && Cls.state == ClientActivityState.Connected); if (_ShowNet.Value != 0) { Con.Print("\n"); } // // bring the links up to date // RelinkEntities(); UpdateTempEntities(); return(0); }
/// <summary> /// CL_ParseStatic /// </summary> private void ParseStatic( ) { var i = cl.num_statics; if (i >= ClientDef.MAX_STATIC_ENTITIES) { Host.Error("Too many static entities"); } var ent = _StaticEntities[i]; cl.num_statics++; ParseBaseline(ent); // copy it to the current state ent.model = cl.model_precache[ent.baseline.modelindex]; ent.frame = ent.baseline.frame; ent.colormap = Host.Screen.vid.colormap; ent.skinnum = ent.baseline.skin; ent.effects = ent.baseline.effects; ent.origin = Utilities.ToVector(ref ent.baseline.origin); ent.angles = Utilities.ToVector(ref ent.baseline.angles); Host.RenderContext.AddEfrags(ent); }
/// <summary> /// CL_ParseStatic /// </summary> private static void ParseStatic() { int i = cl.num_statics; if (i >= MAX_STATIC_ENTITIES) { Host.Error("Too many static entities"); } entity_t ent = _StaticEntities[i]; cl.num_statics++; ParseBaseline(ent); // copy it to the current state ent.model = cl.model_precache[ent.baseline.modelindex]; ent.frame = ent.baseline.frame; ent.colormap = Scr.vid.colormap; ent.skinnum = ent.baseline.skin; ent.effects = ent.baseline.effects; ent.origin = Common.ToVector(ref ent.baseline.origin); ent.angles = Common.ToVector(ref ent.baseline.angles); Render.AddEfrags(ent); }
/// <summary> /// CL_ParseUpdate /// /// Parse an entity update message from the server /// If an entities model or origin changes from frame to frame, it must be /// relinked. Other attributes can change without relinking. /// </summary> private void ParseUpdate(Int32 bits) { Int32 i; if (cls.signon == ClientDef.SIGNONS - 1) { // first update is the final signon stage cls.signon = ClientDef.SIGNONS; SignonReply(); } if ((bits & ProtocolDef.U_MOREBITS) != 0) { i = Host.Network.Reader.ReadByte(); bits |= (i << 8); } Int32 num; if ((bits & ProtocolDef.U_LONGENTITY) != 0) { num = Host.Network.Reader.ReadShort(); } else { num = Host.Network.Reader.ReadByte(); } var ent = EntityNum(num); for (i = 0; i < 16; i++) { if ((bits & (1 << i)) != 0) { _BitCounts[i]++; } } var forcelink = false; if (ent.msgtime != cl.mtime[1]) { forcelink = true; // no previous frame to lerp from } ent.msgtime = cl.mtime[0]; Int32 modnum; if ((bits & ProtocolDef.U_MODEL) != 0) { modnum = Host.Network.Reader.ReadByte(); if (modnum >= QDef.MAX_MODELS) { Host.Error("CL_ParseModel: bad modnum"); } } else { modnum = ent.baseline.modelindex; } var model = cl.model_precache[modnum]; if (model != ent.model) { ent.model = model; // automatic animation (torches, etc) can be either all together // or randomized if (model != null) { if (model.SyncType == SyncType.ST_RAND) { ent.syncbase = ( Single )(MathLib.Random() & 0x7fff) / 0x7fff; } else { ent.syncbase = 0; } } else { forcelink = true; // hack to make null model players work } if (num > 0 && num <= cl.maxclients) { Host.RenderContext.TranslatePlayerSkin(num - 1); } } if ((bits & ProtocolDef.U_FRAME) != 0) { ent.frame = Host.Network.Reader.ReadByte(); } else { ent.frame = ent.baseline.frame; } if ((bits & ProtocolDef.U_COLORMAP) != 0) { i = Host.Network.Reader.ReadByte(); } else { i = ent.baseline.colormap; } if (i == 0) { ent.colormap = Host.Screen.vid.colormap; } else { if (i > cl.maxclients) { Utilities.Error("i >= cl.maxclients"); } ent.colormap = cl.scores[i - 1].translations; } Int32 skin; if ((bits & ProtocolDef.U_SKIN) != 0) { skin = Host.Network.Reader.ReadByte(); } else { skin = ent.baseline.skin; } if (skin != ent.skinnum) { ent.skinnum = skin; if (num > 0 && num <= cl.maxclients) { Host.RenderContext.TranslatePlayerSkin(num - 1); } } if ((bits & ProtocolDef.U_EFFECTS) != 0) { ent.effects = Host.Network.Reader.ReadByte(); } else { ent.effects = ent.baseline.effects; } // shift the known values for interpolation ent.msg_origins[1] = ent.msg_origins[0]; ent.msg_angles[1] = ent.msg_angles[0]; if ((bits & ProtocolDef.U_ORIGIN1) != 0) { ent.msg_origins[0].X = Host.Network.Reader.ReadCoord(); } else { ent.msg_origins[0].X = ent.baseline.origin.x; } if ((bits & ProtocolDef.U_ANGLE1) != 0) { ent.msg_angles[0].X = Host.Network.Reader.ReadAngle(); } else { ent.msg_angles[0].X = ent.baseline.angles.x; } if ((bits & ProtocolDef.U_ORIGIN2) != 0) { ent.msg_origins[0].Y = Host.Network.Reader.ReadCoord(); } else { ent.msg_origins[0].Y = ent.baseline.origin.y; } if ((bits & ProtocolDef.U_ANGLE2) != 0) { ent.msg_angles[0].Y = Host.Network.Reader.ReadAngle(); } else { ent.msg_angles[0].Y = ent.baseline.angles.y; } if ((bits & ProtocolDef.U_ORIGIN3) != 0) { ent.msg_origins[0].Z = Host.Network.Reader.ReadCoord(); } else { ent.msg_origins[0].Z = ent.baseline.origin.z; } if ((bits & ProtocolDef.U_ANGLE3) != 0) { ent.msg_angles[0].Z = Host.Network.Reader.ReadAngle(); } else { ent.msg_angles[0].Z = ent.baseline.angles.z; } if ((bits & ProtocolDef.U_NOLERP) != 0) { ent.forcelink = true; } if (forcelink) { // didn't have an update last message ent.msg_origins[1] = ent.msg_origins[0]; ent.origin = ent.msg_origins[0]; ent.msg_angles[1] = ent.msg_angles[0]; ent.angles = ent.msg_angles[0]; ent.forcelink = true; } }
/// <summary> /// ED_ParseEdict /// Parses an edict out of the given string, returning the new position /// ed should be a properly initialized empty edict. /// Used for initial level load and for savegames. /// </summary> public static string ParseEdict(string data, edict_t ent) { bool init = false; // clear it if (ent != Server.sv.edicts[0]) // hack { ent.Clear(); } // go through all the dictionary pairs bool anglehack; while (true) { // parse key data = Common.Parse(data); if (Common.Token.StartsWith("}")) { break; } if (data == null) { Sys.Error("ED_ParseEntity: EOF without closing brace"); } string token = Common.Token; // anglehack is to allow QuakeEd to write single scalar angles // and allow them to be turned into vectors. (FIXME...) if (token == "angle") { token = "angles"; anglehack = true; } else { anglehack = false; } // FIXME: change light to _light to get rid of this hack if (token == "light") { token = "light_lev"; // hack for single light def } string keyname = token.TrimEnd(); // parse value data = Common.Parse(data); if (data == null) { Sys.Error("ED_ParseEntity: EOF without closing brace"); } if (Common.Token.StartsWith("}")) { Sys.Error("ED_ParseEntity: closing brace without data"); } init = true; // keynames with a leading underscore are used for utility comments, // and are immediately discarded by quake if (keyname[0] == '_') { continue; } ddef_t key = FindField(keyname); if (key == null) { Con.Print("'{0}' is not a field\n", keyname); continue; } token = Common.Token; if (anglehack) { token = "0 " + token + " 0"; } if (!ParsePair(ent, key, token)) { Host.Error("ED_ParseEdict: parse error"); } } if (!init) { ent.free = true; } return(data); }
private Single _LastMsg; // static float lastmsg from CL_KeepaliveMessage /// <summary> /// CL_ParseServerMessage /// </summary> private void ParseServerMessage() { // // if recording demos, copy the message out // if (Host.Cvars.ShowNet.Get <Int32>( ) == 1) { Host.Console.Print("{0} ", Host.Network.Message.Length); } else if (Host.Cvars.ShowNet.Get <Int32>( ) == 2) { Host.Console.Print("------------------\n"); } cl.onground = false; // unless the server says otherwise // // parse the message // Host.Network.Reader.Reset(); Int32 i; while (true) { if (Host.Network.Reader.IsBadRead) { Host.Error("CL_ParseServerMessage: Bad server message"); } var cmd = Host.Network.Reader.ReadByte(); if (cmd == -1) { ShowNet("END OF MESSAGE"); return; // end of message } // if the high bit of the command byte is set, it is a fast update if ((cmd & 128) != 0) { ShowNet("fast update"); ParseUpdate(cmd & 127); continue; } ShowNet(_SvcStrings[cmd]); // other commands switch (cmd) { default: Host.Error("CL_ParseServerMessage: Illegible server message\n"); break; case ProtocolDef.svc_nop: break; case ProtocolDef.svc_time: cl.mtime[1] = cl.mtime[0]; cl.mtime[0] = Host.Network.Reader.ReadFloat(); break; case ProtocolDef.svc_clientdata: i = Host.Network.Reader.ReadShort(); ParseClientData(i); break; case ProtocolDef.svc_version: i = Host.Network.Reader.ReadLong(); if (i != ProtocolDef.PROTOCOL_VERSION) { Host.Error("CL_ParseServerMessage: Server is protocol {0} instead of {1}\n", i, ProtocolDef.PROTOCOL_VERSION); } break; case ProtocolDef.svc_disconnect: Host.EndGame("Server disconnected\n"); break; case ProtocolDef.svc_print: Host.Console.Print(Host.Network.Reader.ReadString()); break; case ProtocolDef.svc_centerprint: Host.Screen.CenterPrint(Host.Network.Reader.ReadString()); break; case ProtocolDef.svc_stufftext: Host.Commands.Buffer.Append(Host.Network.Reader.ReadString()); break; case ProtocolDef.svc_damage: Host.View.ParseDamage(); break; case ProtocolDef.svc_serverinfo: ParseServerInfo(); Host.Screen.vid.recalc_refdef = true; // leave intermission full screen break; case ProtocolDef.svc_setangle: cl.viewangles.X = Host.Network.Reader.ReadAngle(); cl.viewangles.Y = Host.Network.Reader.ReadAngle(); cl.viewangles.Z = Host.Network.Reader.ReadAngle(); break; case ProtocolDef.svc_setview: cl.viewentity = Host.Network.Reader.ReadShort(); break; case ProtocolDef.svc_lightstyle: i = Host.Network.Reader.ReadByte(); if (i >= QDef.MAX_LIGHTSTYLES) { Utilities.Error("svc_lightstyle > MAX_LIGHTSTYLES"); } _LightStyle[i].map = Host.Network.Reader.ReadString(); break; case ProtocolDef.svc_sound: ParseStartSoundPacket(); break; case ProtocolDef.svc_stopsound: i = Host.Network.Reader.ReadShort(); Host.Sound.StopSound(i >> 3, i & 7); break; case ProtocolDef.svc_updatename: Host.Hud.Changed(); i = Host.Network.Reader.ReadByte(); if (i >= cl.maxclients) { Host.Error("CL_ParseServerMessage: svc_updatename > MAX_SCOREBOARD"); } cl.scores[i].name = Host.Network.Reader.ReadString(); break; case ProtocolDef.svc_updatefrags: Host.Hud.Changed(); i = Host.Network.Reader.ReadByte(); if (i >= cl.maxclients) { Host.Error("CL_ParseServerMessage: svc_updatefrags > MAX_SCOREBOARD"); } cl.scores[i].frags = Host.Network.Reader.ReadShort(); break; case ProtocolDef.svc_updatecolors: Host.Hud.Changed(); i = Host.Network.Reader.ReadByte(); if (i >= cl.maxclients) { Host.Error("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD"); } cl.scores[i].colors = Host.Network.Reader.ReadByte(); NewTranslation(i); break; case ProtocolDef.svc_particle: Host.RenderContext.Particles.ParseParticleEffect(Host.Client.cl.time, Host.Network.Reader); break; case ProtocolDef.svc_spawnbaseline: i = Host.Network.Reader.ReadShort(); // must use CL_EntityNum() to force cl.num_entities up ParseBaseline(EntityNum(i)); break; case ProtocolDef.svc_spawnstatic: ParseStatic(); break; case ProtocolDef.svc_temp_entity: ParseTempEntity(); break; case ProtocolDef.svc_setpause: { cl.paused = Host.Network.Reader.ReadByte() != 0; if (cl.paused) { Host.CDAudio.Pause(); } else { Host.CDAudio.Resume(); } } break; case ProtocolDef.svc_signonnum: i = Host.Network.Reader.ReadByte(); if (i <= cls.signon) { Host.Error("Received signon {0} when at {1}", i, cls.signon); } cls.signon = i; SignonReply(); break; case ProtocolDef.svc_killedmonster: cl.stats[QStatsDef.STAT_MONSTERS]++; break; case ProtocolDef.svc_foundsecret: cl.stats[QStatsDef.STAT_SECRETS]++; break; case ProtocolDef.svc_updatestat: i = Host.Network.Reader.ReadByte(); if (i < 0 || i >= QStatsDef.MAX_CL_STATS) { Utilities.Error("svc_updatestat: {0} is invalid", i); } cl.stats[i] = Host.Network.Reader.ReadLong(); break; case ProtocolDef.svc_spawnstaticsound: ParseStaticSound(); break; case ProtocolDef.svc_cdtrack: cl.cdtrack = Host.Network.Reader.ReadByte(); cl.looptrack = Host.Network.Reader.ReadByte(); if ((cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1)) { Host.CDAudio.Play(( Byte )cls.forcetrack, true); } else { Host.CDAudio.Play(( Byte )cl.cdtrack, true); } break; case ProtocolDef.svc_intermission: cl.intermission = 1; cl.completed_time = ( Int32 )cl.time; Host.Screen.vid.recalc_refdef = true; // go to full screen break; case ProtocolDef.svc_finale: cl.intermission = 2; cl.completed_time = ( Int32 )cl.time; Host.Screen.vid.recalc_refdef = true; // go to full screen Host.Screen.CenterPrint(Host.Network.Reader.ReadString()); break; case ProtocolDef.svc_cutscene: cl.intermission = 3; cl.completed_time = ( Int32 )cl.time; Host.Screen.vid.recalc_refdef = true; // go to full screen Host.Screen.CenterPrint(Host.Network.Reader.ReadString()); break; case ProtocolDef.svc_sellscreen: Host.Commands.ExecuteString("help", CommandSource.Command); break; } } }
static float _LastMsg; // static float lastmsg from CL_KeepaliveMessage /// <summary> /// CL_ParseServerMessage /// </summary> static void ParseServerMessage() { // // if recording demos, copy the message out // if (_ShowNet.Value == 1) { Con.Print("{0} ", Net.Message.Length); } else if (_ShowNet.Value == 2) { Con.Print("------------------\n"); } Cl.onground = false; // unless the server says otherwise // // parse the message // Net.Reader.Reset(); int i; while (true) { if (Net.Reader.IsBadRead) { Host.Error("CL_ParseServerMessage: Bad server message"); } int cmd = Net.Reader.ReadByte(); if (cmd == -1) { ShowNet("END OF MESSAGE"); return; // end of message } // if the high bit of the command byte is set, it is a fast update if ((cmd & 128) != 0) { ShowNet("fast update"); ParseUpdate(cmd & 127); continue; } ShowNet(_SvcStrings[cmd]); // other commands switch (cmd) { default: Host.Error("CL_ParseServerMessage: Illegible server message\n"); break; case Protocol.svc_nop: break; case Protocol.svc_time: Cl.mtime[1] = Cl.mtime[0]; Cl.mtime[0] = Net.Reader.ReadFloat(); break; case Protocol.svc_clientdata: i = Net.Reader.ReadShort(); ParseClientData(i); break; case Protocol.svc_version: i = Net.Reader.ReadLong(); if (i != Protocol.PROTOCOL_VERSION) { Host.Error("CL_ParseServerMessage: Server is protocol {0} instead of {1}\n", i, Protocol.PROTOCOL_VERSION); } break; case Protocol.svc_disconnect: Host.EndGame("Server disconnected\n"); break; case Protocol.svc_print: Con.Print(Net.Reader.ReadString()); break; case Protocol.svc_centerprint: Scr.CenterPrint(Net.Reader.ReadString()); break; case Protocol.svc_stufftext: Cbuf.AddText(Net.Reader.ReadString()); break; case Protocol.svc_damage: View.ParseDamage(); break; case Protocol.svc_serverinfo: ParseServerInfo(); Scr.vid.recalc_refdef = true; // leave intermission full screen break; case Protocol.svc_setangle: Cl.viewangles.X = Net.Reader.ReadAngle(); Cl.viewangles.Y = Net.Reader.ReadAngle(); Cl.viewangles.Z = Net.Reader.ReadAngle(); break; case Protocol.svc_setview: Cl.viewentity = Net.Reader.ReadShort(); break; case Protocol.svc_lightstyle: i = Net.Reader.ReadByte(); if (i >= QDef.MAX_LIGHTSTYLES) { Sys.Error("svc_lightstyle > MAX_LIGHTSTYLES"); } _LightStyle[i].map = Net.Reader.ReadString(); break; case Protocol.svc_sound: ParseStartSoundPacket(); break; case Protocol.svc_stopsound: i = Net.Reader.ReadShort(); Sound.StopSound(i >> 3, i & 7); break; case Protocol.svc_updatename: Sbar.Changed(); i = Net.Reader.ReadByte(); if (i >= Cl.maxclients) { Host.Error("CL_ParseServerMessage: svc_updatename > MAX_SCOREBOARD"); } Cl.scores[i].name = Net.Reader.ReadString(); break; case Protocol.svc_updatefrags: Sbar.Changed(); i = Net.Reader.ReadByte(); if (i >= Cl.maxclients) { Host.Error("CL_ParseServerMessage: svc_updatefrags > MAX_SCOREBOARD"); } Cl.scores[i].frags = Net.Reader.ReadShort(); break; case Protocol.svc_updatecolors: Sbar.Changed(); i = Net.Reader.ReadByte(); if (i >= Cl.maxclients) { Host.Error("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD"); } Cl.scores[i].colors = Net.Reader.ReadByte(); NewTranslation(i); break; case Protocol.svc_particle: Render.ParseParticleEffect(); break; case Protocol.svc_spawnbaseline: i = Net.Reader.ReadShort(); // must use CL_EntityNum() to force cl.num_entities up ParseBaseline(EntityNum(i)); break; case Protocol.svc_spawnstatic: ParseStatic(); break; case Protocol.svc_temp_entity: ParseTempEntity(); break; case Protocol.svc_setpause: { Cl.paused = Net.Reader.ReadByte() != 0; if (Cl.paused) { CDAudio.Pause(); } else { CDAudio.Resume(); } } break; case Protocol.svc_signonnum: i = Net.Reader.ReadByte(); if (i <= Cls.signon) { Host.Error("Received signon {0} when at {1}", i, Cls.signon); } Cls.signon = i; SignonReply(); break; case Protocol.svc_killedmonster: Cl.stats[QStats.STAT_MONSTERS]++; break; case Protocol.svc_foundsecret: Cl.stats[QStats.STAT_SECRETS]++; break; case Protocol.svc_updatestat: i = Net.Reader.ReadByte(); if (i < 0 || i >= QStats.MAX_CL_STATS) { Sys.Error("svc_updatestat: {0} is invalid", i); } Cl.stats[i] = Net.Reader.ReadLong(); break; case Protocol.svc_spawnstaticsound: ParseStaticSound(); break; case Protocol.svc_cdtrack: Cl.cdtrack = Net.Reader.ReadByte(); Cl.looptrack = Net.Reader.ReadByte(); if ((Cls.demoplayback || Cls.demorecording) && (Cls.forcetrack != -1)) { CDAudio.Play((byte)Cls.forcetrack, true); } else { CDAudio.Play((byte)Cl.cdtrack, true); } break; case Protocol.svc_intermission: Cl.intermission = 1; Cl.completed_time = (int)Cl.time; Scr.vid.recalc_refdef = true; // go to full screen break; case Protocol.svc_finale: Cl.intermission = 2; Cl.completed_time = (int)Cl.time; Scr.vid.recalc_refdef = true; // go to full screen Scr.CenterPrint(Net.Reader.ReadString()); break; case Protocol.svc_cutscene: Cl.intermission = 3; Cl.completed_time = (int)Cl.time; Scr.vid.recalc_refdef = true; // go to full screen Scr.CenterPrint(Net.Reader.ReadString()); break; case Protocol.svc_sellscreen: Cmd.ExecuteString("help", cmd_source_t.src_command); break; } } }
/// <summary> /// CL_KeepaliveMessage /// When the client is taking a long time to load stuff, send keepalive messages /// so the server doesn't disconnect. /// </summary> static void KeepaliveMessage() { if (Server.IsActive) { return; // no need if server is local } if (Cls.demoplayback) { return; } // read messages from server, should just be nops Net.Message.SaveState(ref _MsgState); int ret; do { ret = GetMessage(); switch (ret) { default: Host.Error("CL_KeepaliveMessage: CL_GetMessage failed"); break; case 0: break; // nothing waiting case 1: Host.Error("CL_KeepaliveMessage: received a message"); break; case 2: if (Net.Reader.ReadByte() != Protocol.svc_nop) { Host.Error("CL_KeepaliveMessage: datagram wasn't a nop"); } break; } } while (ret != 0); Net.Message.RestoreState(_MsgState); // check time float time = (float)Sys.GetFloatTime(); if (time - _LastMsg < 5) { return; } _LastMsg = time; // write out a nop Con.Print("--> client to server keepalive\n"); Cls.message.WriteByte(Protocol.clc_nop); Net.SendMessage(Cls.netcon, Cls.message); Cls.message.Clear(); }
/// <summary> /// PR_ExecuteProgram /// </summary> public unsafe static void Execute(int fnum) { if (fnum < 1 || fnum >= _Functions.Length) { if (Progs.GlobalStruct.self != 0) { Print(Server.ProgToEdict(Progs.GlobalStruct.self)); } Host.Error("PR_ExecuteProgram: NULL function"); } dfunction_t f = _Functions[fnum]; int runaway = 100000; Trace = false; // make a stack frame int exitdepth = _Depth; int ofs; int s = EnterFunction(f); edict_t ed; while (true) { s++; // next statement eval_t *a = (eval_t *)Get(_Statements[s].a); eval_t *b = (eval_t *)Get(_Statements[s].b); eval_t *c = (eval_t *)Get(_Statements[s].c); if (--runaway == 0) { RunError("runaway loop error"); } xFunction.profile++; _xStatement = s; if (Trace) { PrintStatement(ref _Statements[s]); } switch ((OP)_Statements[s].op) { case OP.OP_ADD_F: c->_float = a->_float + b->_float; break; case OP.OP_ADD_V: c->vector[0] = a->vector[0] + b->vector[0]; c->vector[1] = a->vector[1] + b->vector[1]; c->vector[2] = a->vector[2] + b->vector[2]; break; case OP.OP_SUB_F: c->_float = a->_float - b->_float; break; case OP.OP_SUB_V: c->vector[0] = a->vector[0] - b->vector[0]; c->vector[1] = a->vector[1] - b->vector[1]; c->vector[2] = a->vector[2] - b->vector[2]; break; case OP.OP_MUL_F: c->_float = a->_float * b->_float; break; case OP.OP_MUL_V: c->_float = a->vector[0] * b->vector[0] + a->vector[1] * b->vector[1] + a->vector[2] * b->vector[2]; break; case OP.OP_MUL_FV: c->vector[0] = a->_float * b->vector[0]; c->vector[1] = a->_float * b->vector[1]; c->vector[2] = a->_float * b->vector[2]; break; case OP.OP_MUL_VF: c->vector[0] = b->_float * a->vector[0]; c->vector[1] = b->_float * a->vector[1]; c->vector[2] = b->_float * a->vector[2]; break; case OP.OP_DIV_F: c->_float = a->_float / b->_float; break; case OP.OP_BITAND: c->_float = (int)a->_float & (int)b->_float; break; case OP.OP_BITOR: c->_float = (int)a->_float | (int)b->_float; break; case OP.OP_GE: c->_float = (a->_float >= b->_float) ? 1 : 0; break; case OP.OP_LE: c->_float = (a->_float <= b->_float) ? 1 : 0; break; case OP.OP_GT: c->_float = (a->_float > b->_float) ? 1 : 0; break; case OP.OP_LT: c->_float = (a->_float < b->_float) ? 1 : 0; break; case OP.OP_AND: c->_float = (a->_float != 0 && b->_float != 0) ? 1 : 0; break; case OP.OP_OR: c->_float = (a->_float != 0 || b->_float != 0) ? 1 : 0; break; case OP.OP_NOT_F: c->_float = (a->_float != 0) ? 0 : 1; break; case OP.OP_NOT_V: c->_float = (a->vector[0] == 0 && a->vector[1] == 0 && a->vector[2] == 0) ? 1 : 0; break; case OP.OP_NOT_S: c->_float = (a->_string == 0 || String.IsNullOrEmpty(GetString(a->_string))) ? 1 : 0; break; case OP.OP_NOT_FNC: c->_float = (a->function == 0) ? 1 : 0; break; case OP.OP_NOT_ENT: c->_float = (Server.ProgToEdict(a->edict) == Server.sv.edicts[0]) ? 1 : 0; break; case OP.OP_EQ_F: c->_float = (a->_float == b->_float) ? 1 : 0; break; case OP.OP_EQ_V: c->_float = ((a->vector[0] == b->vector[0]) && (a->vector[1] == b->vector[1]) && (a->vector[2] == b->vector[2])) ? 1 : 0; break; case OP.OP_EQ_S: c->_float = (GetString(a->_string) == GetString(b->_string)) ? 1 : 0; //!strcmp(pr_strings + a->_string, pr_strings + b->_string); break; case OP.OP_EQ_E: c->_float = (a->_int == b->_int) ? 1 : 0; break; case OP.OP_EQ_FNC: c->_float = (a->function == b->function) ? 1 : 0; break; case OP.OP_NE_F: c->_float = (a->_float != b->_float) ? 1 : 0; break; case OP.OP_NE_V: c->_float = ((a->vector[0] != b->vector[0]) || (a->vector[1] != b->vector[1]) || (a->vector[2] != b->vector[2])) ? 1 : 0; break; case OP.OP_NE_S: c->_float = (GetString(a->_string) != GetString(b->_string)) ? 1 : 0; //strcmp(pr_strings + a->_string, pr_strings + b->_string); break; case OP.OP_NE_E: c->_float = (a->_int != b->_int) ? 1 : 0; break; case OP.OP_NE_FNC: c->_float = (a->function != b->function) ? 1 : 0; break; case OP.OP_STORE_F: case OP.OP_STORE_ENT: case OP.OP_STORE_FLD: // integers case OP.OP_STORE_S: case OP.OP_STORE_FNC: // pointers b->_int = a->_int; break; case OP.OP_STORE_V: b->vector[0] = a->vector[0]; b->vector[1] = a->vector[1]; b->vector[2] = a->vector[2]; break; case OP.OP_STOREP_F: case OP.OP_STOREP_ENT: case OP.OP_STOREP_FLD: // integers case OP.OP_STOREP_S: case OP.OP_STOREP_FNC: // pointers ed = EdictFromAddr(b->_int, out ofs); ed.StoreInt(ofs, a); break; case OP.OP_STOREP_V: ed = EdictFromAddr(b->_int, out ofs); ed.StoreVector(ofs, a); break; case OP.OP_ADDRESS: ed = Server.ProgToEdict(a->edict); if (ed == Server.sv.edicts[0] && Server.IsActive) { RunError("assignment to world entity"); } c->_int = MakeAddr(a->edict, b->_int); break; case OP.OP_LOAD_F: case OP.OP_LOAD_FLD: case OP.OP_LOAD_ENT: case OP.OP_LOAD_S: case OP.OP_LOAD_FNC: ed = Server.ProgToEdict(a->edict); ed.LoadInt(b->_int, c); break; case OP.OP_LOAD_V: ed = Server.ProgToEdict(a->edict); ed.LoadVector(b->_int, c); break; case OP.OP_IFNOT: if (a->_int == 0) { s += _Statements[s].b - 1; // offset the s++ } break; case OP.OP_IF: if (a->_int != 0) { s += _Statements[s].b - 1; // offset the s++ } break; case OP.OP_GOTO: s += _Statements[s].a - 1; // offset the s++ break; case OP.OP_CALL0: case OP.OP_CALL1: case OP.OP_CALL2: case OP.OP_CALL3: case OP.OP_CALL4: case OP.OP_CALL5: case OP.OP_CALL6: case OP.OP_CALL7: case OP.OP_CALL8: _Argc = _Statements[s].op - (int)OP.OP_CALL0; if (a->function == 0) { RunError("NULL function"); } dfunction_t newf = _Functions[a->function]; if (newf.first_statement < 0) { // negative statements are built in functions int i = -newf.first_statement; if (i >= QBuiltins.Count) { RunError("Bad builtin call number"); } QBuiltins.Execute(i); break; } s = EnterFunction(newf); break; case OP.OP_DONE: case OP.OP_RETURN: float *ptr = (float *)_GlobalStructAddr; int sta = _Statements[s].a; ptr[OFS.OFS_RETURN + 0] = *(float *)Get(sta); ptr[OFS.OFS_RETURN + 1] = *(float *)Get(sta + 1); ptr[OFS.OFS_RETURN + 2] = *(float *)Get(sta + 2); s = LeaveFunction(); if (_Depth == exitdepth) { return; // all done } break; case OP.OP_STATE: ed = Server.ProgToEdict(Progs.GlobalStruct.self); #if FPS_20 ed->v.nextthink = pr_global_struct->time + 0.05; #else ed.v.nextthink = Progs.GlobalStruct.time + 0.1f; #endif if (a->_float != ed.v.frame) { ed.v.frame = a->_float; } ed.v.think = b->function; break; default: RunError("Bad opcode %i", _Statements[s].op); break; } } }