Exemple #1
0
        static readonly int SNAPFLAG_SERVERCOUNT = 4; // toggled every map_restart so transitions can be detected

        #endregion Fields

        #region Methods

        void AddEntitiesVisibleFromPoint(Vector3 origin, ref clientSnapshot_t frame, List<int> snapshotEntitiesNumbers, bool portal)
        {
            // during an error shutdown message we may need to transmit
            // the shutdown message after the server has shutdown, so
            // specfically check for it
            if ((int)sv.state == 0)
                return;

            int leafnum = ClipMap.Instance.PointLeafnum(origin);
            int clientarea = ClipMap.Instance.LeafArea(leafnum);
            int clientcluster = ClipMap.Instance.LeafCluster(leafnum);

            // calculate the visible areas
            frame.areabytes = ClipMap.Instance.WriteAreaBits(ref frame.areabits, clientarea);
            bool[] clientpvs = ClipMap.Instance.ClusterPVS(clientcluster);

            sharedEntity ent;
            for (int i = 0; i < sv.num_entities; i++)
            {
                ent = sv.gentities[i];

                // never send entities that aren't linked in
                if (!ent.r.linked)
                    continue;

                if (ent.s.number != i)
                {
                    Common.Instance.WriteLine("FIXING ENT.S.NUMBER!!!");
                    ent.s.number = i;
                }

                // entities can be flagged to explicitly not be sent to the client
                if ((ent.r.svFlags & Common.svFlags.NOCLIENT) == Common.svFlags.NOCLIENT)
                    continue;

                // entities can be flagged to be sent to only one client
                if ((ent.r.svFlags & Common.svFlags.SINGLECLIENT) == Common.svFlags.SINGLECLIENT)
                    if (ent.r.singleClient != frame.ps.clientNum)
                        continue;

                // entities can be flagged to be sent to everyone but one client
                if ((ent.r.svFlags & Common.svFlags.NOTSINGLECLIENT) == Common.svFlags.NOTSINGLECLIENT)
                    if (ent.r.singleClient == frame.ps.clientNum)
                        continue;

                // entities can be flagged to be sent to a given mask of clients
                if ((ent.r.svFlags & Common.svFlags.CLIENTMASK) == Common.svFlags.CLIENTMASK)
                {
                    if (frame.ps.clientNum >= 32)
                        Common.Instance.Error("CLIENTMASK: clientNum > 32");
                    if ((~ent.r.singleClient & (1 << frame.ps.clientNum)) == (1 << frame.ps.clientNum))
                        continue;
                }

                svEntity_t svEnt = Game.Instance.SvEntityForGentity(ent);

                // don't double add an entity through portals
                if (svEnt.snapshotCounter == sv.snapshotCounter)
                    continue;

                // broadcast entities are always sent
                if ((ent.r.svFlags & Common.svFlags.BROADCAST) == Common.svFlags.BROADCAST)
                {
                    AddEntToSnapshot(svEnt, ent, snapshotEntitiesNumbers);
                    continue;
                }

                //// ignore if not touching a PV leaf
                //// check area
                //if (!ClipMap.Instance.AreasConnected(clientarea, svEnt.areanum))
                //{
                //    // doors can legally straddle two areas, so
                //    // we may need to check another one
                //    if (!ClipMap.Instance.AreasConnected(clientarea, svEnt.areanum2))
                //        continue;   // blocked by a door
                //}

                if (svEnt.numClusters <= 0)
                    continue;
                int l;
                int j;
                for (j = 0; j < svEnt.numClusters; j++)
                {
                    l = svEnt.clusternums[j];
                    if (clientpvs != null && clientpvs[l])
                        break;
                }

                // not visible
                if (j == svEnt.numClusters)
                    continue;

                // add it
                AddEntToSnapshot(svEnt, ent, snapshotEntitiesNumbers);

                // if its a portal entity, add everything visible from its camera position
                if ((ent.r.svFlags & Common.svFlags.PORTAL) == Common.svFlags.PORTAL)
                {
                    if (ent.s.generic1 > 0)
                    {
                        Vector3 dir = ent.s.origin - origin;
                        if (dir.LengthSquared() > (float)ent.s.generic1 * ent.s.generic1)
                            continue;
                    }
                    AddEntitiesVisibleFromPoint(ent.s.origin2, ref frame, snapshotEntitiesNumbers, true);
                }

            }
        }
Exemple #2
0
        /*
        =============
        SV_EmitPacketEntities

        Writes a delta update of an entityState_t list to the message.
        =============
        */
        void EmitPacketEntities(clientSnapshot_t from, clientSnapshot_t to, NetBuffer msg)
        {
            int fromnumentities = 0;

            if (from != null)
                fromnumentities = from.num_entities;

            Common.entityState_t oldent = null, newent = null;
            int oldindex = 0, newindex = 0;
            int newnum, oldnum;
            while (newindex < to.num_entities || oldindex < fromnumentities)
            {
                if (newindex >= to.num_entities)
                    newnum = 9999;
                else
                {
                    newent = snapshotEntities[(to.first_entity + newindex) % numSnapshotEntities];
                    newnum = newent.number;
                }

                if (oldindex >= fromnumentities)
                    oldnum = 9999;
                else
                {
                    oldent = snapshotEntities[(from.first_entity + oldindex) % numSnapshotEntities];
                    oldnum = oldent.number;
                }

                if (newnum == oldnum)
                {
                    // delta update from old position
                    // because the force parm is qfalse, this will not result
                    // in any bytes being emited if the entity has not changed at all
                    Net.Instance.MSG_WriteDeltaEntity(msg, ref oldent, ref newent, false);
                    oldindex++;
                    newindex++;
                    continue;
                }

                if (newnum < oldnum)
                {
                    // this is a new entity, send it from the baseline
                    Net.Instance.MSG_WriteDeltaEntity(msg, ref sv.svEntities[newnum].baseline, ref newent, true);
                    newindex++;
                    continue;
                }

                if (newnum > oldnum)
                {
                    // the old entity isn't present in the new message
                    Common.entityState_t nullEnt = null;
                    Net.Instance.MSG_WriteDeltaEntity(msg, ref oldent, ref nullEnt, true);
                    oldindex++;
                    continue;
                }
            }

            msg.Write(1023);    // end of packetentities
        }
Exemple #3
0
            public string userinfo; // 1024 name, etc

            #endregion Fields

            #region Constructors

            public client_t()
            {
                for (int i = 0; i < 32; i++)
                {
                    frames[i] = new clientSnapshot_t();
                }
            }