Example #1
0
 public clientActive()
 {
     gamestate = new gameState_t();
     gamestate.data = new Dictionary<int, string>();
     for (int i = 0; i < parseEntities.Length; i++)
     {
         parseEntities[i] = new Common.entityState_t();
     }
     for (int i = 0; i < entityBaselines.Length; i++)
     {
         entityBaselines[i] = new Common.entityState_t();
     }
     for (int i = 0; i < snapshots.Length; i++)
     {
         snapshots[i] = new clSnapshot_t();
     }
 }
Example #2
0
        public Common.entityState_t s; // communicated by server to clients

        #endregion Fields

        #region Constructors

        public sharedEntity()
        {
            s = new Common.entityState_t();
            r = new Common.entityShared_t();
            r.s = s;
        }
Example #3
0
        void ParseGameState(NetBuffer msg)
        {
            clc.connectPacketCount = 0;
            // wipe local client state
            ClearState();
            // a gamestate always marks a server command sequence
            clc.serverCommandSequence = msg.ReadInt32();
            // parse all the configstrings and baselines
            while (true)
            {
                int cmd = msg.ReadByte();

                if (cmd == (int)svc_ops_e.svc_EOF)
                    break;

                if (cmd == (int)svc_ops_e.svc_configstring)
                {
                    int index = msg.ReadInt16();
                    string s = msg.ReadString();
                    cl.gamestate.data.Add(index, s);
                }
                else if (cmd == (int)svc_ops_e.svc_baseline)
                {
                    int newnum = msg.ReadInt32();
                    if (newnum < 0 || newnum >= 1024)
                    {
                        Common.Instance.Error("ParseGameState: Baseline number out of range: " + newnum);
                    }
                    Common.entityState_t nullstate = new Common.entityState_t();
                    Net.Instance.MSG_ReadDeltaEntity(msg, ref nullstate, ref cl.entityBaselines[newnum], newnum);
                }
                else
                {
                    Common.Instance.Error("ParseGameState: bad command byte");
                }
            }

            clc.clientNum = msg.ReadInt32();

            // parse useful values out of CS_SERVERINFO
            //ParseServerInfo();

            // parse serverId and other cvars
            SystemInfoChanged();

            InitDownloads();
        }
Example #4
0
        /*
        =============
        SV_BuildClientSnapshot

        Decides which entities are going to be visible to the client, and
        copies off the playerstate and areabits.

        This properly handles multiple recursive portals, but the render
        currently doesn't.

        For viewing through other player's eyes, clent can be something other than client->gentity
        =============
        */
        void BuildClientSnapshot(client_t client, int index)
        {
            List<int> snapshotEntityNumbers = new List<int>();
            // bump the counter used to prevent double adding
            sv.snapshotCounter++;

            // this is the frame we are creating
            clientSnapshot_t frame = client.frames[client.netchan.outgoingSequence & 31];

            // clear everything in this snapshot
            frame.num_entities = 0;
            frame.areabits = new byte[32];

            sharedEntity clent = client.gentity;
            if (clent == null || client.state == clientState_t.CS_ZOMBIE)
            {
                return;
            }

            // grab the current playerState_t
            Common.PlayerState ps = GameClientNum(index);

            //frame.ps = ps;
            frame.ps = ps.Clone();

            // never send client's own entity, because it can
            // be regenerated from the playerstate
            int clientnum = frame.ps.clientNum;
            if (clientnum < 0 || clientnum >= 1024)
            {
                Common.Instance.Error("bad gEnt");
            }

            svEntity_t svEnt = sv.svEntities[clientnum];
            svEnt.snapshotCounter = sv.snapshotCounter;

            // find the client's viewpoint
            Vector3 org = ps.origin;
            org[2] += ps.viewheight;

            // add all the entities directly visible to the eye, which
            // may include portal entities that merge other viewpoints
            AddEntitiesVisibleFromPoint(org, ref frame, snapshotEntityNumbers, false);

            // if there were portals visible, there may be out of order entities
            // in the list which will need to be resorted for the delta compression
            // to work correctly.  This also catches the error condition
            // of an entity being included twice.
            snapshotEntityNumbers.Sort((a, b) => { return a.CompareTo(b); });

            // now that all viewpoint's areabits have been OR'd together, invert
            // all of them to make it a mask vector, which is what the renderer wants
            for (int i = 0; i < 8; i++)
            {
                frame.areabits[i] = (byte)(frame.areabits[i] ^ -1);
            }

            // copy the entity states out
            frame.num_entities = 0;
            frame.first_entity = nextSnapshotEntities;
            for (int i = 0; i < snapshotEntityNumbers.Count; i++)
            {

                sharedEntity ent = sv.gentities[snapshotEntityNumbers[i]];
                snapshotEntities[nextSnapshotEntities++ % numSnapshotEntities] = new Common.entityState_t() { angles = ent.s.angles, angles2 = ent.s.angles2, apos = ent.s.apos, clientNum = ent.s.clientNum, eFlags = ent.s.eFlags, eType = ent.s.eType
                , frame = ent.s.frame, groundEntityNum = ent.s.groundEntityNum, number = ent.s.number, pos = ent.s.pos, solid = ent.s.solid, origin = ent.s.origin, otherEntityNum = ent.s.otherEntityNum, time = ent.s.time, modelindex = ent.s.modelindex};
                //Common.Instance.WriteLine("Sending ent {0} to client {1}", snapshotEntityNumbers[i], index);
                frame.num_entities++;
            }
        }
Example #5
0
        /*
        ==================
        MSG_ReadDeltaEntity

        The entity number has already been read from the message, which
        is how the from state is identified.

        If the delta removes the entity, entityState_t->number will be set to MAX_GENTITIES-1

        Can go from either a baseline or a previous packet_entity
        ==================
        */
        public void MSG_ReadDeltaEntity(NetBuffer msg, ref Common.entityState_t from, ref Common.entityState_t to, int number)
        {
            int startBit = msg.Position-32;
            if (number < 0 || number >= 1024)
            {
                Common.Instance.Error("ReadDeltaEntity: number < 0 || number >= 1024");
            }

            // Check for remove
            if (msg.ReadBoolean())
            {
                to = new Common.entityState_t();
                to.number = 1023;
                Common.Instance.WriteLine("Removed entity: {0}", number);
                return;
            }

            // Check for no delta
            if (!msg.ReadBoolean())
            {
                to = from;
                to.number = number;
                return;
            }

            to.number = number;
            int dataStart = msg.Position;
            to.eType = msg.ReadBoolean() ? msg.ReadInt32() : from.eType;
            to.eFlags = msg.ReadBoolean() ? (Common.EntityFlags)msg.ReadInt32() : from.eFlags;
            int middle = msg.Position;
            to.pos.trBase.X = msg.ReadBoolean() ? msg.ReadFloat() : from.pos.trBase.X;
            to.pos.trBase.Y = msg.ReadBoolean() ? msg.ReadFloat() : from.pos.trBase.Y;
            to.pos.trBase.Z = msg.ReadBoolean() ? msg.ReadFloat() : from.pos.trBase.Z;
            to.pos.trDelta.X = msg.ReadBoolean() ? msg.ReadFloat() : from.pos.trDelta.X;
            to.pos.trDelta.Y = msg.ReadBoolean() ? msg.ReadFloat() : from.pos.trDelta.Y;
            to.pos.trDelta.Z = msg.ReadBoolean() ? msg.ReadFloat() : from.pos.trDelta.Z;
            to.pos.trDuration = msg.ReadBoolean() ? msg.ReadInt32() : from.pos.trDuration;
            to.pos.trTime = msg.ReadBoolean() ? msg.ReadInt32() : from.pos.trTime;
            to.pos.trType = msg.ReadBoolean() ? (Common.trType_t)msg.ReadInt32() : from.pos.trType;

            to.apos.trBase.X = msg.ReadBoolean() ? msg.ReadFloat() : from.apos.trBase.X;
            to.apos.trBase.Y = msg.ReadBoolean() ? msg.ReadFloat() : from.apos.trBase.Y;
            to.apos.trBase.Z = msg.ReadBoolean() ? msg.ReadFloat() : from.apos.trBase.Z;
            to.apos.trDelta.X = msg.ReadBoolean() ? msg.ReadFloat() : from.apos.trDelta.X;
            to.apos.trDelta.Y = msg.ReadBoolean() ? msg.ReadFloat() : from.apos.trDelta.Y;
            to.apos.trDelta.Z = msg.ReadBoolean() ? msg.ReadFloat() : from.apos.trDelta.Z;
            to.apos.trDuration = msg.ReadBoolean() ? msg.ReadInt32() : from.apos.trDuration;
            to.apos.trTime = msg.ReadBoolean() ? msg.ReadInt32() : from.apos.trTime;
            to.apos.trType = msg.ReadBoolean() ? (Common.trType_t)msg.ReadInt32() : from.apos.trType;

            to.time = msg.ReadBoolean() ? msg.ReadInt32() : from.time;
            to.time2 = msg.ReadBoolean() ? msg.ReadInt32() : from.time2;

            to.origin.X = msg.ReadBoolean() ? msg.ReadFloat() : from.origin.X;
            to.origin.Y = msg.ReadBoolean() ? msg.ReadFloat() : from.origin.Y;
            to.origin.Z = msg.ReadBoolean() ? msg.ReadFloat() : from.origin.Z;
            to.origin2.X = msg.ReadBoolean() ? msg.ReadFloat() : from.origin2.X;
            to.origin2.Y = msg.ReadBoolean() ? msg.ReadFloat() : from.origin2.Y;
            to.origin2.Z = msg.ReadBoolean() ? msg.ReadFloat() : from.origin2.Z;

            to.angles.X = msg.ReadBoolean() ? msg.ReadFloat() : from.angles.X;
            to.angles.Y = msg.ReadBoolean() ? msg.ReadFloat() : from.angles.Y;
            to.angles.Z = msg.ReadBoolean() ? msg.ReadFloat() : from.angles.Z;
            to.angles2.X = msg.ReadBoolean() ? msg.ReadFloat() : from.angles2.X;
            to.angles2.Y = msg.ReadBoolean() ? msg.ReadFloat() : from.angles2.Y;
            to.angles2.Z = msg.ReadBoolean() ? msg.ReadFloat() : from.angles2.Z;

            to.otherEntityNum = msg.ReadBoolean() ? msg.ReadInt32() : from.otherEntityNum;
            to.otherEntityNum2 = msg.ReadBoolean() ? msg.ReadInt32() : from.otherEntityNum2;
            to.groundEntityNum = msg.ReadBoolean() ? msg.ReadInt32() : from.groundEntityNum;

            to.modelindex = msg.ReadBoolean() ? msg.ReadInt32() : from.modelindex;
            to.clientNum = msg.ReadBoolean() ? msg.ReadInt32() : from.clientNum;
            to.frame = msg.ReadBoolean() ? msg.ReadInt32() : from.frame;
            to.solid = msg.ReadBoolean() ? msg.ReadInt32() : from.solid;
            to.generic1 = msg.ReadBoolean() ? msg.ReadInt32() : from.generic1;
            int lenghtBits = msg.ReadInt32();

            dataStart = msg.Position - dataStart;
            lenghtBits -= dataStart;
            for (int i = 0; i < lenghtBits; i++)
            {
                msg.ReadBoolean();
            }
            middle = msg.Position - middle;

            //Common.Instance.WriteLine("MSG_ReadDeltaEntity: Read {0} bits", msg.Position - startBit);
        }
Example #6
0
        /*
        ================
        SV_SendClientGameState

        Sends the first message from the server to a connected client.
        This will be sent on the initial connection and upon each new map load.

        It will be resent if the client acknowledges a later message but has
        the wrong gamestate.
        ================
        */
        void SendClientGameState(client_t cl)
        {
            Common.Instance.WriteLine("SendClientGameState for {0}", cl.name);
            Common.Instance.WriteLine("Going from CONNECTED to PRIMED for {0}", cl.name);
            cl.state = clientState_t.CS_PRIMED;
            cl.pureAuthentic = 0;
            cl.gotCP = false;

            // when we receive the first packet from the client, we will
            // notice that it is from a different serverid and that the
            // gamestate message was not just sent, forcing a retransmit
            cl.gamestateMessageNum = cl.netchan.outgoingSequence;

            NetBuffer msg = new NetBuffer();
            // NOTE, MRE: all server->client messages now acknowledge
            // let the client know which reliable clientCommands we have received
            msg.Write(cl.lastClientCommand);

            // send any server commands waiting to be sent first.
            // we have to do this cause we send the client->reliableSequence
            // with a gamestate and it sets the clc.serverCommandSequence at
            // the client side
            UpdateServerCommandsToClient(cl, msg);

            // send the gamestate
            msg.Write((byte)svc_ops_e.svc_gamestate);
            msg.Write(cl.reliableSequence);

            // write the configstrings
            foreach (int i in sv.configstrings.Keys)
            {
                msg.Write((byte)svc_ops_e.svc_configstring);
                msg.Write((short)i);
                msg.Write(sv.configstrings[i]);
            }

            // write the baselines
            Common.entityState_t nullstate = new Common.entityState_t();
            for (int i = 0; i < 1024; i++)
            {
                Common.entityState_t bases = sv.svEntities[i].baseline;
                if (bases == null || bases.number <= 0)
                    continue;

                msg.Write((byte)svc_ops_e.svc_baseline);
                Net.Instance.MSG_WriteDeltaEntity(msg, ref nullstate, ref bases, true);
            }

            msg.Write((byte)svc_ops_e.svc_EOF);
            msg.Write(cl.id);
            SendMessageToClient(msg, cl);
        }