Exemple #1
0
        /// <summary>
        /// Processes the packet.
        /// </summary>
        /// <param name="evt">Evt.</param>
        private void ProcessPacket(Event evt)
        {
            byte[] data = new byte[1024 + 4];
            evt.Packet.CopyTo(data);

            BitBuffer buffer = new BitBuffer(128);

            buffer.FromArray(data, evt.Packet.Length);

            OpCodes op = (OpCodes)buffer.ReadInt();
            uint    id = buffer.ReadUInt();

            if (DEBUG)
            {
                Console.WriteLine($"OPCODE: {op.ToString()}");
                Console.WriteLine($"PEERID: {id.ToString()}");
            }

            if (evt.Peer.ID != id)
            {
                Console.WriteLine($"ID Mismatch! {evt.Peer.ID} vs. {id}");
                return;
            }

            Packet packet = evt.Packet;

            switch (op)
            {
            case OpCodes.PlayerLogin:
                //Answer OK
                SendToSingleClient(CreateAnswerPacketLogin("OK", evt.Peer.ID), evt.Peer.ID);
                break;
            }
        }
        static void WebServerOnData(int id, ArraySegment <byte> data)
        {
            _bitBuffer.Clear();
            _bitBuffer.FromArray(data.Array, data.Count);

            byte messageId = _bitBuffer.ReadByte();

            switch (messageId)
            {
            case 1:
            {
                uint qX = _bitBuffer.ReadUInt();
                uint qY = _bitBuffer.ReadUInt();

                PlayerData playerData = _playerDatas[id];
                playerData.qX = qX;
                playerData.qY = qY;

                // Send this position to everyone next state packet
                _dataToSend.Enqueue(playerData);

                break;
            }

            case 8:
            {
                string name = _bitBuffer.ReadString();
                _playerDatas[id].name = name;

                // Tell all the players this new client's name
                _bitBuffer.Clear();
                _bitBuffer.AddByte(9);
                _bitBuffer.AddUShort(_playerDatas[id].id);
                _bitBuffer.AddString(_playerDatas[id].name);
                _bitBuffer.ToArray(_buffer);
                _webServer.SendAll(_connectedIds, new ArraySegment <byte>(_buffer, 0, 23));

                break;
            }

            case 10:
            {
                ushort objectId = _bitBuffer.ReadUShort();
                _movedObjects.Add(objectId);

                break;
            }

            case 11:
            {
                short pointChange = _bitBuffer.ReadShort();
                _playerDatas[id].points += pointChange;

                break;
            }
            }
        }
        static void WebServerOnData(int id, ArraySegment <byte> data)
        {
            _bitBuffer.FromArray(data.Array);
            byte messageId = data[0];

            switch (messageId)
            {
            case 1:
            {
                break;
            }
            }
        }
        static void WebServerOnData(int id, ArraySegment <byte> data)
        {
            _bitBuffer.FromArray(data.Array, data.Count);

            byte messageId = _bitBuffer.ReadByte();

            switch (messageId)
            {
            case 1:
            {
                uint qX = _bitBuffer.ReadUInt();
                uint qY = _bitBuffer.ReadUInt();

                PlayerData playerData = _playerDatas[id].
Exemple #5
0
    private void WebServerOnonData(int id, ArraySegment <byte> data)
    {
        ushort shortId = (ushort)id;

        if (_playerTransforms[shortId] == null)
        {
            _playerTransforms[shortId] = new uint[8];
        }
        _bitBuffer.Clear();
        _bitBuffer.FromArray(data.Array, data.Count);

        for (int i = 0; i < 8; i++)
        {
            _playerTransforms[shortId][i] = _bitBuffer.ReadUInt();
        }
    }
Exemple #6
0
            private void HandleENETMessage(Event evt)
            {
                Console.WriteLine($"\nreceived by {Context.Self.Path}" +
                                  $"\nsender {Sender.Path}\n");

                byte[] data = new byte[1024 + 4];
                evt.Packet.CopyTo(data);
                //var test = evt.Packet.Length;

                BitBuffer buffer = new BitBuffer(128);

                buffer.FromArray(data, evt.Packet.Length);

                OpCodes op = (OpCodes)buffer.ReadInt();
                uint    id = buffer.ReadUInt();

                if (DEBUG)
                {
                    Console.WriteLine($"OPCODE: {op.ToString()}");
                    Console.WriteLine($"PEERID: {id.ToString()}");
                }

                if (evt.Peer.ID != id)
                {
                    Console.WriteLine($"ID Mismatch! {evt.Peer.ID} vs. {id}");
                    return;
                }

                Packet packet = evt.Packet;

                switch (op)
                {
                case OpCodes.PlayerLogin:
                    //Answer OK
                    SendToSingleClient(CreateAnswerPacketLogin("OK", evt.Peer.ID), evt.Peer.ID);
                    break;
                }

                //Destroy all
                evt.Packet.Dispose();
            }
        static void WebServerOnData(int id, ArraySegment <byte> data)
        {
            _bitBuffer.Clear();
            _bitBuffer.FromArray(data.Array, data.Count);

            byte messageId = _bitBuffer.ReadByte();

            switch (messageId)
            {
            case 1:
            {
                uint qX = _bitBuffer.ReadUInt();
                uint qY = _bitBuffer.ReadUInt();

                PlayerData playerData = _playerDatas[id];
                playerData.qX = qX;
                playerData.qY = qY;

                // Send this position to everyone next state packet
                _dataToSend.Enqueue(playerData);

                break;
            }

            case 8:
            {
                string name = _bitBuffer.ReadString();
                _playerDatas[id].name = name;

                _bitBuffer.Clear();
                _bitBuffer.AddByte(9);
                _bitBuffer.AddUShort(_playerDatas[id].id);
                _bitBuffer.AddString(_playerDatas[id].name);
                _bitBuffer.ToArray(_buffer);

                break;
            }
            }
        }
    private void WsOnonData(ArraySegment <byte> obj)
    {
        _bitBuffer.Clear();
        _bitBuffer.FromArray(obj.Array, obj.Count);

        ushort messageId = _bitBuffer.ReadUShort();

        switch (messageId)
        {
        case 0:
        {
            ushort id = _bitBuffer.ReadUShort();
            if (_ghostCars.ContainsKey(id))
            {
                Destroy(_ghostCars[id].gameObject);
                _ghostCars.Remove(id);
            }

            break;
        }

        case 1:
        {
            ushort count = _bitBuffer.ReadUShort();
            for (int i = 0; i < count; i++)
            {
                ushort id = _bitBuffer.ReadUShort();

                QuantizedVector3    qPosition = new QuantizedVector3(_bitBuffer.ReadUInt(), _bitBuffer.ReadUInt(), _bitBuffer.ReadUInt());
                QuantizedQuaternion qRotation = new QuantizedQuaternion(_bitBuffer.ReadUInt(), _bitBuffer.ReadUInt(), _bitBuffer.ReadUInt(), _bitBuffer.ReadUInt());
                ushort qBestTime = _bitBuffer.ReadUShort();

                // Ignore it if it is the transform for my own car
                if (_myId == id || id == 0)
                {
                    continue;
                }

                Vector3    postion  = BoundedRange.Dequantize(qPosition, Constants.WORLD_BOUNDS);
                Quaternion rotation = SmallestThree.Dequantize(qRotation);

                if (!_ghostCars.ContainsKey(id))
                {
                    GameObject newCar = Instantiate(GhostCarPrefab, postion, rotation);
                    _ghostCars[id] = newCar.GetComponent <GhostCarBehavior>();
                }
                else
                {
                    _ghostCars[id].UpdateTransform(postion, rotation);
                    float bestTime = HalfPrecision.Dequantize(qBestTime);
                    _ghostCars[id].UpdatebestTime(bestTime);
                }
            }

            break;
        }

        case 2:
        {
            ushort id = _bitBuffer.ReadUShort();

            _myId = id;

            break;
        }
        }
    }
Exemple #9
0
        /// <summary>
        /// Consumers the thread.
        /// </summary>
        /// <param name="arg">Argument.</param>
        private static void ConsumerThread(object arg)
        {
            ClientMessageReceived item;

            //while (true)
            Console.WriteLine("Queue: " + Server.QueueMessages.Count.ToString());
            while (!Server.QueueMessages.IsEmpty)
            {
                bool isSuccessful = Server.QueueMessages.TryDequeue(out item);
                Console.WriteLine("Dequeue: " + isSuccessful);
                if (isSuccessful)
                {
                    //https://stackoverflow.com/questions/943398/get-int-value-from-enum-in-c-sharp
                    //https://msdn.microsoft.com/it-it/library/system.enum.getvalues(v=vs.110).aspx
                    //http://csharp.net-informations.com/statements/enum.htm
                    if (((byte)SendType.SENDTOALL).ToString() == item.MessageBytes.GetValue(0).ToString()) //0
                    {
                        //BROADCAST (SENDTOALL)
                        Console.WriteLine("BROADCAST (SENDTOALL)");
                        //Send data received to all client in List
                        foreach (var conn in Server.clients)
                        {
                            if (true)
                            {
                                conn.Value.SendBytes(item.MessageBytes, item.SOClientConnected);
                                Console.WriteLine("Send to: " + conn.Value.EndPoint.ToString());
                            }
                        }
                    }
                    else if ((byte)SendType.SENDTOOTHER == (byte)item.MessageBytes.GetValue(0)) //1
                    {
                        //BROADCAST (SENDTOOTHER)
                        Console.WriteLine("BROADCAST (SENDTOOTHER)");
                        //Call Objects Table
                        var col = db.GetCollection <Objects>("objects");
                        //Parser Message
                        //Remove first byte (type)
                        //https://stackoverflow.com/questions/31550484/faster-code-to-remove-first-elements-from-byte-array
                        byte   STypeBuffer       = item.MessageBytes[0];
                        byte[] NewBufferReceiver = new byte[item.MessageBytes.Length - 1];
                        Array.Copy(item.MessageBytes, 1, NewBufferReceiver, 0, NewBufferReceiver.Length);

                        //Deserialize message using NetStack
                        //Reset bit buffer for further reusing
                        BitBuffer data = new BitBuffer(1024);
                        data.FromArray(NewBufferReceiver, NewBufferReceiver.Length);

                        byte                 TypeBuffer  = data.ReadByte();
                        string               OwnerPlayer = data.ReadString();
                        bool                 isKine      = data.ReadBool();
                        uint                 IDObject    = data.ReadUInt();
                        CompressedVector3    position    = new CompressedVector3(data.ReadUInt(), data.ReadUInt(), data.ReadUInt());
                        CompressedQuaternion rotation    = new CompressedQuaternion(data.ReadByte(), data.ReadShort(), data.ReadShort(), data.ReadShort());
                        // Read Vector3 Compress Velocity
                        //ushort compressedVelocityX = HalfPrecision.Compress(speed);
                        Vector3 VelocityReceived = new Vector3(HalfPrecision.Decompress(data.ReadUShort()), HalfPrecision.Decompress(data.ReadUShort()), HalfPrecision.Decompress(data.ReadUShort()));

                        //Read Float InterpolationTime
                        float InterpolationTime = HalfPrecision.Decompress(data.ReadUShort());

                        // Check if bit buffer is fully unloaded
                        Console.WriteLine("Bit buffer is empty: " + data.IsFinished);

                        //Decompress Vector and Quaternion
                        //Create a new BoundedRange array for Vector3 position, each entry has bounds and precision
                        BoundedRange[] worldBounds = new BoundedRange[3];

                        worldBounds[0] = new BoundedRange(-50f, 50f, 0.05f); // X axis
                        worldBounds[1] = new BoundedRange(0f, 25f, 0.05f);   // Y axis
                        worldBounds[2] = new BoundedRange(-50f, 50f, 0.05f); // Z axis

                        //Decompress position data
                        Vector3 decompressedPosition = BoundedRange.Decompress(position, worldBounds);

                        // Decompress rotation data
                        Quaternion decompressedRotation = SmallestThree.Decompress(rotation);

                        if (Server.DEBUG)
                        {
                            Console.WriteLine("RECEIVED DATA: ");
                            Console.WriteLine("TYPE RECEIVED: " + TypeBuffer.ToString());
                            Console.WriteLine("IDObject RECEIVED: " + IDObject.ToString());
                            Console.WriteLine("UID RECEIVED: " + OwnerPlayer);
                            Console.WriteLine("isKinematic RECEIVED: " + isKine.ToString());
                            Console.WriteLine("POS RECEIVED: " + decompressedPosition.X.ToString() + ", " + decompressedPosition.Y.ToString() + ", " + decompressedPosition.Z.ToString());
                            Console.WriteLine("ROT RECEIVED: " + decompressedRotation.X.ToString() + ", " + decompressedRotation.Y.ToString() + ", " + decompressedRotation.Z.ToString() + ", " + decompressedRotation.W.ToString());
                            Console.WriteLine("PosX: " + decompressedPosition.X);
                            Console.WriteLine("PosY: " + decompressedPosition.Y);
                            Console.WriteLine("PosZ: " + decompressedPosition.Z);
                            Console.WriteLine("VEL RECEIVED: " + VelocityReceived.X.ToString() + ", " + VelocityReceived.Y.ToString() + ", " + VelocityReceived.Z.ToString());
                            Console.WriteLine("INTERPOLATION TIME: " + InterpolationTime.ToString());
                            //var ReceiveMessageFromGameObjectBuffer = new ReceiveMessageFromGameObject(); //NOT USED!
                        }

                        //Check if ObjectReceived.ID <> 0
                        if (IDObject != 0)
                        {
                            var MVobject = new Objects
                            {
                                IDObject = (int)IDObject,
                                isKine   = isKine,
                                PosX     = decompressedPosition.X,
                                PosY     = decompressedPosition.Y,
                                PosZ     = decompressedPosition.Z,
                                RotX     = decompressedRotation.X,
                                RotY     = decompressedRotation.Y,
                                RotZ     = decompressedRotation.Z,
                                RotW     = decompressedRotation.W,
                                UID      = IDObject.ToString() + ";" + OwnerPlayer
                            };

                            //Debug
                            Console.WriteLine("MVobject PosX: " + MVobject.PosX);
                            Console.WriteLine("MVobject PosY: " + MVobject.PosY);
                            Console.WriteLine("MVobject PosZ: " + MVobject.PosZ);

                            if ((byte)PacketId.OBJECT_SPAWN == TypeBuffer)
                            {
                                // Insert new customer document (Id will be auto-incremented)
                                col.Insert(MVobject);

                                // Create unique index in Name field
                                col.EnsureIndex(x => x.UID, true);
                                Console.WriteLine("OBJECT SPAWN SAVED");
                            }
                            else if ((byte)PacketId.OBJECT_MOVE == TypeBuffer)
                            {
                                //Check if record exist
                                if (col.Count(Query.EQ("UID", IDObject.ToString() + ";" + OwnerPlayer)) == 1)
                                {
                                    //Search and update
                                    // Now, search for document your document
                                    var ObjectsFinded = col.FindOne(x => x.UID == IDObject.ToString() + ";" + OwnerPlayer);
                                    //Update data
                                    ObjectsFinded.isKine = isKine;
                                    ObjectsFinded.PosX   = decompressedPosition.X;
                                    ObjectsFinded.PosY   = decompressedPosition.Y;
                                    ObjectsFinded.PosZ   = decompressedPosition.Z;
                                    ObjectsFinded.RotX   = decompressedRotation.X;
                                    ObjectsFinded.RotY   = decompressedRotation.Y;
                                    ObjectsFinded.RotZ   = decompressedRotation.Z;
                                    ObjectsFinded.RotW   = decompressedRotation.W;

                                    //Save data to Objects DB
                                    if (col.Update(ObjectsFinded))
                                    {
                                        Console.WriteLine("UPDATE OBJECT IN DB");
                                    }
                                    else
                                    {
                                        Console.WriteLine("*NOT* UPDATED OBJECT IN DB");
                                    }
                                }
                                else
                                {
                                    col.Insert(MVobject);
                                    //Insert data to Objects DB

                                    col.EnsureIndex(x => x.UID, true);
                                    //Create unique index in Name field
                                    Console.WriteLine("INSERT OBJECT IN DB");
                                }
                                Console.WriteLine("OBJECT MOVE");
                            }
                            else if ((byte)PacketId.OBJECT_UNSPAWN == TypeBuffer)
                            {
                                if (col.Count(Query.EQ("UID", IDObject.ToString() + ";" + OwnerPlayer)) == 1)
                                {
                                    col.Delete(Query.EQ("UID", IDObject.ToString() + ";" + OwnerPlayer));
                                    //Save data to Objects DB
                                    Console.WriteLine("DELETE OBJECT FROM DB");
                                }
                                else
                                {
                                    Console.WriteLine("OBJECT UNSPAWN NOT IN DB");;
                                }
                                Console.WriteLine("OBJECT UNSPAWN");
                            }
                        } // END Check ObjectReceived.ID <> 0
                        //Send data received to all other client in List
                        Console.WriteLine("SEND MESSAGE TO OTHER CLIENTS");
                        foreach (var conn in Server.clients)
                        {
                            if (conn.Value != item.ClientConnected) //SENDTOOTHER
                            {
                                conn.Value.SendBytes(item.MessageBytes, item.SOClientConnected);
                                Console.WriteLine("Send to: " + conn.Value.EndPoint.ToString());
                            }
                        }
                    }
                    else if ((byte)SendType.SENDTOSERVER == (byte)item.MessageBytes.GetValue(0)) //2
                    {
                        //FOR NOW ECHO SERVER (SENDTOSERVER)
                        Console.WriteLine("CLIENT TO SERVER (SENDTOSERVER)");
                        //Parser Message
                        //Remove first byte (type)
                        //https://stackoverflow.com/questions/31550484/faster-code-to-remove-first-elements-from-byte-array
                        byte   STypeBuffer       = item.MessageBytes[0];
                        byte[] NewBufferReceiver = new byte[item.MessageBytes.Length - 1];
                        Array.Copy(item.MessageBytes, 1, NewBufferReceiver, 0, NewBufferReceiver.Length);
                        //Deserialize message using NetStack
                        //Reset bit buffer for further reusing
                        BitBuffer data = new BitBuffer(1024);
                        data.FromArray(NewBufferReceiver, NewBufferReceiver.Length);

                        byte   CommandTypeBuffer = data.ReadByte();
                        string Answer            = data.ReadString();

                        // Check if bit buffer is fully unloaded
                        Console.WriteLine("Bit buffer is empty: " + data.IsFinished);
                        String UIDBuffer = String.Empty;
                        if (STypeBuffer == 2)
                        {
                            if ((sbyte)CommandType.LOGIN == CommandTypeBuffer)
                            {
                                //Cerca e restituisci il tutto
                                foreach (var conn in Server.clients)
                                {
                                    if (conn.Value == item.ClientConnected) //SENDTOSERVER
                                    {
                                        //DONE: Check here if user exist and password correct
                                        //Get users collection
                                        var col = db.GetCollection <Users>("users");
                                        Console.WriteLine("COMMAND RECEIVED: " + Answer);
                                        //Parse HMessageReceived
                                        string[] words = Answer.Split(';');
                                        //words[0] = Login; words[1] = Password
                                        if (col.Count(Query.EQ("UserName", words[0])) == 1)
                                        {
                                            var    results            = col.Find(Query.EQ("UserName", words[0]));
                                            string UserPasswordRecord = string.Empty;
                                            foreach (var c in results)
                                            {
                                                Console.WriteLine("#{0} - {1}", c.Id, c.UserName);
                                                UserPasswordRecord = c.UserPassword;
                                            }
                                            //Verify password
                                            ScryptEncoder encoder = new ScryptEncoder();
                                            //Check password
                                            if (encoder.Compare(words[1], UserPasswordRecord))
                                            {
                                                //OK
                                                UIDBuffer = conn.Key;
                                                Console.WriteLine("UID: " + UIDBuffer);
                                            }
                                            else
                                            {
                                                //*NOT* OK
                                                UIDBuffer = string.Empty;
                                                Console.WriteLine("UID: ERROR PASSWORD" + UIDBuffer);
                                            }
                                        }
                                        else
                                        {
                                            UIDBuffer = string.Empty;
                                            Console.WriteLine("UID: USER NOT EXISTS!" + UIDBuffer);
                                        }
                                    }
                                }
                            }
                        }

                        //Reset bit buffer for further reusing
                        data.Clear();
                        data.AddByte((byte)CommandType.LOGIN)
                        .AddString(UIDBuffer);

                        byte[] BufferNetStack = new byte[data.Length];
                        data.ToArray(BufferNetStack);
                        data.Clear();

                        //SEND MESSAGE
                        // Add type!
                        //https://stackoverflow.com/questions/5591329/c-sharp-how-to-add-byte-to-byte-array
                        byte[] newArray = new byte[BufferNetStack.Length + 1];
                        BufferNetStack.CopyTo(newArray, 1);
                        newArray[0] = (byte)SendType.SENDTOSERVER;
                        item.ClientConnected.SendBytes(newArray, item.SOClientConnected);
                        if (DEBUG)
                        {
                            Console.WriteLine("Data Lenghts: " + newArray.Length.ToString());
                            Console.WriteLine("Data Lenghts NetStack: " + BufferNetStack.Length.ToString());
                            Console.WriteLine("Data Lenghts BitBuffer: " + data.Length.ToString());
                            Console.WriteLine("Message sent!");
                        }
                        Console.WriteLine("Send to: " + item.ClientConnected.EndPoint.ToString());
                        //HERE SEND TO ALL CLIENTS OBJECTS DB
                        //DONE: Add code to send all clients
                        Console.WriteLine("SEND ALL OBJECTS TO CLIENT");
                        //Call Objects Table
                        var col_objects = db.GetCollection <Objects>("objects");
                        //Recovers all objects in the table
                        var results_objects = col_objects.Find(Query.GT("_id", 0));
                        //Foreach send them to the client connected
                        foreach (var o in results_objects)
                        {
                            Console.WriteLine("SEND IDOBJECT: " + o.IDObject.ToString());
                            //SEND USING NETSTACK SERIALIZATION
                            // Create a new BoundedRange array for Vector3 position, each entry has bounds and precision
                            BoundedRange[] worldBounds = new BoundedRange[3];

                            worldBounds[0] = new BoundedRange(-50f, 50f, 0.05f); // X axis
                            worldBounds[1] = new BoundedRange(0f, 25f, 0.05f);   // Y axis
                            worldBounds[2] = new BoundedRange(-50f, 50f, 0.05f); // Z axis

                            //Convert from HazelUDPTestClient.Vector3 at System.Numerics.Vector3
                            System.Numerics.Vector3 InternalPos = new System.Numerics.Vector3(o.PosX, o.PosY, o.PosZ);
                            //Compress position data
                            CompressedVector3 compressedPosition = BoundedRange.Compress(InternalPos, worldBounds);

                            // Read compressed data
                            Console.WriteLine("Compressed position - X: " + compressedPosition.x + ", Y:" + compressedPosition.y + ", Z:" + compressedPosition.z);

                            //Convert from HazelUDPTestClient.Quaternion at System.Numerics.Quaternion
                            System.Numerics.Quaternion InternalRot = new System.Numerics.Quaternion(o.RotX, o.RotY, o.RotZ, o.RotW);
                            // Compress rotation data
                            CompressedQuaternion compressedRotation = SmallestThree.Compress(InternalRot);

                            // Read compressed data
                            Console.WriteLine("Compressed rotation - M: " + compressedRotation.m + ", A:" + compressedRotation.a + ", B:" + compressedRotation.b + ", C:" + compressedRotation.c);

                            //Add Velocity Vector (0,0,0)
                            Vector3 velocity = Vector3.Zero;

                            //Add and compress Interporlation Time
                            ushort compressedTimeInterpolation = HalfPrecision.Compress(0f);

                            //Reset bit buffer for further reusing
                            data.Clear();
                            //Serialization
                            data.AddByte((byte)PacketId.OBJECT_MOVE)
                            .AddString(o.UID.Split(';')[1])     //OwnerPlayer
                            .AddBool(o.isKine)
                            .AddUInt((uint)o.IDObject)
                            .AddUInt(compressedPosition.x)
                            .AddUInt(compressedPosition.y)
                            .AddUInt(compressedPosition.z)
                            .AddByte(compressedRotation.m)
                            .AddShort(compressedRotation.a)
                            .AddShort(compressedRotation.b)
                            .AddShort(compressedRotation.c)     //Add dummy date (0,0,0)
                            .AddUShort(HalfPrecision.Compress(velocity.X))
                            .AddUShort(HalfPrecision.Compress(velocity.Y))
                            .AddUShort(HalfPrecision.Compress(velocity.Z))
                            .AddUShort(compressedTimeInterpolation);

                            Console.WriteLine("BitBuffer: " + data.Length.ToString());

                            byte[] BufferNetStackObject = new byte[data.Length];
                            data.ToArray(BufferNetStackObject);
                            data.Clear();
                            //https://discordapp.com/channels/515987760281288707/515987760281288711/527744788745814028
                            //MA soprattutto: https://discordapp.com/channels/515987760281288707/515987760281288711/536428267851350017
                            //Okay guys, after some debugging I've found the mistake in the original BitBuffer implementation,
                            //Alex forgot to check index boundaries during conversion so this is why + 4 bytes was required for shifting.
                            //Now it's fixed and no longer needed I hope
                            //https://github.com/nxrighthere/NetStack/commit/f381a88751fa0cb72af2cad7652a973d570d3dda

                            //SEND MESSAGE
                            // Add type!
                            //https://stackoverflow.com/questions/5591329/c-sharp-how-to-add-byte-to-byte-array
                            byte[] newArrayObject = new byte[BufferNetStackObject.Length + 1];      //Create +1 NewArrayObject
                            BufferNetStackObject.CopyTo(newArrayObject, 1);                         //Coping start from position 1 (NOT 0)
                            newArrayObject[0] = (byte)SendType.SENDTOOTHER;                         //Coping position 0 byte SendType
                            item.ClientConnected.SendBytes(newArrayObject, item.SOClientConnected); //Send new packet

                            if (DEBUG)
                            {
                                Console.WriteLine("Data Lenghts: " + newArray.Length.ToString());
                                Console.WriteLine("Data Lenghts NetStack: " + BufferNetStack.Length.ToString());
                                Console.WriteLine("Message sent!");
                            }
                        }
                    }
                }
            }
        }
        static void WebServerOnData(int id, ArraySegment<byte> data) {
            _bitBuffer.Clear();
            _bitBuffer.FromArray(data.Array, data.Count);

            byte messageId = _bitBuffer.ReadByte();
            switch (messageId) {
                case 1:
                {
                    uint qX = _bitBuffer.ReadUInt();
                    uint qY = _bitBuffer.ReadUInt();

                    PlayerData playerData = _playerDatas[id];
                    playerData.qX = qX;
                    playerData.qY = qY;

                    // Send this position to everyone next state packet
                    _dataToSend.Enqueue(playerData);
                    
                    break;
                }
                case 8:
                {
                    string name = _bitBuffer.ReadString();
                    _playerDatas[id].name = name;

                    _handshakenClientCount += 1;

                    // Tell all the players this new client's name
                    _bitBuffer.Clear();
                    _bitBuffer.AddByte(9);
                    _bitBuffer.AddUShort(_playerDatas[id].id);
                    _bitBuffer.AddString(_playerDatas[id].name);
                    _bitBuffer.ToArray(_buffer);
                    _webServer.SendAll(_connectedIds, new ArraySegment<byte>(_buffer, 0, 23));

                    break;
                }
                case 10:
                {
                    ushort objectId = _bitBuffer.ReadUShort();
                    ushort newX = _bitBuffer.ReadUShort();
                    ushort newY = _bitBuffer.ReadUShort();
                    _movedObjects[objectId] = new Tuple<ushort, ushort>(newX, newY);

                    break;
                }
                case 11:
                {
                    short pointChange = _bitBuffer.ReadShort();
                    _playerDatas[id].points += pointChange;

                    Console.WriteLine($"Got point change {id} {pointChange}");

                    // If points are 0 or less, give builder a point
                    if (pointChange <= 0) {
                        _playerDatas[_builderId].points += 1;
                    }

                    break;
                }
            }
        }
        /// <summary>
        /// Datas the received.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="args">Arguments.</param>
        private static void DataReceived(object sender, DataReceivedEventArgs args)
        {
            Console.WriteLine("Received (" + string.Join <byte>(", ", args.Bytes) + ") from " + connection.EndPoint.ToString());
            //Decode parse received data
            //Remove first byte (type)
            //https://stackoverflow.com/questions/31550484/faster-code-to-remove-first-elements-from-byte-array
            byte SendTypeBuffer = args.Bytes[0];

            byte[] NewBufferReceiver = new byte[args.Bytes.Length - 1];
            Array.Copy(args.Bytes, 1, NewBufferReceiver, 0, NewBufferReceiver.Length);
            //Check SendType
            if ((SendTypeBuffer == (byte)SendType.SENDTOALL) || (SendTypeBuffer == (byte)SendType.SENDTOOTHER))
            {
                //Deserialize message using NetStack
                //Reset bit buffer for further reusing
                data.Clear();
                data.FromArray(NewBufferReceiver, NewBufferReceiver.Length);

                byte                 TypeBuffer  = data.ReadByte();
                string               OwnerPlayer = data.ReadString();
                bool                 isKine      = data.ReadBool();
                uint                 IDObject    = data.ReadUInt();
                CompressedVector3    position    = new CompressedVector3(data.ReadUInt(), data.ReadUInt(), data.ReadUInt());
                CompressedQuaternion rotation    = new CompressedQuaternion(data.ReadByte(), data.ReadShort(), data.ReadShort(), data.ReadShort());
                //Read Vector3 Compress Velocity
                //ushort compressedVelocityX = HalfPrecision.Compress(speed);
                Vector3 VelocityReceived = new Vector3(HalfPrecision.Decompress(data.ReadUShort()), HalfPrecision.Decompress(data.ReadUShort()), HalfPrecision.Decompress(data.ReadUShort()));
                //Read Float InterpolationTime
                float InterpolationTime = HalfPrecision.Decompress(data.ReadUShort());

                // Check if bit buffer is fully unloaded
                Console.WriteLine("Bit buffer is empty: " + data.IsFinished);

                //Decompress Vector and Quaternion
                //Create a new BoundedRange array for Vector3 position, each entry has bounds and precision
                BoundedRange[] worldBounds = new BoundedRange[3];

                worldBounds[0] = new BoundedRange(-50f, 50f, 0.05f); // X axis
                worldBounds[1] = new BoundedRange(0f, 25f, 0.05f);   // Y axis
                worldBounds[2] = new BoundedRange(-50f, 50f, 0.05f); // Z axis

                //Decompress position data
                Vector3 decompressedPosition = BoundedRange.Decompress(position, worldBounds);

                // Decompress rotation data
                Quaternion decompressedRotation = SmallestThree.Decompress(rotation);

                //Show DATA received
                if (DEBUG)
                {
                    Console.WriteLine("ID RECEIVED: " + IDObject.ToString());
                    Console.WriteLine("TYPE RECEIVED: " + TypeBuffer.ToString());
                    Console.WriteLine("UID RECEIVED: " + OwnerPlayer);
                    Console.WriteLine("IsKINE RECEIVED: " + isKine.ToString());
                    Console.WriteLine("POS RECEIVED: " + decompressedPosition.X.ToString() + ", " + decompressedPosition.Y.ToString() + ", " + decompressedPosition.Z.ToString());
                    Console.WriteLine("ROT RECEIVED: " + decompressedRotation.X.ToString() + ", " + decompressedRotation.Y.ToString() + ", " + decompressedRotation.Z.ToString() + ", " + decompressedRotation.W.ToString());
                    Console.WriteLine("VEL RECEIVED: " + VelocityReceived.X.ToString() + ", " + VelocityReceived.Y.ToString() + ", " + VelocityReceived.Z.ToString());
                    Console.WriteLine("INTERPOLATION TIME: " + InterpolationTime.ToString());
                }

                if ((byte)PacketId.PLAYER_JOIN == TypeBuffer)
                {
                    Console.WriteLine("Add new Player!");
                    //Code for new Player
                    //Spawn something? YES
                    //Using Dispatcher? NO
                    //PlayerSpawn
                    SendMessage(SendType.SENDTOOTHER, PacketId.PLAYER_SPAWN, 0, UID + ";" + AvatarName, true, lastPosition, lastRotation, VelocityDefaultZero, 0f);
                    //TODO: Using Reliable UDP??
                }
                else if ((byte)PacketId.OBJECT_MOVE == TypeBuffer)
                {
                    Console.WriteLine("OBJECT MOVE");
                }
                else if ((byte)PacketId.PLAYER_MOVE == TypeBuffer)
                {
                    Console.WriteLine("PLAYER MOVE");
                }
                else if ((byte)PacketId.PLAYER_SPAWN == TypeBuffer)
                {
                    Console.WriteLine("PLAYER SPAWN");
                }
                else if ((byte)PacketId.OBJECT_SPAWN == TypeBuffer)
                {
                    Console.WriteLine("OBJECT SPAWN");
                    //Rez Object Received
                    //RezObject(OwnerPlayer.Split(';')[1], OwnerPlayer.Split(';')[0], false);
                }
                else if ((byte)PacketId.OBJECT_UNSPAWN == TypeBuffer)
                {
                    Console.WriteLine("OBJECT UNSPAWN");
                    //De Rez Object Received
                    //DeRezObject(OwnerPlayer.Split(';')[1], OwnerPlayer.Split(';')[0], false, ObjectReceived.ID);
                }
            }
            else if (SendTypeBuffer == (byte)SendType.SENDTOSERVER)
            {
                //Deserialize message using NetStack
                //Reset bit buffer for further reusing
                data.Clear();
                data.FromArray(NewBufferReceiver, NewBufferReceiver.Length);

                byte   CommandTypeBuffer = data.ReadByte();
                string Answer            = data.ReadString();

                // Check if bit buffer is fully unloaded
                Console.WriteLine("Bit buffer is empty: " + data.IsFinished);

                if ((byte)CommandType.LOGIN == CommandTypeBuffer)
                {
                    if (Answer != String.Empty)
                    {
                        UID = Answer;
                        //Set UID for Your Avatar ME
                        //UnityMainThreadDispatcher.Instance().Enqueue(SetUIDInMainThread(HMessageReceived.Answer));
                        Console.WriteLine("UID RECEIVED: " + Answer);
                        //PLAYER_JOIN MESSAGE (SENDTOOTHER)
                        SendMessage(SendType.SENDTOOTHER, PacketId.PLAYER_JOIN, 0, UID + ";" + AvatarName, true, lastPosition, lastRotation, VelocityDefaultZero, 0f);
                        //TO DO: Using Reliable UDP??
                    }
                    else
                    {
                        Console.WriteLine("UID RECEIVED is EMPTY (NOT VALID PASSWORD): " + Answer);
                        //Disconnect
                        if (connection != null)
                        {
                            Console.WriteLine("DisConnecting from: " + connection.EndPoint.ToString());
                            connection.Close();
                        }
                    }
                }
                else if ((byte)CommandType.DISCONNECTEDCLIENT == CommandTypeBuffer)
                {
                    //Debug Disconnected UID
                    Console.WriteLine("UID RECEIVED and TO DESTROY: " + Answer);
                }
            }
            args.Recycle();
        }