private void ReadPacket(Q3HuffmanStream stream) { List <string> cmdLog = new List <string> (); PacketKind pktKind = stream.BeginRead(); this.reliableAcknowledge = stream.ReadInt32(); ServerCommandType cmd; while (ServerCommandType.EOF != (cmd = ( ServerCommandType )stream.ReadByte())) { switch (cmd) { case ServerCommandType.Nop: cmdLog.Add("Nop"); break; case ServerCommandType.ServerCommand: this.ParseCommandString(stream); cmdLog.Add("ServerCommand"); break; case ServerCommandType.GameState: this.ParseGamestate(stream); cmdLog.Add("GameState"); break; case ServerCommandType.Snapshot: this.ParseSnapshot(stream); cmdLog.Add("Snapshot"); break; case ServerCommandType.Download: // We never download ;) return; default: // Unknown command return; } } stream.EndRead(); }
private void ParseGamestate(Q3HuffmanStream stream) { this.gameState.Clear(); this.incomingCommandSequence = stream.ReadInt32(); EntityState nullstate = new EntityState(); ServerCommandType cmd; entityBaselinesEvent.WaitOne(); while (ServerCommandType.EOF != (cmd = ( ServerCommandType )stream.ReadByte())) { switch (cmd) { case ServerCommandType.ConfigString: int i = stream.ReadInt16(); gameState [i] = stream.ReadString(); break; case ServerCommandType.BaseLine: int newnum = stream.ReadBits(10); ReadDeltaEntity(stream, nullstate, ref entityBaselines [newnum], newnum); break; default: // Unknown command break; } } entityBaselinesEvent.Set(); this.clientNum = stream.ReadInt32(); this.checksumFeed = stream.ReadInt32(); SystemInfoChanged(); this.connState = ConnectionState.Primed; //SendPureChecksums (); }
private void ReadDeltaPlayerstate(Q3HuffmanStream stream, PlayerState from, ref PlayerState to) { int i; if (from == null) { from = new PlayerState(); } from.CopyTo(to); int lc = stream.ReadByte(); NetField field; int trunc; for (i = 0, field = PlayerState.fields [i]; i < lc; i++) { field = PlayerState.fields [i]; if (stream.ReadBits(1) == 0) { // no change KeyValueCoder.TrySetFieldValue(to, field.name, KeyValueCoder.TryGetFieldValue(from, field.name)); } else { if (field.bits == 0) { // float if (stream.ReadBits(1) == 0) { // integral float trunc = stream.ReadBits(NetField.FLOAT_INT_BITS); // bias to allow equal parts positive and negative trunc -= NetField.FLOAT_INT_BIAS; KeyValueCoder.TrySetFieldValue(to, field.name, trunc); } else { // full floating point value // FIXIT: wrong conversion from 32 bits to floating point value KeyValueCoder.TrySetFieldValue(to, field.name, stream.ReadInt32()); } } else { // integer KeyValueCoder.TrySetFieldValue(to, field.name, stream.ReadBits(( int )field.bits)); } } } for (i = lc, field = PlayerState.fields [lc]; i < PlayerState.fields.Length; i++) { field = PlayerState.fields [i]; // no change KeyValueCoder.TrySetFieldValue(to, field.name, KeyValueCoder.TryGetFieldValue(from, field.name)); } short bits; // read the arrays if (0 != stream.ReadBits(1)) { // parse stats if (0 != stream.ReadBits(1)) { bits = stream.ReadInt16(); for (i = 0; i < 16; i++) { if (0 != (bits & (1 << i))) { to.stats [i] = stream.ReadInt16(); } } } // parse persistant stats if (0 != stream.ReadBits(1)) { bits = stream.ReadInt16(); for (i = 0; i < 16; i++) { if (0 != (bits & (1 << i))) { to.persistant [i] = stream.ReadInt16(); } } } // parse ammo if (0 != stream.ReadBits(1)) { bits = stream.ReadInt16(); for (i = 0; i < 16; i++) { if (0 != (bits & (1 << i))) { to.ammo [i] = stream.ReadInt16(); } } } // parse powerups if (0 != stream.ReadBits(1)) { bits = stream.ReadInt16(); for (i = 0; i < 16; i++) { if (0 != (bits & (1 << i))) { to.powerups [i] = stream.ReadInt32(); } } } } }
private void ParseSnapshot(Q3HuffmanStream stream) { Snapshot old; Snapshot newSnap = new Snapshot(); int deltaNum; newSnap.serverCommandNum = this.incomingCommandSequence; newSnap.serverTime = stream.ReadInt32(); newSnap.messageNum = this.incomingSequence; if (0 == (deltaNum = stream.ReadByte())) { newSnap.deltaNum = -1; } else { newSnap.deltaNum = newSnap.messageNum - deltaNum; } newSnap.snapFlags = stream.ReadByte(); // If the frame is delta compressed from data that we // no longer have available, we must suck up the rest of // the frame, but not use it, then ask for a non-compressed // message if (newSnap.deltaNum <= 0) { newSnap.valid = true; // uncompressed frame old = null; //clc.demowaiting = false; // we can start recording now } else { old = this.snapshots [newSnap.deltaNum & PACKET_MASK]; if (!old.valid) { // should never happen // "Delta from invalid frame (not supposed to happen!)" } else if (old.messageNum != newSnap.deltaNum) { // The frame that the server did the delta from // is too old, so we can't reconstruct it properly. // "Delta frame too old." } else if (parseEntitiesNum - old.parseEntitiesNum > MAX_PARSE_ENTITIES - 128) { // "Delta parseEntitiesNum too old." } else { newSnap.valid = true; // valid delta parse } } // read areamask int len = stream.ReadByte(); stream.Read(newSnap.areamask, 0, len); // read playerinfo if (old != null) { ReadDeltaPlayerstate(stream, old.ps, ref newSnap.ps); } else { ReadDeltaPlayerstate(stream, null, ref newSnap.ps); } // read packet entities ParsePacketEntities(stream, old, newSnap); // if not valid, dump the entire thing now that it has // been properly read if (!newSnap.valid) { return; } // clear the valid flags of any snapshots between the last // received and this one, so if there was a dropped packet // it won't look like something valid to delta from next // time we wrap around in the buffer int oldMessageNum = this.snap.messageNum + 1; if (newSnap.messageNum - oldMessageNum >= PACKET_BACKUP) { oldMessageNum = newSnap.messageNum - (PACKET_BACKUP - 1); } for ( ; oldMessageNum < newSnap.messageNum; oldMessageNum++) { this.snapshots [oldMessageNum & PACKET_MASK].valid = false; } // copy to the current good spot this.snap = newSnap; this.snap.ping = 999; // calculate ping time for (int i = 0; i < PACKET_BACKUP; i++) { int packetNum = (this.outgoingSequence - 1 - i) & PACKET_MASK; if (this.snap.ps.commandTime >= this.outPackets [packetNum].serverTime) { this.snap.ping = ( int )(DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - this.outPackets[packetNum].realtime; break; } } // save the frame off in the backup array for later delta comparisons this.snapshots [this.snap.messageNum & PACKET_MASK] = this.snap; this.newSnapshots = true; }
private void ReadDeltaEntity(Q3HuffmanStream stream, EntityState from, ref EntityState to, int number) { // check for a remove if (stream.ReadBits(1) == 1) { new EntityState().CopyTo(to); to.number = MAX_GENTITIES - 1; return; } // check for no delta if (stream.ReadBits(1) == 0) { from.CopyTo(to); to.number = number; return; } int lc = stream.ReadByte(); to.number = number; int i; NetField field; int trunc; for (i = 0, field = EntityState.fields [i]; i < lc && i < EntityState.fields.Length; i++) { field = EntityState.fields [i]; if (stream.ReadBits(1) == 0) { // no change KeyValueCoder.TrySetFieldValue(to, field.name, KeyValueCoder.TryGetFieldValue(from, field.name)); } else { if (field.bits == 0) { // float if (stream.ReadBits(1) == 0) { KeyValueCoder.TrySetFieldValue(to, field.name, 0); } else { if (stream.ReadBits(1) == 0) { // integral float trunc = stream.ReadBits(NetField.FLOAT_INT_BITS); // bias to allow equal parts positive and negative trunc -= NetField.FLOAT_INT_BIAS; KeyValueCoder.TrySetFieldValue(to, field.name, trunc); } else { // full floating point value // FIXIT: wrong conversion from 32 bits to floating point value KeyValueCoder.TrySetFieldValue(to, field.name, stream.ReadInt32()); } } } else { if (stream.ReadBits(1) == 0) { KeyValueCoder.TrySetFieldValue(to, field.name, 0); } else { // integer KeyValueCoder.TrySetFieldValue(to, field.name, stream.ReadBits(( int )field.bits)); } } } } for (i = lc; i < EntityState.fields.Length; i++) { field = EntityState.fields [i]; // no change KeyValueCoder.TrySetFieldValue(to, field.name, KeyValueCoder.TryGetFieldValue(from, field.name)); } }