Exemple #1
0
        /// <summary>
        /// CL_KeepaliveMessage
        /// When the client is taking a long time to load stuff, send keepalive messages
        /// so the server doesn't disconnect.
        /// </summary>
        private static void KeepaliveMessage()
        {
            if (Server.IsActive)
            {
                return; // no need if server is local
            }
            if (cls.demoplayback)
            {
                return;
            }

            // read messages from server, should just be nops
            Net.Message.SaveState(ref _MsgState);

            int ret;

            do
            {
                ret = GetMessage();
                switch (ret)
                {
                default:
                    Host.Error("CL_KeepaliveMessage: CL_GetMessage failed");
                    break;

                case 0:
                    break;      // nothing waiting

                case 1:
                    Host.Error("CL_KeepaliveMessage: received a message");
                    break;

                case 2:
                    if (Net.Reader.ReadByte() != Protocol.svc_nop)
                    {
                        Host.Error("CL_KeepaliveMessage: datagram wasn't a nop");
                    }
                    break;
                }
            } while(ret != 0);

            Net.Message.RestoreState(_MsgState);

            // check time
            float time = (float)Sys.GetFloatTime();

            if (time - _LastMsg < 5)
            {
                return;
            }

            _LastMsg = time;

            // write out a nop
            Con.Print("--> client to server keepalive\n");

            cls.message.WriteByte(Protocol.clc_nop);
            Net.SendMessage(cls.netcon, cls.message);
            cls.message.Clear();
        }
Exemple #2
0
        /// <summary>
        /// SchedulePollProcedure
        /// </summary>
        static void SchedulePollProcedure(PollProcedure proc, double timeOffset)
        {
            proc.nextTime = Sys.GetFloatTime() + timeOffset;
            PollProcedure pp, prev;

            for (pp = _PollProcedureList, prev = null; pp != null; pp = pp.next)
            {
                if (pp.nextTime >= proc.nextTime)
                {
                    break;
                }

                prev = pp;
            }

            if (prev == null)
            {
                proc.next          = _PollProcedureList;
                _PollProcedureList = proc;
                return;
            }

            proc.next = pp;
            prev.next = proc;
        }
Exemple #3
0
        /// <summary>
        /// NET_Slist_f
        /// </summary>
        public static void Slist_f()
        {
            if (_SlistInProgress)
            {
                return;
            }

            if (!Net.SlistSilent)
            {
                Con.Print("Looking for Quake servers...\n");
                PrintSlistHeader();
            }

            _SlistInProgress = true;
            _SlistStartTime  = Sys.GetFloatTime();

            SchedulePollProcedure(_SlistSendProcedure, 0.0);
            SchedulePollProcedure(_SlistPollProcedure, 0.1);

            Net.HostCacheCount = 0;
        }
Exemple #4
0
        /// <summary>
        /// Slist_Send
        /// </summary>
        static void SlistSend(object arg)
        {
            for (_DriverLevel = 0; _DriverLevel < _Drivers.Length; _DriverLevel++)
            {
                if (!Net.SlistLocal && _DriverLevel == 0)
                {
                    continue;
                }
                if (!_Drivers[_DriverLevel].IsInitialized)
                {
                    continue;
                }

                _Drivers[_DriverLevel].SearchForHosts(true);
            }

            if ((Sys.GetFloatTime() - _SlistStartTime) < 0.5)
            {
                SchedulePollProcedure(_SlistSendProcedure, 0.75);
            }
        }
Exemple #5
0
        // Host_Frame
        public static void Frame(double time)
        {
            if (_ServerProfile.Value == 0)
            {
                InternalFrame(time);
                return;
            }

            double time1 = Sys.GetFloatTime();

            InternalFrame(time);
            double time2 = Sys.GetFloatTime();

            _TimeTotal += time2 - time1;
            _TimeCount++;

            if (_TimeCount < 1000)
            {
                return;
            }

            int m = (int)(_TimeTotal * 1000 / _TimeCount);

            _TimeCount = 0;
            _TimeTotal = 0;
            int c = 0;

            foreach (client_t cl in Server.svs.clients)
            {
                if (cl.active)
                {
                    c++;
                }
            }

            Con.Print("serverprofile: {0,2:d} clients {1,2:d} msec\n", c, m);
        }
Exemple #6
0
        /// <summary>
        /// Slist_Poll
        /// </summary>
        static void SlistPoll(object arg)
        {
            for (_DriverLevel = 0; _DriverLevel < _Drivers.Length; _DriverLevel++)
            {
                if (!Net.SlistLocal && _DriverLevel == 0)
                {
                    continue;
                }

                if (!_Drivers[_DriverLevel].IsInitialized)
                {
                    continue;
                }

                _Drivers[_DriverLevel].SearchForHosts(false);
            }

            if (!Net.SlistSilent)
            {
                PrintSlist();
            }

            if ((Sys.GetFloatTime() - _SlistStartTime) < 1.5)
            {
                SchedulePollProcedure(_SlistPollProcedure, 0.1);
                return;
            }

            if (!Net.SlistSilent)
            {
                PrintSlistTrailer();
            }

            _SlistInProgress = false;
            Net.SlistSilent  = false;
            Net.SlistLocal   = true;
        }
Exemple #7
0
 // double SetNetTime
 public static double SetNetTime()
 {
     _Time = Sys.GetFloatTime();
     return(_Time);
 }
Exemple #8
0
        /// <summary>
        /// NET_SendToAll
        /// This is a reliable *blocking* send to all attached clients.
        /// </summary>
        public static int SendToAll(MsgWriter data, int blocktime)
        {
            bool[] state1 = new bool[QDef.MAX_SCOREBOARD];
            bool[] state2 = new bool[QDef.MAX_SCOREBOARD];

            int count = 0;

            for (int i = 0; i < Server.svs.maxclients; i++)
            {
                Host.HostClient = Server.svs.clients[i];
                if (Host.HostClient.netconnection == null)
                {
                    continue;
                }

                if (Host.HostClient.active)
                {
                    if (Host.HostClient.netconnection.driver == 0)
                    {
                        SendMessage(Host.HostClient.netconnection, data);
                        state1[i] = true;
                        state2[i] = true;
                        continue;
                    }
                    count++;
                    state1[i] = false;
                    state2[i] = false;
                }
                else
                {
                    state1[i] = true;
                    state2[i] = true;
                }
            }

            double start = Sys.GetFloatTime();

            while (count > 0)
            {
                count = 0;
                for (int i = 0; i < Server.svs.maxclients; i++)
                {
                    Host.HostClient = Server.svs.clients[i];
                    if (!state1[i])
                    {
                        if (CanSendMessage(Host.HostClient.netconnection))
                        {
                            state1[i] = true;
                            SendMessage(Host.HostClient.netconnection, data);
                        }
                        else
                        {
                            GetMessage(Host.HostClient.netconnection);
                        }
                        count++;
                        continue;
                    }

                    if (!state2[i])
                    {
                        if (CanSendMessage(Host.HostClient.netconnection))
                        {
                            state2[i] = true;
                        }
                        else
                        {
                            GetMessage(Host.HostClient.netconnection);
                        }
                        count++;
                        continue;
                    }
                }
                if ((Sys.GetFloatTime() - start) > blocktime)
                {
                    break;
                }
            }
            return(count);
        }
Exemple #9
0
        /// <summary>
        /// Host_Spawn_f
        /// </summary>
        private static void Spawn_f()
        {
            if (Cmd.Source == cmd_source_t.src_command)
            {
                Con.Print("spawn is not valid from the console\n");
                return;
            }

            if (Host.HostClient.spawned)
            {
                Con.Print("Spawn not valid -- allready spawned\n");
                return;
            }

            edict_t ent;

            // run the entrance script
            if (Server.sv.loadgame)
            {
                // loaded games are fully inited allready
                // if this is the last client to be connected, unpause
                Server.sv.paused = false;
            }
            else
            {
                // set up the edict
                ent = Host.HostClient.edict;

                ent.Clear(); //memset(&ent.v, 0, progs.entityfields * 4);
                ent.v.colormap = Server.NumForEdict(ent);
                ent.v.team     = (Host.HostClient.colors & 15) + 1;
                ent.v.netname  = Progs.NewString(Host.HostClient.name);

                // copy spawn parms out of the client_t
                Progs.GlobalStruct.SetParams(Host.HostClient.spawn_parms);

                // call the spawn function

                Progs.GlobalStruct.time = (float)Server.sv.time;
                Progs.GlobalStruct.self = Server.EdictToProg(Server.Player);
                Progs.Execute(Progs.GlobalStruct.ClientConnect);

                if ((Sys.GetFloatTime() - Host.HostClient.netconnection.connecttime) <= Server.sv.time)
                {
                    Con.DPrint("{0} entered the game\n", Host.HostClient.name);
                }

                Progs.Execute(Progs.GlobalStruct.PutClientInServer);
            }

            // send all current names, colors, and frag counts
            MsgWriter msg = Host.HostClient.message;

            msg.Clear();

            // send time of update
            msg.WriteByte(Protocol.svc_time);
            msg.WriteFloat((float)Server.sv.time);

            for (int i = 0; i < Server.svs.maxclients; i++)
            {
                client_t client = Server.svs.clients[i];
                msg.WriteByte(Protocol.svc_updatename);
                msg.WriteByte(i);
                msg.WriteString(client.name);
                msg.WriteByte(Protocol.svc_updatefrags);
                msg.WriteByte(i);
                msg.WriteShort(client.old_frags);
                msg.WriteByte(Protocol.svc_updatecolors);
                msg.WriteByte(i);
                msg.WriteByte(client.colors);
            }

            // send all current light styles
            for (int i = 0; i < QDef.MAX_LIGHTSTYLES; i++)
            {
                msg.WriteByte(Protocol.svc_lightstyle);
                msg.WriteByte((char)i);
                msg.WriteString(Server.sv.lightstyles[i]);
            }

            //
            // send some stats
            //
            msg.WriteByte(Protocol.svc_updatestat);
            msg.WriteByte(QStats.STAT_TOTALSECRETS);
            msg.WriteLong((int)Progs.GlobalStruct.total_secrets);

            msg.WriteByte(Protocol.svc_updatestat);
            msg.WriteByte(QStats.STAT_TOTALMONSTERS);
            msg.WriteLong((int)Progs.GlobalStruct.total_monsters);

            msg.WriteByte(Protocol.svc_updatestat);
            msg.WriteByte(QStats.STAT_SECRETS);
            msg.WriteLong((int)Progs.GlobalStruct.found_secrets);

            msg.WriteByte(Protocol.svc_updatestat);
            msg.WriteByte(QStats.STAT_MONSTERS);
            msg.WriteLong((int)Progs.GlobalStruct.killed_monsters);

            //
            // send a fixangle
            // Never send a roll angle, because savegames can catch the server
            // in a state where it is expecting the client to correct the angle
            // and it won't happen if the game was just loaded, so you wind up
            // with a permanent head tilt
            ent = Server.EdictNum(1 + Host.ClientNum);
            msg.WriteByte(Protocol.svc_setangle);
            msg.WriteAngle(ent.v.angles.x);
            msg.WriteAngle(ent.v.angles.y);
            msg.WriteAngle(0);

            Server.WriteClientDataToMessage(Server.Player, Host.HostClient.message);

            msg.WriteByte(Protocol.svc_signonnum);
            msg.WriteByte(3);
            Host.HostClient.sendsignon = true;
        }
Exemple #10
0
        // _Host_Frame
        //
        //Runs all active servers
        static void InternalFrame(double time)
        {
            // keep the random time dependent
            Sys.Random();

            // decide the simulation time
            if (!FilterTime(time))
            {
                return;                 // don't run too fast, or packets will flood out
            }
            // get new key events
            Sys.SendKeyEvents();

            // allow mice or other external controllers to add commands
            Input.Commands();

            // process console commands
            Cbuf.Execute();

            Net.Poll();

            // if running the server locally, make intentions now
            if (Server.sv.active)
            {
                Client.SendCmd();
            }

            //-------------------
            //
            // server operations
            //
            //-------------------

            // check for commands typed to the host
            GetConsoleCommands();

            if (Server.sv.active)
            {
                ServerFrame();
            }

            //-------------------
            //
            // client operations
            //
            //-------------------

            // if running the server remotely, send intentions now after
            // the incoming messages have been read
            if (!Server.sv.active)
            {
                Client.SendCmd();
            }

            _Time += FrameTime;

            // fetch results from server
            if (Client.cls.state == cactive_t.ca_connected)
            {
                Client.ReadFromServer();
            }

            // update video
            if (_Speeds.Value != 0)
            {
                _Time1 = Sys.GetFloatTime();
            }

            Scr.UpdateScreen();

            if (_Speeds.Value != 0)
            {
                _Time2 = Sys.GetFloatTime();
            }

            // update audio
            if (Client.cls.signon == Client.SIGNONS)
            {
                Sound.Update(ref Render.Origin, ref Render.ViewPn, ref Render.ViewRight, ref Render.ViewUp);
                Client.DecayLights();
            }
            else
            {
                Sound.Update(ref Common.ZeroVector, ref Common.ZeroVector, ref Common.ZeroVector, ref Common.ZeroVector);
            }

            CDAudio.Update();

            if (_Speeds.Value != 0)
            {
                int pass1 = (int)((_Time1 - _Time3) * 1000);
                _Time3 = Sys.GetFloatTime();
                int pass2 = (int)((_Time2 - _Time1) * 1000);
                int pass3 = (int)((_Time3 - _Time2) * 1000);
                Con.Print("{0,3} tot {1,3} server {2,3} gfx {3,3} snd\n", pass1 + pass2 + pass3, pass1, pass2, pass3);
            }

            _FrameCount++;
        }
Exemple #11
0
        /// <summary>
        /// Host_ShutdownServer
        /// This only happens at the end of a game, not between levels
        /// </summary>
        public static void ShutdownServer(bool crash)
        {
            if (!Server.IsActive)
            {
                return;
            }

            Server.sv.active = false;

            // stop all client sounds immediately
            if (Client.cls.state == cactive_t.ca_connected)
            {
                Client.Disconnect();
            }

            // flush any pending messages - like the score!!!
            double start = Sys.GetFloatTime();
            int    count;

            do
            {
                count = 0;
                for (int i = 0; i < Server.svs.maxclients; i++)
                {
                    HostClient = Server.svs.clients[i];
                    if (HostClient.active && !HostClient.message.IsEmpty)
                    {
                        if (Net.CanSendMessage(HostClient.netconnection))
                        {
                            Net.SendMessage(HostClient.netconnection, HostClient.message);
                            HostClient.message.Clear();
                        }
                        else
                        {
                            Net.GetMessage(HostClient.netconnection);
                            count++;
                        }
                    }
                }
                if ((Sys.GetFloatTime() - start) > 3.0)
                {
                    break;
                }
            }while (count > 0);

            // make sure all the clients know we're disconnecting
            MsgWriter writer = new MsgWriter(4);

            writer.WriteByte(Protocol.svc_disconnect);
            count = Net.SendToAll(writer, 5);
            if (count != 0)
            {
                Con.Print("Host_ShutdownServer: NET_SendToAll failed for {0} clients\n", count);
            }

            for (int i = 0; i < Server.svs.maxclients; i++)
            {
                HostClient = Server.svs.clients[i];
                if (HostClient.active)
                {
                    Server.DropClient(crash);
                }
            }

            //
            // clear structures
            //
            Server.sv.Clear();
            for (int i = 0; i < Server.svs.clients.Length; i++)
            {
                Server.svs.clients[i].Clear();
            }
        }