예제 #1
0
        /*
         * =======================
         * SV_SendClientDatagram
         * =======================
         */
        static bool SV_SendClientDatagram(client_t client)
        {
            byte[]           buf = new byte[quakedef.MAX_DATAGRAM];
            common.sizebuf_t msg = new common.sizebuf_t();

            msg.data    = buf;
            msg.maxsize = buf.Length;
            msg.cursize = 0;

            common.MSG_WriteByte(msg, net.svc_time);
            common.MSG_WriteFloat(msg, sv.time);

            // add the client specific data to the datagram
            SV_WriteClientdataToMessage(client.edict, msg);

            SV_WriteEntitiesToClient(client.edict, msg);

            // copy the server datagram if there is space
            if (msg.cursize + sv.datagram.cursize < msg.maxsize)
            {
                common.SZ_Write(msg, sv.datagram.data, sv.datagram.cursize);
            }

            // send the datagram
            if (net.NET_SendUnreliableMessage(client.netconnection, msg) == -1)
            {
                return(false);
            }

            return(true);
        }
예제 #2
0
        /*
         * =======================
         * SV_SendNop
         *
         * Send a nop message without trashing or sending the accumulated client
         * message buffer
         * =======================
         */
        static void SV_SendNop(client_t client)
        {
            common.sizebuf_t msg = new common.sizebuf_t();
            byte[]           buf = new byte[4];

            msg.data    = buf;
            msg.maxsize = buf.Length;
            msg.cursize = 0;

            common.MSG_WriteChar(msg, net.svc_nop);

            net.NET_SendUnreliableMessage(client.netconnection, msg);
            client.last_message = host.realtime;
        }
예제 #3
0
        /*
         * ================
         * SV_SendReconnect
         *
         * Tell all the clients that the server is changing levels
         * ================
         */
        static void SV_SendReconnect()
        {
            byte[]           data = new byte[128];
            common.sizebuf_t msg  = new common.sizebuf_t();

            msg.data    = data;
            msg.cursize = 0;
            msg.maxsize = data.Length;

            common.MSG_WriteChar(msg, net.svc_stufftext);
            common.MSG_WriteString(msg, "reconnect\n");
            net.NET_SendToAll(msg, 5);

            if (client.cls.state != client.cactive_t.ca_dedicated)
            {
                quake.cmd.Cmd_ExecuteString("reconnect\n\0".ToCharArray(), quake.cmd.cmd_source_t.src_command);
            }
        }
예제 #4
0
        static int Loop_SendMessage(qsocket_t sock, common.sizebuf_t data)
        {
            byte[] buffer;
            int    ofs;
            int    bufferLength;

            if (sock.driverdata == null)
            {
                return(-1);
            }

            bufferLength = ((qsocket_t)sock.driverdata).receiveMessageLength;

            if ((bufferLength + data.cursize + 4) > NET_MAXMESSAGE)
            {
                sys_linux.Sys_Error("Loop_SendMessage: overflow\n");
            }

            buffer = ((qsocket_t)sock.driverdata).receiveMessage;
            ofs    = bufferLength;

            // message type
            buffer[ofs++] = 1;

            // length
            buffer[ofs++] = (byte)(data.cursize & 0xff);
            buffer[ofs++] = (byte)(data.cursize >> 8);

            // align
            ofs++;

            // message
            Buffer.BlockCopy(data.data, 0, buffer, ofs, data.cursize);
            ((qsocket_t)sock.driverdata).receiveMessageLength = IntAlign(bufferLength + data.cursize + 4);

            sock.canSend = false;
            return(1);
        }
예제 #5
0
        static int Loop_SendUnreliableMessage(qsocket_t sock, common.sizebuf_t data)
        {
            byte[] buffer;
            int    ofs;
            int    bufferLength;

            if (sock.driverdata == null)
            {
                return(-1);
            }

            bufferLength = ((qsocket_t)sock.driverdata).receiveMessageLength;

            if ((bufferLength + data.cursize + sizeof(byte) + sizeof(short)) > NET_MAXMESSAGE)
            {
                return(0);
            }

            buffer = ((qsocket_t)sock.driverdata).receiveMessage;
            ofs    = bufferLength;

            // message type
            buffer[ofs++] = 2;

            // length
            buffer[ofs++] = (byte)(data.cursize & 0xff);
            buffer[ofs++] = (byte)(data.cursize >> 8);

            // align
            ofs++;

            // message
            Buffer.BlockCopy(data.data, 0, buffer, ofs, data.cursize);
            ((qsocket_t)sock.driverdata).receiveMessageLength = IntAlign(bufferLength + data.cursize + 4);
            return(1);
        }
예제 #6
0
        static void CL_KeepaliveMessage()
        {
            double	            time;
            int		            ret;
            common.sizebuf_t	old = new common.sizebuf_t();
            byte[]		        olddata = new byte[8192];

            if (server.sv.active)
                return;		// no need if server is local
            if (client.cls.demoplayback)
                return;

            // read messages from server, should just be nops
            common.sizebuf_t.Copy(net.net_message, old);
            Buffer.BlockCopy(net.net_message.data, 0, olddata, 0, net.net_message.cursize);

            do
            {
                ret = CL_GetMessage ();
                switch (ret)
                {
                default:
                    host.Host_Error("CL_KeepaliveMessage: CL_GetMessage failed");
                    break;
                case 0:
                    break;	// nothing waiting
                case 1:
                    host.Host_Error("CL_KeepaliveMessage: received a message");
                    break;
                case 2:
                    if (common.MSG_ReadByte() != net.svc_nop)
                        host.Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
                    break;
                }
            } while (ret != 0);

            common.sizebuf_t.Copy(old, net.net_message);
            Buffer.BlockCopy(olddata, 0, net.net_message.data, 0, net.net_message.cursize);

            // check time
            time = sys_linux.Sys_FloatTime ();
            if (time - lastmsg < 5)
                return;
            lastmsg = time;

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

            common.MSG_WriteByte (cls.message, net.clc_nop);
            net.NET_SendMessage (cls.netcon, cls.message);
            common.SZ_Clear (cls.message);
        }
예제 #7
0
        /*
        ================
        SV_SendReconnect

        Tell all the clients that the server is changing levels
        ================
        */
        static void SV_SendReconnect()
        {
            byte[]              data = new byte[128];
            common.sizebuf_t	msg = new common.sizebuf_t();

            msg.data = data;
            msg.cursize = 0;
            msg.maxsize = data.Length;

            common.MSG_WriteChar (msg, net.svc_stufftext);
            common.MSG_WriteString (msg, "reconnect\n");
            net.NET_SendToAll (msg, 5);

            if (client.cls.state != client.cactive_t.ca_dedicated)
                quake.cmd.Cmd_ExecuteString("reconnect\n\0".ToCharArray(), quake.cmd.cmd_source_t.src_command);
        }
예제 #8
0
        /*
        =======================
        SV_SendNop

        Send a nop message without trashing or sending the accumulated client
        message buffer
        =======================
        */
        static void SV_SendNop(client_t client)
        {
            common.sizebuf_t	msg = new common.sizebuf_t();
            byte[]		        buf = new byte[4];

            msg.data = buf;
            msg.maxsize = buf.Length;
            msg.cursize = 0;

            common.MSG_WriteChar (msg, net.svc_nop);

            net.NET_SendUnreliableMessage (client.netconnection, msg);
            client.last_message = host.realtime;
        }
예제 #9
0
        /*
        =======================
        SV_SendClientDatagram
        =======================
        */
        static bool SV_SendClientDatagram(client_t client)
        {
            byte[]		        buf = new byte[quakedef.MAX_DATAGRAM];
            common.sizebuf_t    msg = new common.sizebuf_t();

            msg.data = buf;
            msg.maxsize = buf.Length;
            msg.cursize = 0;

            common.MSG_WriteByte (msg, net.svc_time);
            common.MSG_WriteFloat (msg, sv.time);

            // add the client specific data to the datagram
            SV_WriteClientdataToMessage(client.edict, msg);

            SV_WriteEntitiesToClient(client.edict, msg);

            // copy the server datagram if there is space
            if (msg.cursize + sv.datagram.cursize < msg.maxsize)
                common.SZ_Write(msg, sv.datagram.data, sv.datagram.cursize);

            // send the datagram
            if (net.NET_SendUnreliableMessage (client.netconnection, msg) == -1)
            {
                return false;
            }

            return true;
        }
예제 #10
0
        /*
         * ==================
         * SV_WriteClientdataToMessage
         *
         * ==================
         */
        public static void SV_WriteClientdataToMessage(prog.edict_t ent, common.sizebuf_t msg)
        {
            int bits;
            int i;

            prog.edict_t other;
            int          items;

            //
            // send a damage message
            //
            if (ent.v.dmg_take != 0 || ent.v.dmg_save != 0)
            {
                other = prog.PROG_TO_EDICT(ent.v.dmg_inflictor);
                common.MSG_WriteByte(msg, net.svc_damage);
                common.MSG_WriteByte(msg, (int)ent.v.dmg_save);
                common.MSG_WriteByte(msg, (int)ent.v.dmg_take);
                for (i = 0; i < 3; i++)
                {
                    common.MSG_WriteCoord(msg, other.v.origin[i] + 0.5 * (other.v.mins[i] + other.v.maxs[i]));
                }

                ent.v.dmg_take = 0;
                ent.v.dmg_save = 0;
            }

            //
            // send the current viewpos offset from the view entity
            //
            SV_SetIdealPitch();                 // how much to look up / down ideally

            // a fixangle might get lost in a dropped packet.  Oh well.
            if (ent.v.fixangle != 0)
            {
                common.MSG_WriteByte(msg, net.svc_setangle);
                for (i = 0; i < 3; i++)
                {
                    common.MSG_WriteAngle(msg, ent.v.angles[i]);
                }
                ent.v.fixangle = 0;
            }

            bits = 0;

            if (ent.v.view_ofs[2] != net.DEFAULT_VIEWHEIGHT)
            {
                bits |= net.SU_VIEWHEIGHT;
            }

            if (ent.v.idealpitch != 0)
            {
                bits |= net.SU_IDEALPITCH;
            }

            // stuff the sigil bits into the high bits of items for sbar, or else
            // mix in items2
            //val = GetEdictFieldValue(ent, "items2");

            /*if (val)
             *      items = (int)ent->v.items | ((int)val->_float << 23);
             * else*/
            items = (int)ent.v.items | ((int)prog.pr_global_struct[0].serverflags << 28);

            bits |= net.SU_ITEMS;

            if (((int)ent.v.flags & FL_ONGROUND) != 0)
            {
                bits |= net.SU_ONGROUND;
            }

            if (ent.v.waterlevel >= 2)
            {
                bits |= net.SU_INWATER;
            }

            for (i = 0; i < 3; i++)
            {
                if (ent.v.punchangle[i] != 0)
                {
                    bits |= (net.SU_PUNCH1 << i);
                }
                if (ent.v.velocity[i] != 0)
                {
                    bits |= (net.SU_VELOCITY1 << i);
                }
            }

            if (ent.v.weaponframe != 0)
            {
                bits |= net.SU_WEAPONFRAME;
            }

            if (ent.v.armorvalue != 0)
            {
                bits |= net.SU_ARMOR;
            }

            //	if (ent.v.weapon != 0)
            bits |= net.SU_WEAPON;

            // send the data

            common.MSG_WriteByte(msg, net.svc_clientdata);
            common.MSG_WriteShort(msg, bits);

            if ((bits & net.SU_VIEWHEIGHT) != 0)
            {
                common.MSG_WriteChar(msg, (int)ent.v.view_ofs[2]);
            }

            if ((bits & net.SU_IDEALPITCH) != 0)
            {
                common.MSG_WriteChar(msg, (int)ent.v.idealpitch);
            }

            for (i = 0; i < 3; i++)
            {
                if ((bits & (net.SU_PUNCH1 << i)) != 0)
                {
                    common.MSG_WriteChar(msg, (int)ent.v.punchangle[i]);
                }
                if ((bits & (net.SU_VELOCITY1 << i)) != 0)
                {
                    common.MSG_WriteChar(msg, (int)ent.v.velocity[i] / 16);
                }
            }

            // [always sent]	if (bits & SU_ITEMS)
            common.MSG_WriteLong(msg, items);

            if ((bits & net.SU_WEAPONFRAME) != 0)
            {
                common.MSG_WriteByte(msg, (int)ent.v.weaponframe);
            }
            if ((bits & net.SU_ARMOR) != 0)
            {
                common.MSG_WriteByte(msg, (int)ent.v.armorvalue);
            }
            if ((bits & net.SU_WEAPON) != 0)
            {
                common.MSG_WriteByte(msg, SV_ModelIndex(prog.pr_string(ent.v.weaponmodel)));
            }

            common.MSG_WriteShort(msg, (int)ent.v.health);
            common.MSG_WriteByte(msg, (int)ent.v.currentammo);
            common.MSG_WriteByte(msg, (int)ent.v.ammo_shells);
            common.MSG_WriteByte(msg, (int)ent.v.ammo_nails);
            common.MSG_WriteByte(msg, (int)ent.v.ammo_rockets);
            common.MSG_WriteByte(msg, (int)ent.v.ammo_cells);

            if (common.standard_quake)
            {
                common.MSG_WriteByte(msg, (int)ent.v.weapon);
            }
            else
            {
                for (i = 0; i < 32; i++)
                {
                    if ((((int)ent.v.weapon) & (1 << i)) != 0)
                    {
                        common.MSG_WriteByte(msg, i);
                        break;
                    }
                }
            }
        }
예제 #11
0
        /*
         * =============
         * SV_WriteEntitiesToClient
         *
         * =============
         */
        static void SV_WriteEntitiesToClient(prog.edict_t clent, common.sizebuf_t msg)
        {
            int e, i;
            int bits;

            double[] org = new double[3];
            double   miss;

            prog.edict_t ent;

            // send over all entities (excpet the client) that touch the pvs
            for (e = 1; e < sv.num_edicts; e++)
            {
                ent = sv.edicts[e];

                // ignore if not touching a PV leaf
                if (ent != clent)               // clent is ALLWAYS sent
                {
                    // ignore ents without visible models
                    if (ent.v.modelindex == 0 || prog.pr_string(ent.v.model) == null)
                    {
                        continue;
                    }
                }

                if (msg.maxsize - msg.cursize < 16)
                {
                    console.Con_Printf("packet overflow\n");
                    return;
                }

                // send an update
                bits = 0;

                for (i = 0; i < 3; i++)
                {
                    miss = ent.v.origin[i] - ent.baseline.origin[i];
                    if (miss < -0.1 || miss > 0.1)
                    {
                        bits |= net.U_ORIGIN1 << i;
                    }
                }

                if (ent.v.angles[0] != ent.baseline.angles[0])
                {
                    bits |= net.U_ANGLE1;
                }

                if (ent.v.angles[1] != ent.baseline.angles[1])
                {
                    bits |= net.U_ANGLE2;
                }

                if (ent.v.angles[2] != ent.baseline.angles[2])
                {
                    bits |= net.U_ANGLE3;
                }

                if (ent.v.movetype == MOVETYPE_STEP)
                {
                    bits |= net.U_NOLERP;       // don't mess up the step animation
                }
                if (ent.baseline.colormap != ent.v.colormap)
                {
                    bits |= net.U_COLORMAP;
                }

                if (ent.baseline.skin != ent.v.skin)
                {
                    bits |= net.U_SKIN;
                }

                if (ent.baseline.frame != ent.v.frame)
                {
                    bits |= net.U_FRAME;
                }

                if (ent.baseline.effects != ent.v.effects)
                {
                    bits |= net.U_EFFECTS;
                }

                if (ent.baseline.modelindex != ent.v.modelindex)
                {
                    bits |= net.U_MODEL;
                }

                if (e >= 256)
                {
                    bits |= net.U_LONGENTITY;
                }

                if (bits >= 256)
                {
                    bits |= net.U_MOREBITS;
                }

                //
                // write the message
                //
                common.MSG_WriteByte(msg, bits | net.U_SIGNAL);

                if ((bits & net.U_MOREBITS) != 0)
                {
                    common.MSG_WriteByte(msg, bits >> 8);
                }
                if ((bits & net.U_LONGENTITY) != 0)
                {
                    common.MSG_WriteShort(msg, e);
                }
                else
                {
                    common.MSG_WriteByte(msg, e);
                }

                if ((bits & net.U_MODEL) != 0)
                {
                    common.MSG_WriteByte(msg, (int)ent.v.modelindex);
                }
                if ((bits & net.U_FRAME) != 0)
                {
                    common.MSG_WriteByte(msg, (int)ent.v.frame);
                }
                if ((bits & net.U_COLORMAP) != 0)
                {
                    common.MSG_WriteByte(msg, (int)ent.v.colormap);
                }
                if ((bits & net.U_SKIN) != 0)
                {
                    common.MSG_WriteByte(msg, (int)ent.v.skin);
                }
                if ((bits & net.U_EFFECTS) != 0)
                {
                    common.MSG_WriteByte(msg, (int)ent.v.effects);
                }
                if ((bits & net.U_ORIGIN1) != 0)
                {
                    common.MSG_WriteCoord(msg, ent.v.origin[0]);
                }
                if ((bits & net.U_ANGLE1) != 0)
                {
                    common.MSG_WriteAngle(msg, ent.v.angles[0]);
                }
                if ((bits & net.U_ORIGIN2) != 0)
                {
                    common.MSG_WriteCoord(msg, ent.v.origin[1]);
                }
                if ((bits & net.U_ANGLE2) != 0)
                {
                    common.MSG_WriteAngle(msg, ent.v.angles[1]);
                }
                if ((bits & net.U_ORIGIN3) != 0)
                {
                    common.MSG_WriteCoord(msg, ent.v.origin[2]);
                }
                if ((bits & net.U_ANGLE3) != 0)
                {
                    common.MSG_WriteAngle(msg, ent.v.angles[2]);
                }
            }
        }
예제 #12
0
        /*
        =======================
        SV_SendNop

        Send a nop message without trashing or sending the accumulated client
        message buffer
        =======================
        */
        static void SV_SendNop(client_t client)
        {
            common.sizebuf_t	msg = new common.sizebuf_t();
            Uint8Array          buf = new Uint8Array(4);

            msg.data = buf;
            msg.maxsize = buf.Length;
            msg.cursize = 0;

            common.MSG_WriteChar (msg, net.svc_nop);

            if (net.NET_SendUnreliableMessage(client.netconnection, msg) == -1)
                host.SV_DropClient(true);	// if the message couldn't send, kick off

            client.last_message = host.realtime;
        }
예제 #13
0
        static void CL_KeepaliveMessage()
        {
            double time;
            int    ret;

            common.sizebuf_t old     = new common.sizebuf_t();
            byte[]           olddata = new byte[8192];

            if (server.sv.active)
            {
                return;         // no need if server is local
            }
            if (client.cls.demoplayback)
            {
                return;
            }

            // read messages from server, should just be nops
            common.sizebuf_t.Copy(net.net_message, old);
            Buffer.BlockCopy(net.net_message.data, 0, olddata, 0, net.net_message.cursize);

            do
            {
                ret = CL_GetMessage();
                switch (ret)
                {
                default:
                    host.Host_Error("CL_KeepaliveMessage: CL_GetMessage failed");
                    break;

                case 0:
                    break;              // nothing waiting

                case 1:
                    host.Host_Error("CL_KeepaliveMessage: received a message");
                    break;

                case 2:
                    if (common.MSG_ReadByte() != net.svc_nop)
                    {
                        host.Host_Error("CL_KeepaliveMessage: datagram wasn't a nop");
                    }
                    break;
                }
            } while (ret != 0);

            common.sizebuf_t.Copy(old, net.net_message);
            Buffer.BlockCopy(olddata, 0, net.net_message.data, 0, net.net_message.cursize);

            // check time
            time = sys_linux.Sys_FloatTime();
            if (time - lastmsg < 5)
            {
                return;
            }
            lastmsg = time;

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

            common.MSG_WriteByte(cls.message, net.clc_nop);
            net.NET_SendMessage(cls.netcon, cls.message);
            common.SZ_Clear(cls.message);
        }