/// <summary>
 /// 
 /// </summary>
 /// <param name="packet"></param>
 public void QueuePacket(IPacket packet, int connectionId)
 {
     m_packetQueue.Add(new ServerPacket(ServerPacketType.ToConnection, packet, connectionId));
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rawPacket"></param>
        /// <param name="hostId"></param>
        /// <param name="connectionId"></param>
        private void OnPlayerConnectPacket(IPacket rawPacket, int hostId, int connectionId)
        {
            var packet = rawPacket as Client.Packet.PlayerConnectPacket;
            if (packet == null)
            {
                return;
            }

            var allowConnection = true;
            var errorMessage = "None";

            // Check for already existing username
            if (m_players.Any(x => x.Username.Equals(packet.Username, StringComparison.OrdinalIgnoreCase)))
            {
                // Username already in use.
                allowConnection = false;
                errorMessage = string.Format("The username {0} is already in use.", packet.Username);
                Debug.LogError(string.Format("Server: {0}", errorMessage));
            }

            var spawnPoint = new Vector3(-280.0f, 47.5f, 338.0f);

            if (allowConnection)
            {
                // Try get an offline player and get their location
                var offlinePlayer = m_offlinePlayers.FirstOrDefault(x => x.Username.Equals(packet.Username, StringComparison.OrdinalIgnoreCase));
                if (offlinePlayer != null)
                {
                    spawnPoint = offlinePlayer.CurrentPosition;
                }

                // Player is valid, store them
                var newPlayerData = new PlayerData(connectionId, packet.Username, spawnPoint);

                // Player is valid, tell all other players about them.
                var playerJoinPacket = new Server.Packet.PlayerJoinPacket(connectionId, newPlayerData.Username, newPlayerData.CurrentPosition);
                QueuePacketAllExcluding(playerJoinPacket, new int[] { connectionId });

                foreach (var player in m_players)
                {
                    var otherPlayerJoinPack = new Server.Packet.PlayerJoinPacket(player.ConnectionId, player.Username, player.CurrentPosition);
                    QueuePacket(otherPlayerJoinPack, connectionId);
                }

                m_players.Add(newPlayerData);

                if (offlinePlayer != null)
                {
                    m_offlinePlayers.Remove(offlinePlayer);
                }

                SendMobSpawnPackets(newPlayerData.ConnectionId);
            }

            var handShakePacket = new Server.Packet.PlayerHandshakePacket(allowConnection, errorMessage, spawnPoint);
            QueuePacket(handShakePacket, connectionId);

            Debug.Log(string.Format("Server: Revieved player connection from {0}", packet.Username));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rawPacket"></param>
        /// <param name="hostId"></param>
        /// <param name="connectionId"></param>
        private void OnPlayerMovePacket(IPacket rawPacket, int hostId, int connectionId)
        {
            var packet = rawPacket as Client.Packet.PlayerMovePacket;
            if (packet == null)
            {
                return;
            }

            var player = m_players.FirstOrDefault(x => x.ConnectionId == connectionId);
            if (player == null)
            {
                return;
            }

            player.CurrentPosition = packet.GetPosition();

            var movementPacket = new Server.Packet.PlayerMovePacket(connectionId, packet.GetPosition());
            QueuePacketAllExcluding(movementPacket, new int[] { connectionId });
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rawPacket"></param>
        /// <param name="hostId"></param>
        /// <param name="connectionId"></param>
        private void OnPlayerAttackPacket(IPacket rawPacket, int hostId, int connectionId)
        {
            var packet = rawPacket as Client.Packet.PlayerAttackPacket;
            if (packet == null)
            {
                return;
            }

            Debug.Log("Server: Player Attack Packet Received - 1");

            var mob = m_mobs.FirstOrDefault(x => x.ID == packet.MobID);
            if (mob == null)
            {
                return;
            }

            mob.Health -= packet.Damage;

            if (mob.Health > 0)
            {
                var mobDamagePacket = new Server.Packet.MobDamagedPacket(mob.ID, mob.Health);
                QueuePacketAll(mobDamagePacket);
            }
            else
            {
                // It's dead mate
                var mobDeathPacket = new Server.Packet.MobDeathPacket(mob.ID);
                QueuePacketAll(mobDeathPacket);

                m_mobs.Remove(mob);
                var spawner = mob.SpawnArea.GetComponent<Server.SpawnArea>();
                spawner.RequestSpawn();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rawPacket"></param>
        /// <param name="hostId"></param>
        /// <param name="connectionId"></param>
        private void OnPlayerChatSendPacket(IPacket rawPacket, int hostId, int connectionId)
        {
            var packet = rawPacket as Client.Packet.PlayerChatSendPacket;
            if (packet == null)
            {
                return;
            }

            var chatPacket = new Server.Packet.PlayerChatPacket(connectionId, packet.ChatMessage);
            QueuePacketAllExcluding(chatPacket, new int[] { connectionId });
        }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="type"></param>
 /// <param name="packet"></param>
 /// <param name="connectionId"></param>
 public ServerPacket(ServerPacketType type, IPacket packet, int connectionId)
     : this(type, packet)
 {
     this.ConnectionId = connectionId;
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rawPacket"></param>
        /// <param name="hostId"></param>
        /// <param name="connectionId"></param>
        private void OnPlayerMovePacket(IPacket rawPacket, int hostId, int connectionId)
        {
            var packet = rawPacket as Server.Packet.PlayerMovePacket;
            if (packet == null)
            {
                return;
            }

            var remoteConnectionId = packet.ConnectionId;
            if (!m_remotePlayers.ContainsKey(remoteConnectionId))
            {
                return;
            }

            var remotePlayer = m_remotePlayers[remoteConnectionId];
            remotePlayer.HandleMovePacket(packet);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rawPacket"></param>
        /// <param name="hostId"></param>
        /// <param name="connectionId"></param>
        private void OnPlayerDisconnectPacket(IPacket rawPacket, int hostId, int connectionId)
        {
            var packet = rawPacket as Server.Packet.PlayerDisconnectPacket;
            if (packet == null)
            {
                return;
            }

            var remoteConnectionId = packet.ConnectionId;
            if (!m_remotePlayers.ContainsKey(remoteConnectionId))
            {
                return;
            }

            var remotePlayer = m_remotePlayers[remoteConnectionId];
            GameObject.Destroy(remotePlayer.gameObject);

            m_remotePlayers.Remove(remoteConnectionId);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rawPacket"></param>
        /// <param name="hostId"></param>
        /// <param name="connectionId"></param>
        private void OnPlayerHandshakePacket(IPacket rawPacket, int hostId, int connectionId)
        {
            var packet = rawPacket as Server.Packet.PlayerHandshakePacket;
            if (packet == null)
            {
                return;
            }

            Debug.Log(string.Format("Client: Recieved PlayerHandshakePacket.\nAllowed: {0}, Error: {1}", packet.AllowConnection, packet.ErrorMessage));

            if (!packet.AllowConnection)
            {
                // TODO: Show error ui
                Application.LoadLevel("Menu");
            }

            var navAgent = this.GetComponent<NavMeshAgent>();
            navAgent.enabled = false;

            var spawnPoint = packet.GetPosition();
            this.transform.position = spawnPoint;

            navAgent.enabled = true;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rawPacket"></param>
        /// <param name="hostId"></param>
        /// <param name="connectionId"></param>
        private void OnMobSpawnPacket(IPacket rawPacket, int hostId, int connectionId)
        {
            var packet = rawPacket as Server.Packet.MobSpawnPacket;
            if (packet == null)
            {
                return;
            }

            if (m_mobs.ContainsKey(packet.ID))
            {
                // This mob already exists
                return;
            }

            var mobTypePrefab = this.MobPrefabs.FirstOrDefault(x => x.name.Equals(packet.MobType, StringComparison.OrdinalIgnoreCase));
            if (mobTypePrefab == null)
            {
                // Mob type not registered on client
                return;
            }

            var spawnLocation = packet.GetPosition();
            var newMob = (Common.Mob)GameObject.Instantiate(mobTypePrefab, spawnLocation, Quaternion.identity); // Initial rotation should be in spawn packet
            newMob.ID = packet.ID;
            m_mobs[packet.ID] = newMob;

            newMob.transform.parent = this.MobContainer;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rawPacket"></param>
        /// <param name="hostId"></param>
        /// <param name="connectionId"></param>
        private void OnPlayerChatPacket(IPacket rawPacket, int hostId, int connectionId)
        {
            var packet = rawPacket as Server.Packet.PlayerChatPacket;
            if (packet == null)
            {
                return;
            }

            var remoteConnectionId = packet.ConnectionId;
            if (!m_remotePlayers.ContainsKey(remoteConnectionId))
            {
                return;
            }

            var remotePlayer = m_remotePlayers[remoteConnectionId];
            var chatBox = GameObject.FindObjectOfType<Chat.ChatInputField>();
            chatBox.HandleChatPacket(remotePlayer, packet.ChatMessage);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rawPacket"></param>
        /// <param name="hostId"></param>
        /// <param name="connectionId"></param>
        private void OnMobMovePacket(IPacket rawPacket, int hostId, int connectionId)
        {
            var packet = rawPacket as Server.Packet.MobMovePacket;
            if (packet == null)
            {
                return;
            }

            if (!m_mobs.ContainsKey(packet.MobID))
            {
                return;
            }

            var mob = m_mobs[packet.MobID];
            mob.HandleMovePacket(packet);
        }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="packet"></param>
 public void QueuePacket(IPacket packet)
 {
     m_packetQueue[packet.PacketType] = packet;
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="type"></param>
 /// <param name="packet"></param>
 /// <param name="connectionId"></param>
 public ServerPacket(ServerPacketType type, IPacket packet, IEnumerable<int> excluding)
     : this(type, packet)
 {
     this.Excluding = excluding;
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="packet"></param>
 public void QueuePacketAll(IPacket packet)
 {
     m_packetQueue.Add(new ServerPacket(ServerPacketType.ToAll, packet));
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rawPacket"></param>
        /// <param name="hostId"></param>
        /// <param name="connectionId"></param>
        private void OnPlayerJoinPacket(IPacket rawPacket, int hostId, int connectionId)
        {
            var packet = rawPacket as Server.Packet.PlayerJoinPacket;
            if (packet == null)
            {
                return;
            }

            var remotePlayer = (GameObject)GameObject.Instantiate(RemotePlayerPrefab, packet.GetPosition(), Quaternion.identity);
            remotePlayer.name = "RemotePlayer " + packet.Username;

            var remoteClient = remotePlayer.GetComponent<RemoteClient>();
            remoteClient.Username = packet.Username;

            m_remotePlayers[packet.ConnectionId] = remoteClient;
        }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="packet"></param>
 public void QueuePacketAllExcluding(IPacket packet, IEnumerable<int> excludedConnectionIds)
 {
     m_packetQueue.Add(new ServerPacket(ServerPacketType.ToAllExcluding, packet, excludedConnectionIds));
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="type"></param>
 /// <param name="packet"></param>
 public ServerPacket(ServerPacketType type, IPacket packet)
 {
     this.SendType = type;
     this.Packet = packet;
 }