private void StartReceivingMessages()
        {
            Task.Run(async() =>
            {
                try
                {
                    using (CancellationTokenSource tokenSource = new CancellationTokenSource())
                    {
                        // Keep receiving packets from the client and respond to them
                        // Eventually when the client disconnects we'll just get an exception and end the thread...

                        using (var streamReader = new MessagePackStreamReader(_netStream, true))
                        {
                            while (server.Clients.Contains(this))
                            {
                                if (_netStream.DataAvailable)
                                {
                                    try
                                    {
                                        ReadOnlySequence <byte>?sequence = await streamReader.ReadAsync(tokenSource.Token);
                                        if (sequence.HasValue)
                                        {
                                            ServerPack obj = MessagePackSerializer.Deserialize <ServerPack>(sequence.Value, PlayerdomGame.SerializerSettings, tokenSource.Token);
                                            HandleMessage(obj);
                                        }
                                    }
                                    catch (MessagePackSerializationException)
                                    {
                                    }
                                }

                                else
                                {
                                    Task.Delay(10).Wait();
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    if (e.GetType() == typeof(Exception))
                    {
                        server.logger("Exception thrown: " + e.Message);
                    }
                    server.RemoveClient(this);
                }
            });
        }
        private void HandleMessage(ServerPack obj)
        {
            InputState = obj.KeysPressed;
            LastUpdate = DateTime.Now;

            if (obj.CurrentMessage == null)
            {
                return;
            }

            if (obj.CurrentMessage.MessageType == "login" && !FocusedObjectId.HasValue)
            {
                using (SqliteCommand command = server.connection.CreateCommand())
                {
                    command.CommandText =
                        @"
                            SELECT * FROM players WHERE username=$username
                        ";
                    command.Parameters.AddWithValue("$username", obj.CurrentMessage.MessageContent[0]);

                    Name = obj.CurrentMessage.MessageContent[0];

                    using (SqliteDataReader reader = command.ExecuteReader())
                    {
                        if (reader.Read())
                        {
                            lock (server.Clients)
                            {
                                if (GetHash(obj.CurrentMessage.MessageContent[1]) != reader.GetString(2))
                                {
                                    throw new Exception("Incorrect Password");
                                }

                                if (server.Clients.Where(c => c.UserId == reader.GetInt64(0)).Count() > 0)
                                {
                                    throw new Exception("Player already logged in");
                                }
                            }

                            UserId = reader.GetInt64(0);

                            Player p = new Player()
                            {
                                Name = this.Name, Coordinates = (reader.GetDouble(3), reader.GetDouble(4)), Level = (uint)reader.GetInt32(6), Health = (ulong)reader.GetInt64(7)
                            };
                            DimensionId = reader.GetByte(5);
                            InitializePlayer(p, DimensionId);
                        }
                        else
                        {
                            InitializePlayer(new Player()
                            {
                                Name = this.Name, Health = Player.GetMaxHealth(0)
                            }, DimensionId);
                        }
                    }

                    if (!UserId.HasValue)
                    {
                        using (SqliteDataReader reader = command.ExecuteReader())
                        {
                            if (reader.Read())
                            {
                                lock (server.Clients)
                                {
                                    if (server.Clients.Where(c => c.UserId == reader.GetInt64(0)).Count() > 0)
                                    {
                                        throw new Exception("Player already logged in");
                                    }
                                }

                                UserId = reader.GetInt64(0);
                                SetPassword(obj.CurrentMessage.MessageContent[1]);
                            }
                        }
                    }
                }
            }
        }
        private void HandleMessage(ServerPack obj)
        {
            InputState = obj.KeysPressed;
            LastUpdate = DateTime.Now;

            if (obj.CurrentMessage == null)
            {
                return;
            }

            if (obj.CurrentMessage.MessageType == "login" && !FocusedObjectId.HasValue)
            {
                using (SqliteCommand command = server.connection.CreateCommand())
                {
                    command.CommandText =
                        @"
                            SELECT * FROM players WHERE username=$username
                        ";
                    command.Parameters.AddWithValue("$username", obj.CurrentMessage.MessageContent[0]);

                    Name = obj.CurrentMessage.MessageContent[0];

                    using (SqliteDataReader reader = command.ExecuteReader())
                    {
                        if (reader.Read())
                        {
                            lock (server.Clients)
                            {
                                if (GetHash(obj.CurrentMessage.MessageContent[1]) != reader.GetString(2))
                                {
                                    throw new Exception("Incorrect Password");
                                }

                                if (server.Clients.Where(c => c.UserId == reader.GetInt64(0)).Count() > 0)
                                {
                                    throw new Exception("Player already logged in");
                                }
                            }

                            UserId = reader.GetInt64(0);

                            Player p = new Player()
                            {
                                Name = this.Name, Coordinates = (reader.GetDouble(3), reader.GetDouble(4)), Level = (uint)reader.GetInt32(6), Health = (ulong)reader.GetInt64(7)
                            };
                            DimensionId = reader.GetByte(5);
                            InitializePlayer(p, DimensionId);
                        }
                        else
                        {
                            InitializePlayer(new Player()
                            {
                                Name = this.Name, Health = Player.GetMaxHealth(0)
                            }, DimensionId);
                        }
                    }

                    if (!UserId.HasValue)
                    {
                        using (SqliteDataReader reader = command.ExecuteReader())
                        {
                            if (reader.Read())
                            {
                                lock (server.Clients)
                                {
                                    if (server.Clients.Where(c => c.UserId == reader.GetInt64(0)).Count() > 0)
                                    {
                                        throw new Exception("Player already logged in");
                                    }
                                }

                                UserId = reader.GetInt64(0);
                                SetPassword(obj.CurrentMessage.MessageContent[1]);
                            }
                        }
                    }
                }
            }
            else if (FocusedObjectId.HasValue)
            {
                if (obj.CurrentMessage.MessageType.StartsWith("chat_") && obj.CurrentMessage.MessageType.Length > "chat_".Length && obj.CurrentMessage.MessageContent.Length == 1)
                {
                    ChatMessageScopes scope = ChatMessageScopes.Area;
                    switch (obj.CurrentMessage.MessageType.Substring("chat_".Length))
                    {
                    default:
                    case "area":
                        break;

                    case "party":
                        scope = ChatMessageScopes.Party;
                        break;

                    case "dimension":
                        scope = ChatMessageScopes.Dimension;
                        break;

                    case "global":
                        scope = ChatMessageScopes.Global;
                        break;
                    }

                    if (server.Dimensions.TryGetValue(DimensionId, out Dimension d) && d.Map.LoadedObjects.TryGetValue(FocusedObjectId.Value, out GameObject go))
                    {
                        server.MessageQueue.Enqueue(new ChatMessage()
                        {
                            Content        = obj.CurrentMessage.MessageContent[0],
                            Sender         = Name,
                            TimeSent       = DateTime.Now,
                            DimensionSent  = DimensionId,
                            PlaceSent      = go.Coordinates,
                            SenderObjectId = FocusedObjectId.Value,
                            MessageType    = ChatMessageTypes.Player,
                            MessageScope   = scope
                        });
                    }
                }
            }
        }