public static int ReadInt(UdpKit.UdpStream stream, int minValue = int.MinValue, int maxValue = int.MaxValue)
    {
        int reqBit = (int)RequiredBits(minValue, maxValue);

        //Debug.Log("ReadInt: required bits:" + reqBit);
        return(stream.ReadInt(reqBit) + minValue);
    }
Beispiel #2
0
        internal void SendCommand(UdpCommandType cmd)
        {
            if (CheckCanSend(true) == UdpSendFailReason.None)
            {
                UdpStream stream = socket.GetWriteStream(mtu << 3, UdpSocket.HeaderBitSize);
                stream.WriteByte((byte)cmd, 8);

                UdpHeader header = MakeHeader(false);
                header.Pack(stream, socket);

                UdpHandle handle = MakeHandle(ref header);
                handle.Object = null;

                if (SendStream(stream, handle, false))
                {
                    // track stats
                    stats.PacketSent((uint)stream.Ptr >> 3);
                    socket.Stats.PacketSent((uint)stream.Ptr >> 3);
                }
                else
                {
                    // should we do something here?????
                }
            }
        }
    //callback from SteamClient. Read the data and decide how to process it.
    public void ReceiveP2PData(ulong steamID, byte[] bytes, int length, int channel)
    {
        readStream = new UdpKit.UdpStream(bytes, length);
        //Debug.Log("rec message");
        //string s = stream.ReadString();
        while (readStream.CanRead() && readStream.CanRead(8))
        {
            int msgCode = (int)SerializerUtils.ReadInt(readStream, 0, 255);
            //Debug.Log("[REC] MessageCode: " + msgCode);
            if (msgCode == GetMessageCode("Empty"))
            {
                break; //no more data, the rest of this packet is junk
            }

            if (MessageDeserializers[msgCode] != null)
            {
                MessageDeserializers[msgCode](steamID, msgCode, readStream);
                //entity messages deserialize is called internally (MessageCodes.SpawnPrefab.Deserialize  calles entity.Deserialize)
            }
            else
            {
                MessageProcessors[msgCode](steamID); //process is usually called within the deserializer, but since we have no deserializer (because we have no data, just a msgCode), call it here.
            }
        }
    }
Beispiel #4
0
        public UdpStream Acquire()
        {
            UdpStream stream = null;

            lock (pool) {
                if (pool.Count > 0)
                {
                    stream = pool.Pop();
                }
            }

            if (stream == null)
            {
                stream      = new UdpStream(new byte[PacketSize * 2]);
                stream.Pool = this;
            }

            UdpAssert.Assert(stream.IsPooled);

            stream.IsPooled = false;
            stream.Position = 0;
            //stream.Size = (PacketSize - UdpMath.BytesRequired(UdpSocket.HeaderBitSize)) << 3;
            stream.Size = (PacketSize - 0) << 3; //we're not using this for it's intended purpose,
            //just hijacking it to use it's bitpacking methods.

            return(stream);
        }
Beispiel #5
0
        void RecvUnconnectedPacket(UdpStream buffer, UdpEndPoint ep)
        {
            UdpAssert.Assert(buffer.Ptr == 0);
            buffer.Ptr = HeaderBitSize;

            if (buffer.ReadByte(8) == (byte)UdpCommandType.Connect)
            {
                if (Config.AllowIncommingConnections && ((connLookup.Count + pendingConnections.Count) < Config.ConnectionLimit || Config.ConnectionLimit == -1))
                {
                    if (Config.AutoAcceptIncommingConnections)
                    {
                        AcceptConnection(ep, null);
                    }
                    else
                    {
                        if (pendingConnections.Add(ep))
                        {
                            object obj = null;
                            if (buffer.ReadByte(8) == UdpEvent.INTERNAL_COMMAND_HASOBJECT)
                            {
                                //they've also sent an object along with their connection request
                                serializer.Unpack(buffer, ref obj);
                            }
                            Raise(UdpEvent.PUBLIC_CONNECT_REQUEST, ep, obj);
                        }
                    }
                }
                else
                {
                    SendRefusedCommand(ep);
                }
            }
        }
Beispiel #6
0
    //callback from SteamClient. Read the data and decide how to process it.
    public void ReceiveP2PData(ulong steamID, byte[] bytes, int length, int channel)
    {
        readStream = new UdpKit.UdpStream(bytes, length);
        //Debug.Log("rec message");
        //string s = stream.ReadString();
        while (readStream.CanRead() && readStream.CanRead(SerializerUtils.RequiredBitsInt(0, maxMessageTypes)))
        {
            int msgCode = (int)SerializerUtils.ReadInt(readStream, 0, maxMessageTypes);
            //Debug.Log("[REC] MessageCode: " + msgCode);
            if (msgCode == GetMessageCode("Empty"))
            {
                AddToBandwidthInBuffer(-8);
                break; //no more data, the rest of this packet is junk
            }
            //can we ignore all state data here if we're not in the same zone?
            //we don't know what kind of entity it's from..so...
            //maybe all zoneless data should just go through events?
            //or we can check the prefab to find out if it's zoneless?

            if (MessageDeserializers[msgCode] != null)
            {
                MessageDeserializers[msgCode](steamID, msgCode, readStream);
                //entity messages deserialize is called internally (MessageCodes.SpawnPrefab.Deserialize  calles entity.Deserialize)
            }
            else
            {
                MessageProcessors[msgCode](steamID); //process is usually called within the deserializer, but since we have no deserializer (because we have no data, just a msgCode), call it here.
            }
        }
    }
        void RecvNetworkData()
        {
            if (platform.RecvPoll(1))
            {
                int         bytes  = 0;
                UdpEndPoint ep     = UdpEndPoint.Any;
                UdpStream   stream = GetReadStream();

                if (platform.RecvFrom(stream.Data, stream.Data.Length, ref bytes, ref ep))
                {
                    //UdpLog.Debug("received packet from {0}", ep.ToString());

#if DEBUG
                    if (ShouldDropPacket)
                    {
                        return;
                    }

                    if (ShouldDelayPacket)
                    {
                        DelayPacket(ep, stream.Data, bytes);
                        return;
                    }
#endif

                    RecvNetworkPacket(ep, stream, bytes);
                }
            }
        }
        UdpSocket(UdpPlatform platform, UdpSerializerFactory serializerFactory, UdpConfig config)
        {
            this.platform          = platform;
            this.serializerFactory = serializerFactory;
            this.Config            = config.Duplicate();
            this.configCopy        = config;

            state          = UdpSocketState.Created;
            random         = new System.Random();
            stats          = new UdpStats();
            availableEvent = new AutoResetEvent(false);

            if (this.Config.NoiseFunction == null)
            {
                this.Config.NoiseFunction = delegate() { return((float)random.NextDouble()); };
            }

            readStream  = new UdpStream(new byte[config.PacketSize * 2]);
            writeStream = new UdpStream(new byte[config.PacketSize * 2]);
            streamPool  = new UdpStreamPool(this);

            eventQueueIn  = new Queue <UdpEvent>(config.InitialEventQueueSize);
            eventQueueOut = new Queue <UdpEvent>(config.InitialEventQueueSize);

            threadSocket              = new Thread(NetworkLoop);
            threadSocket.Name         = "udpkit thread";
            threadSocket.IsBackground = true;
            threadSocket.Start();
        }
Beispiel #9
0
        void RecvNetworkData()
        {
            if (platform.RecvPoll(1))
            {
                int         bytes  = 0;
                UdpEndPoint ep     = UdpEndPoint.Any;
                UdpStream   stream = GetReadStream();

                if (platform.RecvFrom(stream.Data, stream.Data.Length, ref bytes, ref ep))
                {
#if DEBUG
                    if (ShouldDropPacket)
                    {
                        return;
                    }

                    if (ShouldDelayPacket)
                    {
                        DelayPacket(ep, stream.Data, bytes);
                        return;
                    }
#endif

                    RecvNetworkPacket(ep, stream, bytes);
                }
            }
        }
        public UdpStream Acquire()
        {
            UdpStream stream = null;

            lock (pool) {
                if (pool.Count > 0)
                {
                    stream = pool.Pop();
                }
            }

            if (stream == null)
            {
                stream      = new UdpStream(new byte[socket.Config.PacketSize * 2]);
                stream.Pool = this;
            }

            UdpAssert.Assert(stream.IsPooled);

            stream.IsPooled = false;
            stream.Position = 0;
            stream.Size     = (socket.Config.PacketSize - UdpMath.BytesRequired(UdpSocket.HeaderBitSize)) << 3;

            return(stream);
        }
        void RecvUnconnectedPacket(UdpStream buffer, UdpEndPoint ep)
        {
            UdpAssert.Assert(buffer.Ptr == 0);
            buffer.Ptr = HeaderBitSize;

            if (buffer.ReadByte(8) == (byte)UdpCommandType.Connect)
            {
                if (Config.AllowIncommingConnections && ((connLookup.Count + pendingConnections.Count) < Config.ConnectionLimit || Config.ConnectionLimit == -1))
                {
                    if (Config.AutoAcceptIncommingConnections)
                    {
                        AcceptConnection(ep);
                    }
                    else
                    {
                        if (pendingConnections.Add(ep))
                        {
                            Raise(UdpEvent.PUBLIC_CONNECT_REQUEST, ep);
                        }
                    }
                }
                else
                {
                    SendRefusedCommand(ep);
                }
            }
        }
        internal void SendObject(object o)
        {
            serializer.SendNext(o);

            while (serializer.HasQueuedObjects)
            {
                UdpSendFailReason reason = CheckCanSend(false);

                if (reason != UdpSendFailReason.None)
                {
                    while (serializer.HasQueuedObjects)
                    {
                        socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, serializer.NextObject(), reason);
                    }

                    break;
                }

                UdpStream stream = socket.GetWriteStream(mtu << 3, UdpSocket.HeaderBitSize);
                object    obj    = serializer.NextObject();

                if (serializer.Pack(stream, ref obj))
                {
                    if (stream.Overflowing && (socket.Config.AllowPacketOverflow == false))
                    {
                        UdpLog.Error("stream to {0} is overflowing, not sending", endpoint.ToString());
                        socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, obj, UdpSendFailReason.StreamOverflow);
                        return;
                    }

                    UdpHeader header = MakeHeader(true);
                    header.Pack(stream, socket);

                    UdpHandle handle = MakeHandle(ref header);
                    handle.Object = obj;

                    if (SendStream(stream, handle, alwaysSendMtu))
                    {
                        // track stats
                        stats.PacketSent((uint)stream.Ptr >> 3);
                        socket.Statistics.PacketSent((uint)stream.Ptr >> 3);

                        // push object to user thread
                        socket.Raise(UdpEvent.PUBLIC_OBJECT_SENT, this, obj);
                        Log.info(this, "SendObject##UdpSocket.HeaderBitSize: " + (UdpSocket.HeaderBitSize >> 3));
                        Log.info(this, "SendObject##size: " + (stream.Ptr >> 3));
                    }
                    else
                    {
                        socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, obj, UdpSendFailReason.SocketError);
                    }
                }
                else
                {
                    socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, obj, UdpSendFailReason.SerializerReturnedFalse);
                }
            }
        }
Beispiel #13
0
        void OnCommandDisconnected(UdpStream buffer)
        {
            EnsureClientIsConnected();

            if (CheckState(UdpConnectionState.Connected))
            {
                ChangeState(UdpConnectionState.Disconnected);
            }
        }
Beispiel #14
0
    //don't need a custom range for bools, because they are always one bit

    //uses smallest three compression in the range of [-10, 10] by default.
    //can't change the range as a quaterion is always [-1, 1] technically, but we can change the precision.
    public static void WriteQuaterinion(UdpKit.UdpStream stream, Quaternion rotation, float precision = 0.0000001f)
    {
        //find the index with the largest abs value
        int   largestIndex = 0;
        float v            = rotation[0];

        for (int i = 1; i < 4; i++)
        {
            if (Mathf.Abs(rotation[i]) > v)
            {
                v            = rotation[i];
                largestIndex = i;
            }
        }

        //Debug.Log("largest index write: " + largestIndex + " v: " + v);
        WriteInt(stream, largestIndex, 0, 3);
        float sign = (rotation[largestIndex] < 0) ? -1 : 1;

        //if(Mathf.Approximately(rotation[largestIndex], 1f)) {
        //    //write one bit as true
        //    //because we know if any component is 1, everything else is 0 so don't bother even sending.
        //    //in *most* cases this is an extra bit as this isn't true often I imagine, so maybe it's not worth it
        //    //to save one bit infrequently, while having to send one bit more often.
        //} else {
        //    //write one bit as false
        //}

        switch (largestIndex)
        {
        case 0:
            WriteFloat(stream, rotation[1] * sign, -1f, 1f, precision);
            WriteFloat(stream, rotation[2] * sign, -1f, 1f, precision);
            WriteFloat(stream, rotation[3] * sign, -1f, 1f, precision);
            break;

        case 1:
            WriteFloat(stream, rotation[0] * sign, -1f, 1f, precision);
            WriteFloat(stream, rotation[2] * sign, -1f, 1f, precision);
            WriteFloat(stream, rotation[3] * sign, -1f, 1f, precision);
            break;

        case 2:
            WriteFloat(stream, rotation[0] * sign, -1f, 1f, precision);
            WriteFloat(stream, rotation[1] * sign, -1f, 1f, precision);
            WriteFloat(stream, rotation[3] * sign, -1f, 1f, precision);
            break;

        case 3:
            WriteFloat(stream, rotation[0] * sign, -1f, 1f, precision);
            WriteFloat(stream, rotation[1] * sign, -1f, 1f, precision);
            WriteFloat(stream, rotation[2] * sign, -1f, 1f, precision);
            break;
        }
    }
    public static float ReadFloat(UdpKit.UdpStream stream, float minValue = float.MinValue, float maxValue = float.MaxValue, float precision = 0.0000001f)
    {
        int intMax = (int)((maxValue - minValue + precision) * (1f / precision));
        //Debug.Log("read intMax: " + intMax);
        int   intVal = ReadInt(stream, 0, intMax);
        float value  = (intVal * precision) + minValue;

        //need to clean it up because sometimes we're getting 1.000001 with 0.1 prec, so fix that
        value = Mathf.Round((value) * (1f / precision)) * precision;
        return(value);
    }
Beispiel #16
0
        internal void Release(UdpStream stream)
        {
            UdpAssert.Assert(stream.IsPooled == false);

            lock (pool) {
                stream.Size     = 0;
                stream.Position = 0;
                stream.IsPooled = true;

                pool.Push(stream);
            }
        }
Beispiel #17
0
        public void Unpack(UdpStream buffer, UdpSocket socket)
        {
            buffer.Position = 0;

            ObjSequence = TrimSequence((ushort)IPAddress.NetworkToHostOrder((short)buffer.ReadUShort(SEQ_BITS + SEQ_PADD)));
            AckSequence = TrimSequence((ushort)IPAddress.NetworkToHostOrder((short)buffer.ReadUShort(SEQ_BITS + SEQ_PADD)));
            AckHistory  = (ulong)IPAddress.NetworkToHostOrder((long)buffer.ReadULong(UdpSocket.AckRedundancy));

            if (UdpSocket.CalculateNetworkPing)
            {
                AckTime = (ushort)IPAddress.NetworkToHostOrder((short)buffer.ReadUShort(NETPING_BITS));
            }
        }
Beispiel #18
0
 void OnCommandConnect(UdpStream buffer)
 {
     if (IsServer)
     {
         if (CheckState(UdpConnectionState.Connected))
         {
             SendCommand(UdpCommandType.Accepted);
         }
     }
     else
     {
         ConnectionError(UdpConnectionError.IncorrectCommand);
     }
 }
Beispiel #19
0
 void OnCommandAccepted(UdpStream buffer)
 {
     if (IsClient)
     {
         if (CheckState(UdpConnectionState.Connecting))
         {
             ChangeState(UdpConnectionState.Connected);
         }
     }
     else
     {
         ConnectionError(UdpConnectionError.IncorrectCommand);
     }
 }
    //values outside the specified range will be clamped
    //shifts values into positive range so we don't have to send a sign bit
    //eg, [-4, 4] range and value of 0 gets shifted to
    // [0, 8] range and a value of 4
    //then we reverse it on the other side
    public static void WriteInt(UdpKit.UdpStream stream, int value, int minValue = int.MinValue, int maxValue = int.MaxValue)
    {
        int reqBit = (int)RequiredBits(minValue, maxValue);

        //Debug.Log("WriteInt: " + value + " : requiredBits : " + reqBit);
        if (value < minValue || value > maxValue)
        {
            Debug.Log($"Value [{value}] is outside of range [{minValue}, {maxValue}] and will be clamped");
        }

        value = Mathf.Clamp(value, minValue, maxValue);
        value = value - minValue;

        stream.WriteInt(value, reqBit);
    }
    //state serialize, deserialize, no process, as it goes in the entity state, peek, priority calculator
    //public delegate int StatePeeker(params object[] args);
    //public delegate void StateSerializer(ulong receiver, ByteStream stream, int prefabId, int networkId, int owner, int controller, int stateCode, params object[] args);
    //public delegate void StateDeserializer(ulong sender, ByteStream stream, int prefabId, int networkid, int owner, int controller, int stateCode);
    //public delegate float StatePriorityCalculator(ulong receiver, int prefabId, int networkId, int owner, int controller, int stateCode, params object[] args);

    //public List<string> StateCodes = new List<string>();
    //public List<StateSerializer> StateSerializers = new List<StateSerializer>();
    //public List<StateDeserializer> StateDeserializers = new List<StateDeserializer>();
    //public List<StatePeeker> StatePeekers = new List<StatePeeker>();
    //public List<StatePriorityCalculator> StatePriorityCalculators = new List<StatePriorityCalculator>();


    //STATES
    //need a priority to decide if we should or should not send them (based on some filter)
    //needs a way to update queued messages with the most recent data right before they go out. (not important for now, but would be nice, no reason to queue two messages, only need the one with the latest data (unless we need it for interpolation?) idk
    //needs a peek, serialize and deserialize, to inject into the pack sequence if it's a state update (for custom data)
    //should states be defined when we SpawnPrefab? When we register prefab? When we spawm prefab internally on the behaviour script? (eg, state = Core.net.GetState("CubeBehaviour"));
    //maybe we could register states automatically when registering prefabs? search for a attached NetworkGameObject, and add it by script name?
    //then can always add extra states after, too..
    //that sounds like the proper way to do it.  As states are ALWAYS tied to an entity, no need to register/manage them manually I guess
    //Do I even need any of thsese then? or can I just call the methods directly on the object?
    //A registered prefab will ALWAYS have the same state, so just assume it has the right one on it, and call the internal methods?
    //remove the idea of states entirely and don't register them

    //we need a priority system.  Every time a message in the queue is skipped we
    //should we define a "Priority" Message delegate, that we can call to calculate the priority
    //would need one for normal messages, and one for state replicate/entity events?
    //state messages should be cleared from the queue if they sit there too long
    //or maybe they can be replaced/updated or something with the "latest" data

    void Awake()
    {
        DontDestroyOnLoad(this.gameObject);
        instance = this;
        Core.net = this;

        networkSimulationTimer = (1f / 60f) * (60f / networkSimulationRate);
        //register internal message types
        //RegisterInternalMessages.Register(); //to tidy it up, moved all this stuff to a nother class

        readStream  = new ByteStream(new byte[packetSize]); //max packet size 1024 bytes? (not sure why x2, but that's how udpkit did it)
        writeStream = new ByteStream(new byte[packetSize]);

        RegisterMessageType("Empty", null, null, null, null, null); //added to the end of the packet so we don't read to the end if we don't have to.
        RegisterMessageType("ConnectRequest",
                            null,
                            null,
                            null,
                            null,
                            MessageCode.ConnectRequest.Process);

        RegisterMessageType("ConnectRequestResponse",
                            MessageCode.ConnectRequestResponse.Peek,
                            null, //doesn't need a priority because this can not be queued, because it's sent before the connection is established
                            MessageCode.ConnectRequestResponse.Serialize,
                            MessageCode.ConnectRequestResponse.Deserialize,
                            MessageCode.ConnectRequestResponse.Process);

        RegisterMessageType("TestState",
                            MessageCode.TestState.Peek,
                            MessageCode.TestState.Priority,
                            MessageCode.TestState.Serialize,
                            MessageCode.TestState.Deserialize,
                            MessageCode.TestState.Process);

        RegisterMessageType("StateUpdate",
                            MessageCode.StateUpdate.Peek,
                            MessageCode.StateUpdate.Priority,
                            MessageCode.StateUpdate.Serialize,
                            MessageCode.StateUpdate.Deserialize,
                            MessageCode.StateUpdate.Process);


        for (int i = 0; i < registerPrefabsOnStart.Count; i++)
        {
            RegisterPrefab(registerPrefabsOnStart[i].gameObject.name, registerPrefabsOnStart[i]);
        }
    }
Beispiel #22
0
        bool SendStream(UdpStream stream, UdpHandle handle, bool expandToMtu)
        {
            int bytesToSend = UdpMath.BytesRequired(stream.Ptr);

            if (bytesToSend < mtu && expandToMtu)
            {
                bytesToSend = mtu;
            }

            sendTime     = handle.SendTime;
            sendSequence = handle.ObjSequence;
            sendWindow.Enqueue(handle);
            recvSinceLastSend = 0;

            return(socket.Send(endpoint, stream.Data, bytesToSend));
        }
Beispiel #23
0
        void OnCommandRefused(UdpStream buffer)
        {
            if (IsClient)
            {
                if (CheckState(UdpConnectionState.Connecting))
                {
                    socket.Raise(UdpEvent.PUBLIC_CONNECT_REFUSED, endpoint);

                    // destroy this connection on next timeout check
                    ChangeState(UdpConnectionState.Destroy);
                }
            }
            else
            {
                ConnectionError(UdpConnectionError.IncorrectCommand);
            }
        }
Beispiel #24
0
        bool ParseHeader(UdpStream stream)
        {
            // we should always start at ptr 0
            UdpAssert.Assert(stream.Ptr == 0);

            UdpHeader header = new UdpHeader();

            header.Unpack(stream, socket);

            // after unpacking the header, the pointer should be at the header size
            UdpAssert.Assert(stream.Ptr == UdpSocket.HeaderBitSize);

            int seqDistance = UdpMath.SeqDistance(header.ObjSequence, recvSequence, UdpHeader.SEQ_PADD);

            // we have to be within window size
            if (seqDistance > socket.Config.PacketWindow || seqDistance < -socket.Config.PacketWindow)
            {
                ConnectionError(UdpConnectionError.SequenceOutOfBounds);
                return(false);
            }

            // this is an old packet
            if (seqDistance <= 0)
            {
                return(false);
            }

            // update receive history
            if (seqDistance >= UdpSocket.AckRedundancy)
            {
                recvHistory = 1UL;
            }
            else
            {
                recvHistory = (recvHistory << seqDistance) | 1UL;
            }

            // update our receive stats
            recvSequence       = header.ObjSequence;
            recvSinceLastSend += 1;

            // ack sent objects
            AckHandles(header, true);

            return(true);
        }
Beispiel #25
0
        internal void OnPacket(UdpStream buffer)
        {
            // track stats
            stats.PacketReceived((uint)buffer.Length >> 3);
            socket.Stats.PacketReceived((uint)buffer.Length >> 3);

            // set recv time of for last packet
            recvTime = socket.GetCurrentTime();

            if ((buffer.Data[0] & 1) == 1)
            {
                OnObjectReceived(buffer);
            }
            else
            {
                OnCommandReceived(buffer);
            }
        }
        void RecvNetworkPacket(UdpEndPoint ep, UdpStream stream, int bytes)
        {
            // set stream length
            stream.Length = bytes << 3;

            // try to grab connection
            UdpConnection cn;

            if (connLookup.TryGetValue(ep, out cn))
            {
                // deliver to connection
                cn.OnPacket(stream);
            }
            else
            {
                // handle unconnected data
                RecvUnconnectedPacket(stream, ep);
            }
        }
Beispiel #27
0
        public void Pack(UdpStream buffer, UdpSocket socket)
        {
            int pos = buffer.Position;

            buffer.Position = 0;
            buffer.WriteUShort((ushort)IPAddress.HostToNetworkOrder((short)PadSequence(ObjSequence)), SEQ_BITS + SEQ_PADD);
            buffer.WriteUShort((ushort)IPAddress.HostToNetworkOrder((short)PadSequence(AckSequence)), SEQ_BITS + SEQ_PADD);
            buffer.WriteULong((ulong)IPAddress.HostToNetworkOrder((long)AckHistory), UdpSocket.AckRedundancy);

            if (UdpSocket.CalculateNetworkPing)
            {
                buffer.WriteUShort((ushort)IPAddress.HostToNetworkOrder((short)AckTime), NETPING_BITS);
            }

            buffer.Position = pos;
#if UNITY_EDITOR
            Log.info(this, "UdpHeader##Pack#ObjSequence: " + PadSequence(ObjSequence) + ":AckSequence: " + PadSequence(AckSequence));
#endif
        }
    ///precision is how many digits after decimal. Max is 7 (0.0000001)
    ///precision of 1 (1.1)
    ///2 (1.01)
    ///3 (1.001), etc.
    ///Lower precision means fewer bits to send
    public static void WriteFloat(UdpKit.UdpStream stream, float value, float minValue = float.MinValue, float maxValue = float.MaxValue, float precision = 0.0000001f)
    {
        //what is our int max value do we have from (min -> max ) with precision
        //[0->1] with 0.1 precision means
        //[0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
        //[0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10]
        //max value is 10!

        //[-1 ->1] with 0.1 prec
        //[-1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
        //lets push it to a pos rage.
        //[ 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0]
        //[   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,  19,  20]
        if (value < minValue || value > maxValue)
        {
            Debug.Log($"Value [{value}] is outside of range [{minValue}, {maxValue}] and will be clamped");
        }
        value = Mathf.Clamp(value, minValue, maxValue);

        int intMax = (int)((maxValue - minValue + precision) * (1f / precision)); //10
        //Debug.Log("intMax: " + intMax);
        //don't round, just remove values past precision
        //if we passed in 0.4524, we should use the value 0.4 (precision 0.1)
        //and that should be int value of 4
        bool neg = (value < 0);

        value = value - minValue;
        //Debug.Log("offset value: " + value);
        if (!neg)
        {
            value = Mathf.Floor(value * (1 / precision)) * precision; //converts 0.452 to 0.4.
        }
        else
        {
            value = Mathf.Ceil(value * (1 / precision)) * precision; //converts 0.452 to 0.4.
        }
        //Debug.Log("Rounded value: " + value);
        float intVal = ((value) * (1f / precision)); //1.4 should be 14

        //Debug.Log("IntVal: " + intVal);
        //compress values [0->11]
        WriteInt(stream, (int)intVal, 0, intMax);
    }
Beispiel #29
0
    public static Quaternion ReadQuaternion(UdpKit.UdpStream stream, float precision = 0.0000001f)
    {
        float x = 0f;
        float y = 0f;
        float z = 0f;
        float w = 0f;

        int largestIndex = ReadInt(stream, 0, 3);
        //Debug.Log("read largestIndex: " + largestIndex);
        //largestIndex needs to be calculated
        float a = ReadFloat(stream, -1f, 1f, precision);
        float b = ReadFloat(stream, -1f, 1f, precision);
        float c = ReadFloat(stream, -1f, 1f, precision);

        float d = Mathf.Sqrt(1f - ((a * a) + (b * b) + (c * c))); //largest

        //Debug.Log(a + " : " + b + " : " + c + " : " + d);

        switch (largestIndex)
        {
        case 0:
            return(new Quaternion(d, a, b, c));

            break;

        case 1:
            return(new Quaternion(a, d, b, c));

            break;

        case 2:
            return(new Quaternion(a, b, d, c));

            break;

        case 3:
            return(new Quaternion(a, b, c, d));

            break;
        }

        return(new Quaternion(0f, 0f, 0f, 1f));
    }
        void SendRefusedCommand(UdpEndPoint endpoint)
        {
            UdpStream stream = GetWriteStream(Config.PacketSize << 3, HeaderBitSize);

            stream.WriteByte((byte)UdpCommandType.Refused, 8);

            UdpHeader header = new UdpHeader();

            header.IsObject    = false;
            header.AckHistory  = 0;
            header.AckSequence = 1;
            header.ObjSequence = 1;
            header.Now         = 0;
            header.Pack(stream, this);

            if (Send(endpoint, stream.Data, UdpMath.BytesRequired(stream.Ptr)) == false)
            {
                // do something here?
            }
        }