示例#1
0
        public static void SV_BuildClientFrame(client_t client)
        {
            Int32 e, i;

            Single[]       org = new Single[] { 0, 0, 0 };
            edict_t        ent;
            edict_t        clent;
            client_frame_t frame;
            entity_state_t state;
            Int32          l;
            Int32          clientarea, clientcluster;
            Int32          leafnum;
            Int32          c_fullsend;

            Byte[] clientphs;
            Byte[] bitvector;
            clent = client.edict;
            if (clent.client == null)
            {
                return;
            }
            frame          = client.frames[SV_INIT.sv.framenum & Defines.UPDATE_MASK];
            frame.senttime = SV_INIT.svs.realtime;
            for (i = 0; i < 3; i++)
            {
                org[i] = clent.client.ps.pmove.origin[i] * 0.125F + clent.client.ps.viewoffset[i];
            }
            leafnum         = CM.CM_PointLeafnum(org);
            clientarea      = CM.CM_LeafArea(leafnum);
            clientcluster   = CM.CM_LeafCluster(leafnum);
            frame.areabytes = CM.CM_WriteAreaBits(frame.areabits, clientarea);
            frame.ps.Set(clent.client.ps);
            SV_FatPVS(org);
            clientphs          = CM.CM_ClusterPHS(clientcluster);
            frame.num_entities = 0;
            frame.first_entity = SV_INIT.svs.next_client_entities;
            c_fullsend         = 0;
            for (e = 1; e < GameBase.num_edicts; e++)
            {
                ent = GameBase.g_edicts[e];
                if ((ent.svflags & Defines.SVF_NOCLIENT) != 0)
                {
                    continue;
                }
                if (0 == ent.s.modelindex && 0 == ent.s.effects && 0 == ent.s.sound && 0 == ent.s.event_renamed)
                {
                    continue;
                }
                if (ent != clent)
                {
                    if (!CM.CM_AreasConnected(clientarea, ent.areanum))
                    {
                        if (0 == ent.areanum2 || !CM.CM_AreasConnected(clientarea, ent.areanum2))
                        {
                            continue;
                        }
                    }

                    if ((ent.s.renderfx & Defines.RF_BEAM) != 0)
                    {
                        l = ent.clusternums[0];
                        if (0 == (clientphs[l >> 3] & (1 << (l & 7))))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (ent.s.sound == 0)
                        {
                            bitvector = SV_ENTS.fatpvs;
                        }
                        else
                        {
                            bitvector = SV_ENTS.fatpvs;
                        }
                        if (ent.num_clusters == -1)
                        {
                            if (!CM.CM_HeadnodeVisible(ent.headnode, bitvector))
                            {
                                continue;
                            }
                            c_fullsend++;
                        }
                        else
                        {
                            for (i = 0; i < ent.num_clusters; i++)
                            {
                                l = ent.clusternums[i];
                                if ((bitvector[l >> 3] & (1 << (l & 7))) != 0)
                                {
                                    break;
                                }
                            }

                            if (i == ent.num_clusters)
                            {
                                continue;
                            }
                        }

                        if (ent.s.modelindex == 0)
                        {
                            Single[] delta = new Single[] { 0, 0, 0 };
                            Single   len;
                            Math3D.VectorSubtract(org, ent.s.origin, delta);
                            len = Math3D.VectorLength(delta);
                            if (len > 400)
                            {
                                continue;
                            }
                        }
                    }
                }

                var ix = SV_INIT.svs.next_client_entities % SV_INIT.svs.num_client_entities;
                state = SV_INIT.svs.client_entities[ix];
                if (ent.s.number != e)
                {
                    Com.DPrintf("FIXING ENT.S.NUMBER!!!\\n");
                    ent.s.number = e;
                }

                SV_INIT.svs.client_entities[ix].Set(ent.s);
                if (ent.owner == client.edict)
                {
                    state.solid = 0;
                }
                SV_INIT.svs.next_client_entities++;
                frame.num_entities++;
            }
        }
示例#2
0
        /**
         * Decides which entities are going to be visible to the client, and copies
         * off the playerstat and areabits.
         */
        public static void SV_BuildClientFrame(client_t client)
        {
            int e, i;

            float[]        org = { 0, 0, 0 };
            edict_t        ent;
            edict_t        clent;
            client_frame_t frame;
            entity_state_t state;
            int            l;
            int            clientarea, clientcluster;
            int            leafnum;
            int            c_fullsend;

            byte[] clientphs;
            byte[] bitvector;

            clent = client.edict;

            if (clent.client == null)
            {
                return;                 // not in game yet
            }
            // this is the frame we are creating
            frame = client.frames[SV_INIT.sv.framenum & Defines.UPDATE_MASK];

            frame.senttime = SV_INIT.svs.realtime;             // save it for ping calc later

            // find the client's PVS
            for (i = 0; i < 3; i++)
            {
                org[i] = clent.client.ps.pmove.origin[i] * 0.125f + clent.client.ps.viewoffset[i];
            }

            leafnum       = CM.CM_PointLeafnum(org);
            clientarea    = CM.CM_LeafArea(leafnum);
            clientcluster = CM.CM_LeafCluster(leafnum);

            // calculate the visible areas
            frame.areabytes = CM.CM_WriteAreaBits(frame.areabits, clientarea);

            // grab the current player_state_t
            frame.ps.set(clent.client.ps);

            SV_ENTS.SV_FatPVS(org);
            clientphs = CM.CM_ClusterPHS(clientcluster);

            // build up the list of visible entities
            frame.num_entities = 0;
            frame.first_entity = SV_INIT.svs.next_client_entities;

            c_fullsend = 0;

            for (e = 1; e < GameBase.num_edicts; e++)
            {
                ent = GameBase.g_edicts[e];

                // ignore ents without visible models
                if ((ent.svflags & Defines.SVF_NOCLIENT) != 0)
                {
                    continue;
                }

                // ignore ents without visible models unless they have an effect
                if (0 == ent.s.modelindex && 0 == ent.s.effects && 0 == ent.s.sound && 0 == ent.s.@event)
                {
                    continue;
                }

                // ignore if not touching a PV leaf
                // check area
                if (ent != clent)
                {
                    if (!CM.CM_AreasConnected(clientarea, ent.areanum))
                    {
                        // doors can legally straddle two areas, so we may need to check another one
                        if (0 == ent.areanum2 || !CM.CM_AreasConnected(clientarea, ent.areanum2))
                        {
                            continue;                             // blocked by a door
                        }
                    }

                    // beams just check one point for PHS
                    if ((ent.s.renderfx & Defines.RF_BEAM) != 0)
                    {
                        l = ent.clusternums[0];

                        if (0 == (clientphs[l >> 3] & (1 << (l & 7))))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        // FIXME: if an ent has a model and a sound, but isn't
                        // in the PVS, only the PHS, clear the model
                        if (ent.s.sound == 0)
                        {
                            bitvector = SV_ENTS.fatpvs;                             //clientphs;
                        }
                        else
                        {
                            bitvector = SV_ENTS.fatpvs;
                        }

                        if (ent.num_clusters == -1)
                        {
                            // too many leafs for
                            // individual check, go by
                            // headnode
                            if (!CM.CM_HeadnodeVisible(ent.headnode, bitvector))
                            {
                                continue;
                            }

                            c_fullsend++;
                        }
                        else
                        {
                            // check individual leafs
                            for (i = 0; i < ent.num_clusters; i++)
                            {
                                l = ent.clusternums[i];

                                if ((bitvector[l >> 3] & (1 << (l & 7))) != 0)
                                {
                                    break;
                                }
                            }

                            if (i == ent.num_clusters)
                            {
                                continue;                                 // not visible
                            }
                        }

                        if (ent.s.modelindex == 0)
                        {
                            // don't send sounds if they
                            // will be attenuated away
                            float[] delta = { 0, 0, 0 };
                            float   len;

                            Math3D.VectorSubtract(org, ent.s.origin, delta);
                            len = Math3D.VectorLength(delta);

                            if (len > 400)
                            {
                                continue;
                            }
                        }
                    }
                }

                // add it to the circular client_entities array
                var ix = SV_INIT.svs.next_client_entities % SV_INIT.svs.num_client_entities;
                state = SV_INIT.svs.client_entities[ix];

                if (ent.s.number != e)
                {
                    Com.DPrintf("FIXING ENT.S.NUMBER!!!\n");
                    ent.s.number = e;
                }

                //*state = ent.s;
                SV_INIT.svs.client_entities[ix].set(ent.s);

                // don't mark players missiles as solid
                if (ent.owner == client.edict)
                {
                    state.solid = 0;
                }

                SV_INIT.svs.next_client_entities++;
                frame.num_entities++;
            }
        }