Example #1
0
        /**
         * Writes a frame to a client system.
         */
        public static void SV_WriteFrameToClient(client_t client, sizebuf_t msg)
        {
            //ptr
            client_frame_t frame, oldframe;
            int            lastframe;

            //Com.Printf ("%i . %i\n", new
            // Vargs().add(client.lastframe).add(sv.framenum));
            // this is the frame we are creating
            frame = client.frames[SV_INIT.sv.framenum & Defines.UPDATE_MASK];

            if (client.lastframe <= 0)
            {
                // client is asking for a retransmit
                oldframe  = null;
                lastframe = -1;
            }
            else if (SV_INIT.sv.framenum - client.lastframe >= Defines.UPDATE_BACKUP - 3)
            {
                // client hasn't gotten a good message through in a long time
                // Com_Printf ("%s: Delta request from out-of-date packet.\n",
                // client.name);
                oldframe  = null;
                lastframe = -1;
            }
            else
            {
                // we have a valid message to delta from
                oldframe  = client.frames[client.lastframe & Defines.UPDATE_MASK];
                lastframe = client.lastframe;
            }

            MSG.WriteByte(msg, Defines.svc_frame);
            MSG.WriteLong(msg, SV_INIT.sv.framenum);
            MSG.WriteLong(msg, lastframe);             // what we are delta'ing from
            MSG.WriteByte(msg, client.surpressCount);  // rate dropped packets
            client.surpressCount = 0;

            // send over the areabits
            MSG.WriteByte(msg, frame.areabytes);
            SZ.Write(msg, frame.areabits, frame.areabytes);

            // delta encode the playerstate
            SV_ENTS.SV_WritePlayerstateToClient(oldframe, frame, msg);

            // delta encode the entities
            SV_ENTS.SV_EmitPacketEntities(oldframe, frame, msg);
        }
Example #2
0
        /**
         * SV_Frame.
         */
        public static void SV_Frame(long msec)
        {
            Globals.time_before_game = Globals.time_after_game = 0;

            // if server is not active, do nothing
            if (!SV_INIT.svs.initialized)
            {
                return;
            }

            SV_INIT.svs.realtime += (int)msec;

            // keep the random time dependent
            Lib.rand();

            // check timeouts
            SV_MAIN.SV_CheckTimeouts();

            // get packets from clients
            SV_MAIN.SV_ReadPackets();

            //if (Game.g_edicts[1] !=null)
            //	Com.p("player at:" + Lib.vtofsbeaty(Game.g_edicts[1].s.origin ));

            // move autonomous things around if enough time has passed
            if (0 == SV_MAIN.sv_timedemo.value && SV_INIT.svs.realtime < SV_INIT.sv.time)
            {
                // never let the time get too far off
                if (SV_INIT.sv.time - SV_INIT.svs.realtime > 100)
                {
                    if (SV_MAIN.sv_showclamp.value != 0)
                    {
                        Com.Printf("sv lowclamp\n");
                    }

                    SV_INIT.svs.realtime = SV_INIT.sv.time - 100;
                }

                return;
            }

            // update ping based on the last known frame from all clients
            SV_MAIN.SV_CalcPings();

            // give the clients some timeslices
            SV_MAIN.SV_GiveMsec();

            // let everything in the world think and move
            SV_MAIN.SV_RunGameFrame();

            // send messages back to the clients that had packets read this frame
            SV_SEND.SV_SendClientMessages();

            // save the entire world state if recording a serverdemo
            SV_ENTS.SV_RecordDemoMessage();

            // send a heartbeat to the master if needed
            SV_MAIN.Master_Heartbeat();

            // clear teleport flags, etc for next frame
            SV_MAIN.SV_PrepWorldFrame();
        }
Example #3
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++;
            }
        }