Example #1
0
        public static void SV_ReadPackets( )
        {
            Int32    i;
            client_t cl;
            var      qport = 0;

            while (NET.GetPacket(Defines.NS_SERVER, Globals.net_from, Globals.net_message))
            {
                if ((Globals.net_message.data[0] == -1) && (Globals.net_message.data[1] == -1) && (Globals.net_message.data[2] == -1) && (Globals.net_message.data[3] == -1))
                {
                    SV_ConnectionlessPacket();
                    continue;
                }

                MSG.BeginReading(Globals.net_message);
                MSG.ReadLong(Globals.net_message);
                MSG.ReadLong(Globals.net_message);
                qport = MSG.ReadShort(Globals.net_message) & 0xffff;
                for (i = 0; i < SV_MAIN.maxclients.value; i++)
                {
                    cl = SV_INIT.svs.clients[i];
                    if (cl.state == Defines.cs_free)
                    {
                        continue;
                    }
                    if (!NET.CompareBaseAdr(Globals.net_from, cl.netchan.remote_address))
                    {
                        continue;
                    }
                    if (cl.netchan.qport != qport)
                    {
                        continue;
                    }
                    if (cl.netchan.remote_address.port != Globals.net_from.port)
                    {
                        Com.Printf("SV_ReadPackets: fixing up a translated port\\n");
                        cl.netchan.remote_address.port = Globals.net_from.port;
                    }

                    if (Netchan.Process(cl.netchan, Globals.net_message))
                    {
                        if (cl.state != Defines.cs_zombie)
                        {
                            cl.lastmessage = SV_INIT.svs.realtime;
                            SV_USER.SV_ExecuteClientMessage(cl);
                        }
                    }

                    break;
                }

                if (i != SV_MAIN.maxclients.value)
                {
                    continue;
                }
            }
        }
Example #2
0
        /**
         * A connectionless packet has four leading 0xff characters to distinguish
         * it from a game channel. Clients that are in the game can still send
         * connectionless packets. It is used also by rcon commands.
         */
        public static void SV_ConnectionlessPacket()
        {
            string s;
            string c;

            MSG.BeginReading(Globals.net_message);
            MSG.ReadLong(Globals.net_message);             // skip the -1 marker

            s = MSG.ReadStringLine(Globals.net_message);

            Cmd.TokenizeString(s.ToCharArray(), false);

            c = Cmd.Argv(0);

            //for debugging purposes
            //Com.Printf("Packet " + NET.AdrToString(Netchan.net_from) + " : " + c + "\n");
            //Com.Printf(Lib.hexDump(net_message.data, 64, false) + "\n");

            if (0 == Lib.strcmp(c, "ping"))
            {
                SV_MAIN.SVC_Ping();
            }
            else if (0 == Lib.strcmp(c, "ack"))
            {
                SV_MAIN.SVC_Ack();
            }
            else if (0 == Lib.strcmp(c, "status"))
            {
                SV_MAIN.SVC_Status();
            }
            else if (0 == Lib.strcmp(c, "info"))
            {
                SV_MAIN.SVC_Info();
            }
            else if (0 == Lib.strcmp(c, "getchallenge"))
            {
                SV_MAIN.SVC_GetChallenge();
            }
            else if (0 == Lib.strcmp(c, "connect"))
            {
                SV_MAIN.SVC_DirectConnect();
            }
            else if (0 == Lib.strcmp(c, "rcon"))
            {
                SV_MAIN.SVC_RemoteCommand();
            }
            else
            {
                Com.Printf("bad connectionless packet from " + NET.AdrToString(Globals.net_from) + "\n");
                Com.Printf("[" + s + "]\n");
                Com.Printf("" + Lib.hexDump(Globals.net_message.data, 128, false));
            }
        }
Example #3
0
        public static void SV_ConnectionlessPacket( )
        {
            String s;
            String c;

            MSG.BeginReading(Globals.net_message);
            MSG.ReadLong(Globals.net_message);
            s = MSG.ReadStringLine(Globals.net_message);
            Cmd.TokenizeString(s.ToCharArray(), false);
            c = Cmd.Argv(0);
            if (0 == Lib.Strcmp(c, "ping"))
            {
                SVC_Ping();
            }
            else if (0 == Lib.Strcmp(c, "ack"))
            {
                SVC_Ack();
            }
            else if (0 == Lib.Strcmp(c, "status"))
            {
                SVC_Status();
            }
            else if (0 == Lib.Strcmp(c, "info"))
            {
                SVC_Info();
            }
            else if (0 == Lib.Strcmp(c, "getchallenge"))
            {
                SVC_GetChallenge();
            }
            else if (0 == Lib.Strcmp(c, "connect"))
            {
                SVC_DirectConnect();
            }
            else if (0 == Lib.Strcmp(c, "rcon"))
            {
                SVC_RemoteCommand();
            }
            else
            {
                Com.Printf("bad connectionless packet from " + NET.AdrToString(Globals.net_from) + "\\n");
                Com.Printf("[" + s + "]\\n");
                Com.Printf("" + Lib.HexDump(Globals.net_message.data, 128, false));
            }
        }
Example #4
0
        public static void ParseServerData( )
        {
            Com.DPrintf("ParseServerData():Serverdata packet received.\\n");
            CL.ClearState();
            Globals.cls.state = Defines.ca_connected;
            var i = MSG.ReadLong(Globals.net_message);

            Globals.cls.serverProtocol = i;
            if (Globals.server_state != 0 && Defines.PROTOCOL_VERSION == 34)
            {
            }
            else if (i != Defines.PROTOCOL_VERSION)
            {
                Com.Error(Defines.ERR_DROP, "Server returned version " + i + ", not " + Defines.PROTOCOL_VERSION);
            }
            Globals.cl.servercount = MSG.ReadLong(Globals.net_message);
            Globals.cl.attractloop = MSG.ReadByte(Globals.net_message) != 0;
            var str = MSG.ReadString(Globals.net_message);

            Globals.cl.gamedir = str;
            Com.Dprintln("gamedir=" + str);
            if (str.Length > 0 && (FS.fs_gamedirvar.string_renamed == null || FS.fs_gamedirvar.string_renamed.Length == 0 || FS.fs_gamedirvar.string_renamed.Equals(str)) || (str.Length == 0 && (FS.fs_gamedirvar.string_renamed != null || FS.fs_gamedirvar.string_renamed.Length == 0)))
            {
                Cvar.Set("game", str);
            }
            Globals.cl.playernum = MSG.ReadShort(Globals.net_message);
            Com.Dprintln("numplayers=" + Globals.cl.playernum);
            str = MSG.ReadString(Globals.net_message);
            Com.Dprintln("levelname=" + str);
            if (Globals.cl.playernum == -1)
            {
                SCR.PlayCinematic(str);
            }
            else
            {
                Com.Printf("Levelname:" + str + "\\n");
                Globals.cl.refresh_prepped = false;
            }
        }
Example #5
0
        /**
         * Reads packets from the network or loopback.
         */
        public static void SV_ReadPackets()
        {
            int      i;
            client_t cl;
            var      qport = 0;

            while (NET.GetPacket(Defines.NS_SERVER, Globals.net_from, Globals.net_message))
            {
                // check for connectionless packet (0xffffffff) first
                if (Globals.net_message.data[0] == 255 &&
                    Globals.net_message.data[1] == 255 &&
                    Globals.net_message.data[2] == 255 &&
                    Globals.net_message.data[3] == 255)
                {
                    SV_MAIN.SV_ConnectionlessPacket();

                    continue;
                }

                // read the qport out of the message so we can fix up
                // stupid address translating routers
                MSG.BeginReading(Globals.net_message);
                MSG.ReadLong(Globals.net_message);                 // sequence number
                MSG.ReadLong(Globals.net_message);                 // sequence number
                qport = MSG.ReadShort(Globals.net_message) & 0xffff;

                // check for packets from connected clients
                for (i = 0; i < SV_MAIN.maxclients.value; i++)
                {
                    cl = SV_INIT.svs.clients[i];

                    if (cl.state == Defines.cs_free)
                    {
                        continue;
                    }

                    if (!NET.CompareBaseAdr(Globals.net_from, cl.netchan.remote_address))
                    {
                        continue;
                    }

                    if (cl.netchan.qport != qport)
                    {
                        continue;
                    }

                    if (cl.netchan.remote_address.port != Globals.net_from.port)
                    {
                        Com.Printf("SV_ReadPackets: fixing up a translated port\n");
                        cl.netchan.remote_address.port = Globals.net_from.port;
                    }

                    if (Netchan.Process(cl.netchan, Globals.net_message))
                    {
                        // this is a valid, sequenced packet, so process it
                        if (cl.state != Defines.cs_zombie)
                        {
                            cl.lastmessage = SV_INIT.svs.realtime;                             // don't timeout
                            SV_USER.SV_ExecuteClientMessage(cl);
                        }
                    }

                    break;
                }

                if (i != SV_MAIN.maxclients.value)
                {
                    continue;
                }
            }
        }
Example #6
0
        /*
         * =====================================================================
         *
         * SERVER CONNECTING MESSAGES
         *
         * =====================================================================
         */

        /*
         * ================== CL_ParseServerData ==================
         */
        //checked once, was ok.
        public static void ParseServerData()
        {
            Com.DPrintf("ParseServerData():Serverdata packet received.\n");

            //
            //	   wipe the client_state_t struct
            //
            Cl.ClearState();
            Globals.cls.state = Defines.ca_connected;

            //	   parse protocol version number
            var i = MSG.ReadLong(Globals.net_message);

            Globals.cls.serverProtocol = i;

            // BIG HACK to let demos from release work with the 3.0x patch!!!
            if (Globals.server_state != 0 && Defines.PROTOCOL_VERSION == 34)
            {
            }
            else if (i != Defines.PROTOCOL_VERSION)
            {
                Com.Error(Defines.ERR_DROP, "Server returned version " + i + ", not " + Defines.PROTOCOL_VERSION);
            }

            Globals.cl.servercount = MSG.ReadLong(Globals.net_message);
            Globals.cl.attractloop = MSG.ReadByte(Globals.net_message) != 0;

            // game directory
            var str = MSG.ReadString(Globals.net_message);

            Globals.cl.gamedir = str;
            Com.dprintln("gamedir=" + str);

            // set gamedir
            if ((str.Length > 0 && (FS.fs_gamedirvar.@string == null || [email protected] == 0 || [email protected](str))) ||
                (str.Length == 0 && (FS.fs_gamedirvar.@string != null || [email protected] == 0)))
            {
                Cvar.Set("game", str);
            }

            // parse player entity number
            Globals.cl.playernum = MSG.ReadShort(Globals.net_message);
            Com.dprintln("numplayers=" + Globals.cl.playernum);

            // get the full level name
            str = MSG.ReadString(Globals.net_message);
            Com.dprintln("levelname=" + str);

            if (Globals.cl.playernum == -1)
            {
                // playing a cinematic or showing a
                // pic, not a level
                SCR.PlayCinematic(str);
            }
            else
            {
                // seperate the printfs so the server message can have a color
                //			Com.Printf(
                //				"\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n");
                //			Com.Printf('\02' + str + "\n");
                Com.Printf("Levelname:" + str + "\n");

                // need to prep refresh at next oportunity
                Globals.cl.refresh_prepped = false;
            }
        }
Example #7
0
 public static void ParseDelta(entity_state_t from, entity_state_t to, Int32 number, Int32 bits)
 {
     to.Set(from);
     Math3D.VectorCopy(from.origin, to.old_origin);
     to.number = number;
     if ((bits & Defines.U_MODEL) != 0)
     {
         to.modelindex = MSG.ReadByte(Globals.net_message);
     }
     if ((bits & Defines.U_MODEL2) != 0)
     {
         to.modelindex2 = MSG.ReadByte(Globals.net_message);
     }
     if ((bits & Defines.U_MODEL3) != 0)
     {
         to.modelindex3 = MSG.ReadByte(Globals.net_message);
     }
     if ((bits & Defines.U_MODEL4) != 0)
     {
         to.modelindex4 = MSG.ReadByte(Globals.net_message);
     }
     if ((bits & Defines.U_FRAME8) != 0)
     {
         to.frame = MSG.ReadByte(Globals.net_message);
     }
     if ((bits & Defines.U_FRAME16) != 0)
     {
         to.frame = MSG.ReadShort(Globals.net_message);
     }
     if ((bits & Defines.U_SKIN8) != 0 && (bits & Defines.U_SKIN16) != 0)
     {
         to.skinnum = MSG.ReadLong(Globals.net_message);
     }
     else if ((bits & Defines.U_SKIN8) != 0)
     {
         to.skinnum = MSG.ReadByte(Globals.net_message);
     }
     else if ((bits & Defines.U_SKIN16) != 0)
     {
         to.skinnum = MSG.ReadShort(Globals.net_message);
     }
     if ((bits & (Defines.U_EFFECTS8 | Defines.U_EFFECTS16)) == (Defines.U_EFFECTS8 | Defines.U_EFFECTS16))
     {
         to.effects = MSG.ReadLong(Globals.net_message);
     }
     else if ((bits & Defines.U_EFFECTS8) != 0)
     {
         to.effects = MSG.ReadByte(Globals.net_message);
     }
     else if ((bits & Defines.U_EFFECTS16) != 0)
     {
         to.effects = MSG.ReadShort(Globals.net_message);
     }
     if ((bits & (Defines.U_RENDERFX8 | Defines.U_RENDERFX16)) == (Defines.U_RENDERFX8 | Defines.U_RENDERFX16))
     {
         to.renderfx = MSG.ReadLong(Globals.net_message);
     }
     else if ((bits & Defines.U_RENDERFX8) != 0)
     {
         to.renderfx = MSG.ReadByte(Globals.net_message);
     }
     else if ((bits & Defines.U_RENDERFX16) != 0)
     {
         to.renderfx = MSG.ReadShort(Globals.net_message);
     }
     if ((bits & Defines.U_ORIGIN1) != 0)
     {
         to.origin[0] = MSG.ReadCoord(Globals.net_message);
     }
     if ((bits & Defines.U_ORIGIN2) != 0)
     {
         to.origin[1] = MSG.ReadCoord(Globals.net_message);
     }
     if ((bits & Defines.U_ORIGIN3) != 0)
     {
         to.origin[2] = MSG.ReadCoord(Globals.net_message);
     }
     if ((bits & Defines.U_ANGLE1) != 0)
     {
         to.angles[0] = MSG.ReadAngle(Globals.net_message);
     }
     if ((bits & Defines.U_ANGLE2) != 0)
     {
         to.angles[1] = MSG.ReadAngle(Globals.net_message);
     }
     if ((bits & Defines.U_ANGLE3) != 0)
     {
         to.angles[2] = MSG.ReadAngle(Globals.net_message);
     }
     if ((bits & Defines.U_OLDORIGIN) != 0)
     {
         MSG.ReadPos(Globals.net_message, to.old_origin);
     }
     if ((bits & Defines.U_SOUND) != 0)
     {
         to.sound = MSG.ReadByte(Globals.net_message);
     }
     if ((bits & Defines.U_EVENT) != 0)
     {
         to.event_renamed = MSG.ReadByte(Globals.net_message);
     }
     else
     {
         to.event_renamed = 0;
     }
     if ((bits & Defines.U_SOLID) != 0)
     {
         to.solid = MSG.ReadShort(Globals.net_message);
     }
 }
Example #8
0
        public static void ParseFrame( )
        {
            Int32   cmd;
            Int32   len;
            frame_t old;

            Globals.cl.frame.Reset();
            Globals.cl.frame.serverframe = MSG.ReadLong(Globals.net_message);
            Globals.cl.frame.deltaframe  = MSG.ReadLong(Globals.net_message);
            Globals.cl.frame.servertime  = Globals.cl.frame.serverframe * 100;
            if (Globals.cls.serverProtocol != 26)
            {
                Globals.cl.surpressCount = MSG.ReadByte(Globals.net_message);
            }
            if (Globals.cl_shownet.value == 3)
            {
                Com.Printf("   frame:" + Globals.cl.frame.serverframe + "  delta:" + Globals.cl.frame.deltaframe + "\\n");
            }
            if (Globals.cl.frame.deltaframe <= 0)
            {
                Globals.cl.frame.valid = true;
                old = null;
                Globals.cls.demowaiting = false;
            }
            else
            {
                old = Globals.cl.frames[Globals.cl.frame.deltaframe & Defines.UPDATE_MASK];
                if (!old.valid)
                {
                    Com.Printf("Delta from invalid frame (not supposed to happen!).\\n");
                }

                if (old.serverframe != Globals.cl.frame.deltaframe)
                {
                    Com.Printf("Delta frame too old.\\n");
                }
                else if (Globals.cl.parse_entities - old.parse_entities > Defines.MAX_PARSE_ENTITIES - 128)
                {
                    Com.Printf("Delta parse_entities too old.\\n");
                }
                else
                {
                    Globals.cl.frame.valid = true;
                }
            }

            if (Globals.cl.time > Globals.cl.frame.servertime)
            {
                Globals.cl.time = Globals.cl.frame.servertime;
            }
            else if (Globals.cl.time < Globals.cl.frame.servertime - 100)
            {
                Globals.cl.time = Globals.cl.frame.servertime - 100;
            }
            len = MSG.ReadByte(Globals.net_message);
            MSG.ReadData(Globals.net_message, Globals.cl.frame.areabits, len);
            cmd = MSG.ReadByte(Globals.net_message);
            CL_parse.SHOWNET(CL_parse.svc_strings[cmd]);
            if (cmd != Defines.svc_playerinfo)
            {
                Com.Error(Defines.ERR_DROP, "CL_ParseFrame: not playerinfo");
            }
            ParsePlayerstate(old, Globals.cl.frame);
            cmd = MSG.ReadByte(Globals.net_message);
            CL_parse.SHOWNET(CL_parse.svc_strings[cmd]);
            if (cmd != Defines.svc_packetentities)
            {
                Com.Error(Defines.ERR_DROP, "CL_ParseFrame: not packetentities");
            }
            ParsePacketEntities(old, Globals.cl.frame);
            Globals.cl.frames[Globals.cl.frame.serverframe & Defines.UPDATE_MASK].Set(Globals.cl.frame);
            if (Globals.cl.frame.valid)
            {
                if (Globals.cls.state != Defines.ca_active)
                {
                    Globals.cls.state              = Defines.ca_active;
                    Globals.cl.force_refdef        = true;
                    Globals.cl.predicted_origin[0] = Globals.cl.frame.playerstate.pmove.origin[0] * 0.125F;
                    Globals.cl.predicted_origin[1] = Globals.cl.frame.playerstate.pmove.origin[1] * 0.125F;
                    Globals.cl.predicted_origin[2] = Globals.cl.frame.playerstate.pmove.origin[2] * 0.125F;
                    Math3D.VectorCopy(Globals.cl.frame.playerstate.viewangles, Globals.cl.predicted_angles);
                    if (Globals.cls.disable_servercount != Globals.cl.servercount && Globals.cl.refresh_prepped)
                    {
                        SCR.EndLoadingPlaque();
                    }
                }

                Globals.cl.sound_prepped = true;
                FireEntityEvents(Globals.cl.frame);
                CL_pred.CheckPredictionError();
            }
        }
Example #9
0
        public static void ParsePlayerstate(frame_t oldframe, frame_t newframe)
        {
            Int32          flags;
            player_state_t state;
            Int32          i;
            Int32          statbits;

            state = newframe.playerstate;
            if (oldframe != null)
            {
                state.Set(oldframe.playerstate);
            }
            else
            {
                state.Clear();
            }
            flags = MSG.ReadShort(Globals.net_message);
            if ((flags & Defines.PS_M_TYPE) != 0)
            {
                state.pmove.pm_type = MSG.ReadByte(Globals.net_message);
            }
            if ((flags & Defines.PS_M_ORIGIN) != 0)
            {
                state.pmove.origin[0] = MSG.ReadShort(Globals.net_message);
                state.pmove.origin[1] = MSG.ReadShort(Globals.net_message);
                state.pmove.origin[2] = MSG.ReadShort(Globals.net_message);
            }

            if ((flags & Defines.PS_M_VELOCITY) != 0)
            {
                state.pmove.velocity[0] = MSG.ReadShort(Globals.net_message);
                state.pmove.velocity[1] = MSG.ReadShort(Globals.net_message);
                state.pmove.velocity[2] = MSG.ReadShort(Globals.net_message);
            }

            if ((flags & Defines.PS_M_TIME) != 0)
            {
                state.pmove.pm_time = ( Byte )MSG.ReadByte(Globals.net_message);
            }

            if ((flags & Defines.PS_M_FLAGS) != 0)
            {
                state.pmove.pm_flags = ( Byte )MSG.ReadByte(Globals.net_message);
            }
            if ((flags & Defines.PS_M_GRAVITY) != 0)
            {
                state.pmove.gravity = MSG.ReadShort(Globals.net_message);
            }
            if ((flags & Defines.PS_M_DELTA_ANGLES) != 0)
            {
                state.pmove.delta_angles[0] = MSG.ReadShort(Globals.net_message);
                state.pmove.delta_angles[1] = MSG.ReadShort(Globals.net_message);
                state.pmove.delta_angles[2] = MSG.ReadShort(Globals.net_message);
            }

            if (Globals.cl.attractloop)
            {
                state.pmove.pm_type = Defines.PM_FREEZE;
            }
            if ((flags & Defines.PS_VIEWOFFSET) != 0)
            {
                state.viewoffset[0] = MSG.ReadChar(Globals.net_message) * 0.25F;
                state.viewoffset[1] = MSG.ReadChar(Globals.net_message) * 0.25F;
                state.viewoffset[2] = MSG.ReadChar(Globals.net_message) * 0.25F;
            }

            if ((flags & Defines.PS_VIEWANGLES) != 0)
            {
                state.viewangles[0] = MSG.ReadAngle16(Globals.net_message);
                state.viewangles[1] = MSG.ReadAngle16(Globals.net_message);
                state.viewangles[2] = MSG.ReadAngle16(Globals.net_message);
            }

            if ((flags & Defines.PS_KICKANGLES) != 0)
            {
                state.kick_angles[0] = MSG.ReadChar(Globals.net_message) * 0.25F;
                state.kick_angles[1] = MSG.ReadChar(Globals.net_message) * 0.25F;
                state.kick_angles[2] = MSG.ReadChar(Globals.net_message) * 0.25F;
            }

            if ((flags & Defines.PS_WEAPONINDEX) != 0)
            {
                state.gunindex = MSG.ReadByte(Globals.net_message);
            }

            if ((flags & Defines.PS_WEAPONFRAME) != 0)
            {
                state.gunframe     = MSG.ReadByte(Globals.net_message);
                state.gunoffset[0] = MSG.ReadChar(Globals.net_message) * 0.25F;
                state.gunoffset[1] = MSG.ReadChar(Globals.net_message) * 0.25F;
                state.gunoffset[2] = MSG.ReadChar(Globals.net_message) * 0.25F;
                state.gunangles[0] = MSG.ReadChar(Globals.net_message) * 0.25F;
                state.gunangles[1] = MSG.ReadChar(Globals.net_message) * 0.25F;
                state.gunangles[2] = MSG.ReadChar(Globals.net_message) * 0.25F;
            }

            if ((flags & Defines.PS_BLEND) != 0)
            {
                state.blend[0] = MSG.ReadByte(Globals.net_message) / 255F;
                state.blend[1] = MSG.ReadByte(Globals.net_message) / 255F;
                state.blend[2] = MSG.ReadByte(Globals.net_message) / 255F;
                state.blend[3] = MSG.ReadByte(Globals.net_message) / 255F;
            }

            if ((flags & Defines.PS_FOV) != 0)
            {
                state.fov = MSG.ReadByte(Globals.net_message);
            }
            if ((flags & Defines.PS_RDFLAGS) != 0)
            {
                state.rdflags = MSG.ReadByte(Globals.net_message);
            }
            statbits = MSG.ReadLong(Globals.net_message);
            for (i = 0; i < Defines.MAX_STATS; i++)
            {
                if ((statbits & (1 << i)) != 0)
                {
                    state.stats[i] = MSG.ReadShort(Globals.net_message);
                }
            }
        }
Example #10
0
        public static void SV_ExecuteClientMessage(client_t cl)
        {
            Int32     c;
            String    s;
            usercmd_t nullcmd = new usercmd_t();
            usercmd_t oldest = new usercmd_t(), oldcmd = new usercmd_t(), newcmd = new usercmd_t();
            Int32     net_drop;
            Int32     stringCmdCount;
            Int32     checksum, calculatedChecksum;
            Int32     checksumIndex;
            Boolean   move_issued;
            Int32     lastframe;

            SV_MAIN.sv_client = cl;
            SV_USER.sv_player = SV_MAIN.sv_client.edict;
            move_issued       = false;
            stringCmdCount    = 0;
            while (true)
            {
                if (Globals.net_message.readcount > Globals.net_message.cursize)
                {
                    Com.Printf("SV_ReadClientMessage: bad read:\\n");
                    Com.Printf(Lib.HexDump(Globals.net_message.data, 32, false));
                    SV_MAIN.SV_DropClient(cl);
                    return;
                }

                c = MSG.ReadByte(Globals.net_message);
                if (c == -1)
                {
                    break;
                }
                switch (c)

                {
                default:
                    Com.Printf("SV_ReadClientMessage: unknown command char\\n");
                    SV_MAIN.SV_DropClient(cl);
                    return;

                case Defines.clc_nop:
                    break;

                case Defines.clc_userinfo:
                    cl.userinfo = MSG.ReadString(Globals.net_message);
                    SV_MAIN.SV_UserinfoChanged(cl);
                    break;

                case Defines.clc_move:
                    if (move_issued)
                    {
                        return;
                    }
                    move_issued   = true;
                    checksumIndex = Globals.net_message.readcount;
                    checksum      = MSG.ReadByte(Globals.net_message);
                    lastframe     = MSG.ReadLong(Globals.net_message);
                    if (lastframe != cl.lastframe)
                    {
                        cl.lastframe = lastframe;
                        if (cl.lastframe > 0)
                        {
                            cl.frame_latency[cl.lastframe & (Defines.LATENCY_COUNTS - 1)] = SV_INIT.svs.realtime - cl.frames[cl.lastframe & Defines.UPDATE_MASK].senttime;
                        }
                    }

                    nullcmd = new usercmd_t();
                    MSG.ReadDeltaUsercmd(Globals.net_message, nullcmd, oldest);
                    MSG.ReadDeltaUsercmd(Globals.net_message, oldest, oldcmd);
                    MSG.ReadDeltaUsercmd(Globals.net_message, oldcmd, newcmd);
                    if (cl.state != Defines.cs_spawned)
                    {
                        cl.lastframe = -1;
                        break;
                    }

                    calculatedChecksum = Com.BlockSequenceCRCByte(Globals.net_message.data, checksumIndex + 1, Globals.net_message.readcount - checksumIndex - 1, cl.netchan.incoming_sequence);
                    if ((calculatedChecksum & 0xff) != checksum)
                    {
                        Com.DPrintf("Failed command checksum for " + cl.name + " (" + calculatedChecksum + " != " + checksum + ")/" + cl.netchan.incoming_sequence + "\\n");
                        return;
                    }

                    if (0 == SV_MAIN.sv_paused.value)
                    {
                        net_drop = cl.netchan.dropped;
                        if (net_drop < 20)
                        {
                            while (net_drop > 2)
                            {
                                SV_ClientThink(cl, cl.lastcmd);
                                net_drop--;
                            }

                            if (net_drop > 1)
                            {
                                SV_ClientThink(cl, oldest);
                            }
                            if (net_drop > 0)
                            {
                                SV_ClientThink(cl, oldcmd);
                            }
                        }

                        SV_ClientThink(cl, newcmd);
                    }

                    cl.lastcmd.Set(newcmd);
                    break;

                case Defines.clc_stringcmd:
                    s = MSG.ReadString(Globals.net_message);
                    if (++stringCmdCount < SV_USER.MAX_STRINGCMDS)
                    {
                        SV_ExecuteUserCommand(s);
                    }
                    if (cl.state == Defines.cs_zombie)
                    {
                        return;
                    }
                    break;
                }
            }
        }