Пример #1
0
        private void HandleClientIncomingData(Client client, NetIncomingMessage msg)
        {
            var packetType = (PacketType)msg.ReadInt32();

            switch (packetType)
            {
            case PacketType.ChatData:
            {
                // TODO: This code really could use refactoring.. right now only trying to make sure this all works on .NET Core and fixing small issues.
                var len      = msg.ReadInt32();
                var chatData = Util.DeserializeBinary <ChatData>(msg.ReadBytes(len));
                if (chatData != null)
                {
                    // Plugin chat handling
                    var chatPluginResult = GameEvents.ChatMessage(client, chatData);
                    if (!chatPluginResult.ContinueServerProc)
                    {
                        return;
                    }
                    chatData = chatPluginResult.Data;

                    // Command handling
                    if (chatData.Message.StartsWith("/"))
                    {
                        var cmdArgs = chatData.Message.Split(' ');
                        var cmdName = cmdArgs[0].Remove(0, 1);
                        if (Commands.ContainsKey(cmdName))
                        {
                            Commands[cmdName].OnCommandExec(client, chatData);
                            return;
                        }
                        SendChatMessageToPlayer(client, "Command not found");
                        return;
                    }
                    var chatMsg = new ChatMessage(chatData, client);
                    if (!chatMsg.Suppress)
                    {
                        chatData.Id     = client.NetConnection.RemoteUniqueIdentifier;
                        chatData.Sender = "";
                        if (!string.IsNullOrWhiteSpace(chatMsg.Prefix))
                        {
                            chatData.Sender += "[" + chatMsg.Prefix + "] ";
                        }
                        chatData.Sender += chatMsg.Sender.DisplayName;

                        if (!string.IsNullOrWhiteSpace(chatMsg.Suffix))
                        {
                            chatData.Sender += $" ({chatMsg.Suffix}) ";
                        }
                        SendToAll(chatData, PacketType.ChatData, true);
                        logger.LogInformation($"[Chat] <{chatData.Sender}>: {chatData.Message}");
                    }
                }
            }
            break;

            case PacketType.VehiclePositionData:
            {
                var len         = msg.ReadInt32();
                var vehicleData = Util.DeserializeBinary <VehicleData>(msg.ReadBytes(len));
                if (vehicleData != null)
                {
                    var vehiclePluginResult = GameEvents.VehicleDataUpdate(client, vehicleData);
                    if (!vehiclePluginResult.ContinueServerProc)
                    {
                        return;
                    }
                    vehicleData = vehiclePluginResult.Data;

                    vehicleData.Id      = client.NetConnection.RemoteUniqueIdentifier;
                    vehicleData.Name    = client.Name;
                    vehicleData.Latency = client.Latency;

                    client.Health            = vehicleData.PlayerHealth;
                    client.LastKnownPosition = vehicleData.Position;
                    client.IsInVehicle       = false;

                    SendToAll(vehicleData, PacketType.VehiclePositionData, false, client);
                }
            }
            break;

            case PacketType.PedPositionData:
            {
                var len        = msg.ReadInt32();
                var pedPosData = Util.DeserializeBinary <PedData>(msg.ReadBytes(len));
                if (pedPosData != null)
                {
                    var pedPluginResult = GameEvents.PedDataUpdate(client, pedPosData);
                    if (!pedPluginResult.ContinueServerProc)
                    {
                        return;
                    }
                    pedPosData = pedPluginResult.Data;

                    pedPosData.Id      = client.NetConnection.RemoteUniqueIdentifier;
                    pedPosData.Name    = client.DisplayName;
                    pedPosData.Latency = client.Latency;

                    client.Health            = pedPosData.PlayerHealth;
                    client.LastKnownPosition = pedPosData.Position;
                    client.IsInVehicle       = false;

                    SendToAll(pedPosData, PacketType.PedPositionData, false, client);
                }
            }
            break;

            case PacketType.NpcVehPositionData:
            {
                var len     = msg.ReadInt32();
                var vehData = Util.DeserializeBinary <VehicleData>(msg.ReadBytes(len));

                if (vehData != null)
                {
                    var pluginVehData = GameEvents.NpcVehicleDataUpdate(client, vehData);
                    if (!pluginVehData.ContinueServerProc)
                    {
                        return;
                    }
                    vehData = pluginVehData.Data;

                    vehData.Id = client.NetConnection.RemoteUniqueIdentifier;
                    SendToAll(vehData, PacketType.NpcVehPositionData, false, client);
                }
            }
            break;

            case PacketType.NpcPedPositionData:
            {
                var len     = msg.ReadInt32();
                var pedData = Util.DeserializeBinary <PedData>(msg.ReadBytes(len));
                if (pedData != null)
                {
                    var pluginPedData = GameEvents.NpcPedDataUpdate(client, pedData);
                    if (!pluginPedData.ContinueServerProc)
                    {
                        return;
                    }
                    pedData = pluginPedData.Data;

                    pedData.Id = msg.SenderConnection.RemoteUniqueIdentifier;
                }
                SendToAll(pedData, PacketType.NpcPedPositionData, false, client);
            }
            break;

            case PacketType.WorldSharingStop:
            {
                GameEvents.WorldSharingStop(client);
                var dcObj = new PlayerDisconnect()
                {
                    Id = client.NetConnection.RemoteUniqueIdentifier
                };
                SendToAll(dcObj, PacketType.WorldSharingStop, true);
            }
            break;

            case PacketType.NativeResponse:
            {
                var len            = msg.ReadInt32();
                var nativeResponse = Util.DeserializeBinary <NativeResponse>(msg.ReadBytes(len));
                if (nativeResponse == null || !_callbacks.ContainsKey(nativeResponse.Id))
                {
                    return;
                }
                object response = nativeResponse.Response;
                if (response is IntArgument)
                {
                    response = ((IntArgument)response).Data;
                }
                else if (response is UIntArgument)
                {
                    response = ((UIntArgument)response).Data;
                }
                else if (response is StringArgument)
                {
                    response = ((StringArgument)response).Data;
                }
                else if (response is FloatArgument)
                {
                    response = ((FloatArgument)response).Data;
                }
                else if (response is BooleanArgument)
                {
                    response = ((BooleanArgument)response).Data;
                }
                else if (response is Vector3Argument)
                {
                    var tmp = (Vector3Argument)response;
                    response = new Vector3()
                    {
                        X = tmp.X,
                        Y = tmp.Y,
                        Z = tmp.Z
                    };
                }
                _callbacks[nativeResponse.Id].Invoke(response);
                _callbacks.Remove(nativeResponse.Id);
            }
            break;

            case PacketType.PlayerSpawned:
            {
                GameEvents.PlayerSpawned(client);
                logger.LogInformation("Player spawned: " + client.DisplayName);
            }
            break;

            // The following is normally only received on the client.
            case PacketType.PlayerDisconnect:
                break;

            case PacketType.DiscoveryResponse:
                break;

            case PacketType.ConnectionRequest:
                break;

            case PacketType.NativeCall:
                break;

            case PacketType.NativeTick:
                break;

            case PacketType.NativeTickRecall:
                break;

            case PacketType.NativeOnDisconnect:
                break;

            case PacketType.NativeOnDisconnectRecall:
                break;

            default:
                // ReSharper disable once NotResolvedInText
                // resharper wants to see a variable name in the below... w/e.
                throw new ArgumentOutOfRangeException("Received unknown packet type. Server out of date or modded client?");
            }
        }
Пример #2
0
        public void Tick()
        {
            if (AnnounceSelf && DateTime.Now.Subtract(_lastAnnounceDateTime).TotalMinutes >= 5)
            {
                _lastAnnounceDateTime = DateTime.Now;
                AnnounceSelfToMaster();
            }

            NetIncomingMessage msg;

            while ((msg = Server.ReadMessage()) != null)
            {
                Client client = null;
                lock (Clients)
                {
                    foreach (Client c in Clients)
                    {
                        if (c != null && c.NetConnection != null &&
                            c.NetConnection.RemoteUniqueIdentifier != 0 &&
                            msg.SenderConnection != null &&
                            c.NetConnection.RemoteUniqueIdentifier == msg.SenderConnection.RemoteUniqueIdentifier)
                        {
                            client = c;
                            break;
                        }
                    }
                }

                if (client == null)
                {
                    client = new Client(msg.SenderConnection);
                }

                switch (msg.MessageType)
                {
                case NetIncomingMessageType.UnconnectedData:
                    var isPing = msg.ReadString();
                    if (isPing == "ping")
                    {
                        Console.WriteLine("INFO: ping received from " + msg.SenderEndPoint.Address.ToString());
                        var pong = Server.CreateMessage();
                        pong.Write("pong");
                        Server.SendMessage(pong, client.NetConnection, NetDeliveryMethod.ReliableOrdered);
                    }
                    if (isPing == "query")
                    {
                        int playersonline = 0;
                        lock (Clients) playersonline = Clients.Count;
                        Console.WriteLine("INFO: query received from " + msg.SenderEndPoint.Address.ToString());
                        var pong = Server.CreateMessage();
                        pong.Write(Name + "%" + PasswordProtected + "%" + playersonline + "%" + MaxPlayers + "%" + GamemodeName);
                        Server.SendMessage(pong, client.NetConnection, NetDeliveryMethod.ReliableOrdered);
                    }
                    break;

                case NetIncomingMessageType.VerboseDebugMessage:
                case NetIncomingMessageType.DebugMessage:
                case NetIncomingMessageType.WarningMessage:
                case NetIncomingMessageType.ErrorMessage:
                    Console.WriteLine(msg.ReadString());
                    break;

                case NetIncomingMessageType.ConnectionLatencyUpdated:
                    client.Latency = msg.ReadFloat();
                    break;

                case NetIncomingMessageType.ConnectionApproval:
                    var type    = msg.ReadInt32();
                    var leng    = msg.ReadInt32();
                    var connReq = DeserializeBinary <ConnectionRequest>(msg.ReadBytes(leng)) as ConnectionRequest;
                    if (connReq == null)
                    {
                        client.NetConnection.Deny("Connection Object is null");
                        Server.Recycle(msg);
                        continue;
                    }

                    if ((ScriptVersion)connReq.ScriptVersion == ScriptVersion.Unknown)
                    {
                        client.NetConnection.Deny("Unknown version. Please update your client.");
                        Server.Recycle(msg);
                        continue;
                    }

                    int clients = 0;
                    lock (Clients) clients = Clients.Count;
                    if (clients < MaxPlayers)
                    {
                        if (PasswordProtected && !string.IsNullOrWhiteSpace(Password))
                        {
                            if (Password != connReq.Password)
                            {
                                client.NetConnection.Deny("Wrong password.");
                                Console.WriteLine("Player connection refused: wrong password.");

                                if (_gamemode != null)
                                {
                                    _gamemode.OnConnectionRefused(client, "Wrong password");
                                }
                                if (_filterscripts != null)
                                {
                                    _filterscripts.ForEach(fs => fs.OnConnectionRefused(client, "Wrong password"));
                                }

                                Server.Recycle(msg);

                                continue;
                            }
                        }

                        lock (Clients)
                        {
                            int    duplicate   = 0;
                            string displayname = connReq.DisplayName;
                            while (AllowDisplayNames && Clients.Any(c => c.DisplayName == connReq.DisplayName))
                            {
                                duplicate++;

                                connReq.DisplayName = displayname + " (" + duplicate + ")";
                            }

                            Clients.Add(client);
                        }

                        client.Name        = connReq.Name;
                        client.DisplayName = AllowDisplayNames ? connReq.DisplayName : connReq.Name;

                        if (client.RemoteScriptVersion != (ScriptVersion)connReq.ScriptVersion)
                        {
                            client.RemoteScriptVersion = (ScriptVersion)connReq.ScriptVersion;
                        }
                        if (client.GameVersion != connReq.GameVersion)
                        {
                            client.GameVersion = connReq.GameVersion;
                        }

                        var channelHail = Server.CreateMessage();
                        channelHail.Write(GetChannelIdForConnection(client));
                        client.NetConnection.Approve(channelHail);

                        if (_gamemode != null)
                        {
                            _gamemode.OnIncomingConnection(client);
                        }
                        if (_filterscripts != null)
                        {
                            _filterscripts.ForEach(fs => fs.OnIncomingConnection(client));
                        }

                        Console.WriteLine("New incoming connection: " + client.Name + " (" + client.DisplayName + ")");
                    }
                    else
                    {
                        client.NetConnection.Deny("No available player slots.");
                        Console.WriteLine("Player connection refused: server full.");
                        if (_gamemode != null)
                        {
                            _gamemode.OnConnectionRefused(client, "Server is full");
                        }
                        if (_filterscripts != null)
                        {
                            _filterscripts.ForEach(fs => fs.OnConnectionRefused(client, "Server is full"));
                        }
                    }
                    break;

                case NetIncomingMessageType.StatusChanged:
                    var newStatus = (NetConnectionStatus)msg.ReadByte();

                    if (newStatus == NetConnectionStatus.Connected)
                    {
                        bool sendMsg = true;

                        if (_gamemode != null)
                        {
                            sendMsg = sendMsg && _gamemode.OnPlayerConnect(client);
                        }
                        if (_filterscripts != null)
                        {
                            _filterscripts.ForEach(fs => sendMsg = sendMsg && fs.OnPlayerConnect(client));
                        }

                        if (sendMsg)
                        {
                            SendNotificationToAll("Player ~h~" + client.DisplayName + "~h~ has connected.");
                        }

                        Console.WriteLine("New player connected: " + client.Name + " (" + client.DisplayName + ")");
                    }
                    else if (newStatus == NetConnectionStatus.Disconnected)
                    {
                        lock (Clients)
                        {
                            if (Clients.Contains(client))
                            {
                                var sendMsg = true;

                                if (_gamemode != null)
                                {
                                    sendMsg = sendMsg && _gamemode.OnPlayerDisconnect(client);
                                }
                                if (_filterscripts != null)
                                {
                                    _filterscripts.ForEach(fs => sendMsg = sendMsg && fs.OnPlayerDisconnect(client));
                                }

                                if (sendMsg)
                                {
                                    SendNotificationToAll("Player ~h~" + client.DisplayName + "~h~ has disconnected.");
                                }

                                var dcObj = new PlayerDisconnect()
                                {
                                    Id = client.NetConnection.RemoteUniqueIdentifier,
                                };

                                SendToAll(dcObj, PacketType.PlayerDisconnect, true);

                                Console.WriteLine("Player disconnected: " + client.Name + " (" + client.DisplayName + ")");

                                Clients.Remove(client);
                            }
                        }
                    }
                    break;

                case NetIncomingMessageType.DiscoveryRequest:
                    NetOutgoingMessage response = Server.CreateMessage();
                    var obj = new DiscoveryResponse();
                    obj.ServerName        = Name;
                    obj.MaxPlayers        = MaxPlayers;
                    obj.PasswordProtected = PasswordProtected;
                    obj.Gamemode          = GamemodeName;
                    lock (Clients) obj.PlayerCount = Clients.Count;
                    obj.Port = Port;

                    var bin = SerializeBinary(obj);

                    response.Write((int)PacketType.DiscoveryResponse);
                    response.Write(bin.Length);
                    response.Write(bin);

                    Server.SendDiscoveryResponse(response, msg.SenderEndPoint);
                    break;

                case NetIncomingMessageType.Data:
                    var packetType = (PacketType)msg.ReadInt32();

                    switch (packetType)
                    {
                    case PacketType.ChatData:
                    {
                        try
                        {
                            var len  = msg.ReadInt32();
                            var data = DeserializeBinary <ChatData>(msg.ReadBytes(len)) as ChatData;
                            if (data != null)
                            {
                                var pass = true;
                                if (_gamemode != null)
                                {
                                    pass = _gamemode.OnChatMessage(client, data.Message);
                                }

                                if (_filterscripts != null)
                                {
                                    _filterscripts.ForEach(fs => pass = pass && fs.OnChatMessage(client, data.Message));
                                }

                                if (pass)
                                {
                                    data.Id     = client.NetConnection.RemoteUniqueIdentifier;
                                    data.Sender = client.DisplayName;
                                    SendToAll(data, PacketType.ChatData, true);
                                    Console.WriteLine(data.Sender + ": " + data.Message);
                                }
                            }
                        }
                        catch (IndexOutOfRangeException)
                        { }
                    }
                    break;

                    case PacketType.VehiclePositionData:
                    {
                        try
                        {
                            var len  = msg.ReadInt32();
                            var data =
                                DeserializeBinary <VehicleData>(msg.ReadBytes(len)) as
                                VehicleData;
                            if (data != null)
                            {
                                data.Id      = client.NetConnection.RemoteUniqueIdentifier;
                                data.Name    = client.DisplayName;
                                data.Latency = client.Latency;

                                client.Health            = data.PlayerHealth;
                                client.LastKnownPosition = data.Position;
                                client.VehicleHealth     = data.VehicleHealth;
                                client.IsInVehicle       = true;

                                SendToAll(data, PacketType.VehiclePositionData, false, client);
                            }
                        }
                        catch (IndexOutOfRangeException)
                        { }
                    }
                    break;

                    case PacketType.PedPositionData:
                    {
                        try
                        {
                            var len  = msg.ReadInt32();
                            var data = DeserializeBinary <PedData>(msg.ReadBytes(len)) as PedData;
                            if (data != null)
                            {
                                data.Id      = client.NetConnection.RemoteUniqueIdentifier;
                                data.Name    = client.DisplayName;
                                data.Latency = client.Latency;

                                client.Health            = data.PlayerHealth;
                                client.LastKnownPosition = data.Position;
                                client.IsInVehicle       = false;

                                SendToAll(data, PacketType.PedPositionData, false, client);
                            }
                        }
                        catch (IndexOutOfRangeException)
                        { }
                    }
                    break;

                    case PacketType.NpcVehPositionData:
                    {
                        try
                        {
                            var len  = msg.ReadInt32();
                            var data =
                                DeserializeBinary <VehicleData>(msg.ReadBytes(len)) as
                                VehicleData;
                            if (data != null)
                            {
                                data.Id = client.NetConnection.RemoteUniqueIdentifier;
                                SendToAll(data, PacketType.NpcVehPositionData, false, client);
                            }
                        }
                        catch (IndexOutOfRangeException)
                        { }
                    }
                    break;

                    case PacketType.NpcPedPositionData:
                    {
                        try
                        {
                            var len  = msg.ReadInt32();
                            var data =
                                DeserializeBinary <PedData>(msg.ReadBytes(len)) as PedData;
                            if (data != null)
                            {
                                data.Id = msg.SenderConnection.RemoteUniqueIdentifier;
                                SendToAll(data, PacketType.NpcPedPositionData, false, client);
                            }
                        }
                        catch (IndexOutOfRangeException)
                        { }
                    }
                    break;

                    case PacketType.WorldSharingStop:
                    {
                        var dcObj = new PlayerDisconnect()
                        {
                            Id = client.NetConnection.RemoteUniqueIdentifier,
                        };
                        SendToAll(dcObj, PacketType.WorldSharingStop, true);
                    }
                    break;

                    case PacketType.NativeResponse:
                    {
                        var len  = msg.ReadInt32();
                        var data = DeserializeBinary <NativeResponse>(msg.ReadBytes(len)) as NativeResponse;
                        if (data == null || !_callbacks.ContainsKey(data.Id))
                        {
                            continue;
                        }
                        object resp = null;
                        if (data.Response is IntArgument)
                        {
                            resp = ((IntArgument)data.Response).Data;
                        }
                        else if (data.Response is UIntArgument)
                        {
                            resp = ((UIntArgument)data.Response).Data;
                        }
                        else if (data.Response is StringArgument)
                        {
                            resp = ((StringArgument)data.Response).Data;
                        }
                        else if (data.Response is FloatArgument)
                        {
                            resp = ((FloatArgument)data.Response).Data;
                        }
                        else if (data.Response is BooleanArgument)
                        {
                            resp = ((BooleanArgument)data.Response).Data;
                        }
                        else if (data.Response is Vector3Argument)
                        {
                            var tmp = (Vector3Argument)data.Response;
                            resp = new Vector3()
                            {
                                X = tmp.X,
                                Y = tmp.Y,
                                Z = tmp.Z,
                            };
                        }
                        if (_callbacks.ContainsKey(data.Id))
                        {
                            _callbacks[data.Id].Invoke(resp);
                        }
                        _callbacks.Remove(data.Id);
                    }
                    break;

                    case PacketType.PlayerKilled:
                    {
                        if (_gamemode != null)
                        {
                            _gamemode.OnPlayerKilled(client);
                        }
                        if (_filterscripts != null)
                        {
                            _filterscripts.ForEach(fs => fs.OnPlayerKilled(client));
                        }
                    }
                    break;
                    }
                    break;

                default:
                    Console.WriteLine("WARN: Unhandled type: " + msg.MessageType);
                    break;
                }
                Server.Recycle(msg);
            }
            if (_gamemode != null)
            {
                _gamemode.OnTick();
            }
            if (_filterscripts != null)
            {
                _filterscripts.ForEach(fs => fs.OnTick());
            }
        }
Пример #3
0
        private void HandleClientStatusChange(Client client, NetIncomingMessage msg)
        {
            var newStatus = (NetConnectionStatus)msg.ReadByte();

            switch (newStatus)
            {
            case NetConnectionStatus.Connected:
                logger.LogInformation($"Connected: {client.DisplayName}@{msg.SenderEndPoint.Address.ToString()}");
                SendNotificationToAll($"Player connected: {client.DisplayName}");
                break;

            case NetConnectionStatus.Disconnected:
                lock (Clients)
                {
                    if (Clients.Contains(client))
                    {
                        if (!client.Silent)
                        {
                            if (client.Kicked)
                            {
                                if (string.IsNullOrEmpty(client.KickReason))
                                {
                                    client.KickReason = "Unknown";
                                }
                                SendNotificationToAll(
                                    $"Player kicked: {client.DisplayName} - Reason: {client.KickReason}");
                            }
                            else
                            {
                                SendNotificationToAll(
                                    $"Player disconnected: {client.DisplayName}");
                            }
                        }
                        var dcMsg = new PlayerDisconnect()
                        {
                            Id = client.NetConnection.RemoteUniqueIdentifier
                        };

                        SendToAll(dcMsg, PacketType.PlayerDisconnect, true);

                        if (client.Kicked)
                        {
                            logger.LogInformation(
                                $"Player kicked: {client.DisplayName}@{msg.SenderEndPoint.Address.ToString()}");
                            LastKickedClient = client;
                            LastKickedIP     = client.NetConnection.RemoteEndPoint.ToString();
                        }
                        else
                        {
                            logger.LogInformation($"Player disconnected: {client.DisplayName}@{msg.SenderEndPoint.Address.ToString()}");
                        }
                        Clients.Remove(client);
                    }
                    break;
                }

            // resharper was bugging me about not having the below case statements
            case NetConnectionStatus.None:
            case NetConnectionStatus.InitiatedConnect:
            case NetConnectionStatus.ReceivedInitiation:
            case NetConnectionStatus.RespondedAwaitingApproval:
            case NetConnectionStatus.RespondedConnect:
            case NetConnectionStatus.Disconnecting:
            default:
                break;
            }
        }
Пример #4
0
        public void Tick()
        {
            if (DateTime.UtcNow.Day != _lastDay)
            {
                _lastDay = DateTime.UtcNow.Day;
                if (AnnounceSelf)
                {
                    AnnounceSelfToMaster();
                }
            }

            NetIncomingMessage msg;

            while ((msg = Server.ReadMessage()) != null)
            {
                switch (msg.MessageType)
                {
                case NetIncomingMessageType.UnconnectedData:
                    var isPing = msg.ReadString();
                    if (isPing == "ping")
                    {
                        Console.WriteLine("INFO: ping received from " + msg.SenderEndPoint.Address.ToString());
                        var pong = Server.CreateMessage();
                        pong.Write("pong");
                        Server.SendMessage(pong, msg.SenderConnection, NetDeliveryMethod.ReliableOrdered);
                    }
                    break;

                case NetIncomingMessageType.VerboseDebugMessage:
                case NetIncomingMessageType.DebugMessage:
                case NetIncomingMessageType.WarningMessage:
                case NetIncomingMessageType.ErrorMessage:
                    Console.WriteLine(msg.ReadString());
                    break;

                case NetIncomingMessageType.ConnectionLatencyUpdated:
                    var latency = msg.ReadFloat();
                    if (KnownLatencies.ContainsKey(msg.SenderConnection.RemoteUniqueIdentifier))
                    {
                        KnownLatencies[msg.SenderConnection.RemoteUniqueIdentifier] = latency;
                    }
                    else
                    {
                        KnownLatencies.Add(msg.SenderConnection.RemoteUniqueIdentifier, latency);
                    }
                    break;

                case NetIncomingMessageType.ConnectionApproval:
                    var type    = msg.ReadInt32();
                    var leng    = msg.ReadInt32();
                    var connReq = DeserializeBinary <ConnectionRequest>(msg.ReadBytes(leng)) as ConnectionRequest;
                    if (connReq == null)
                    {
                        msg.SenderConnection.Deny("Connection Object is null");
                        Server.Recycle(msg);
                        continue;
                    }

                    if (Clients.Count < MaxPlayers)
                    {
                        if (PasswordProtected && !string.IsNullOrWhiteSpace(Password))
                        {
                            if (Password != connReq.Password)
                            {
                                msg.SenderConnection.Deny("Wrong password.");
                                Console.WriteLine("Player connection refused: wrong password.");
                                if (_gamemode != null)
                                {
                                    _gamemode.OnConnectionRefused(msg.SenderConnection, "Wrong password");
                                }
                                if (_filterscripts != null)
                                {
                                    _filterscripts.ForEach(fs => fs.OnConnectionRefused(msg.SenderConnection, "Wrong password"));
                                }
                                Server.Recycle(msg);
                                continue;
                            }
                        }

                        Clients.Add(msg.SenderConnection);
                        if (NickNames.ContainsKey(msg.SenderConnection.RemoteUniqueIdentifier))
                        {
                            NickNames[msg.SenderConnection.RemoteUniqueIdentifier] = connReq.Name;
                        }
                        else
                        {
                            NickNames.Add(msg.SenderConnection.RemoteUniqueIdentifier, connReq.Name);
                        }

                        var channelHail = Server.CreateMessage();
                        channelHail.Write(GetChannelIdForConnection(msg.SenderConnection));
                        msg.SenderConnection.Approve(channelHail);

                        var chatObj = new ChatData()
                        {
                            Sender  = "SERVER",
                            Message =
                                "Player ~h~" + NickNames[msg.SenderConnection.RemoteUniqueIdentifier] +
                                "~h~ has connected.",
                        };

                        SendToAll(chatObj, PacketType.ChatData, 0);

                        Console.WriteLine("New player connected: " + NickNames[msg.SenderConnection.RemoteUniqueIdentifier]);

                        if (_gamemode != null)
                        {
                            _gamemode.OnPlayerConnect(msg.SenderConnection);
                        }
                        if (_filterscripts != null)
                        {
                            _filterscripts.ForEach(fs => fs.OnPlayerConnect(msg.SenderConnection));
                        }
                    }
                    else
                    {
                        msg.SenderConnection.Deny("No available player slots.");
                        Console.WriteLine("Player connection refused: server full.");
                        if (_gamemode != null)
                        {
                            _gamemode.OnConnectionRefused(msg.SenderConnection, "Server is full");
                        }
                        if (_filterscripts != null)
                        {
                            _filterscripts.ForEach(fs => fs.OnConnectionRefused(msg.SenderConnection, "Server is full"));
                        }
                    }
                    break;

                case NetIncomingMessageType.StatusChanged:
                    var newStatus = (NetConnectionStatus)msg.ReadByte();
                    if (newStatus == NetConnectionStatus.Disconnected && Clients.Contains(msg.SenderConnection))
                    {
                        var name = "";
                        if (NickNames.ContainsKey(msg.SenderConnection.RemoteUniqueIdentifier))
                        {
                            name = NickNames[msg.SenderConnection.RemoteUniqueIdentifier];
                        }

                        var chatObj = new ChatData()
                        {
                            Sender  = "SERVER",
                            Message =
                                "Player ~h~" + name +
                                "~h~ has disconnected.",
                        };

                        SendToAll(chatObj, PacketType.ChatData, 0);

                        var dcObj = new PlayerDisconnect()
                        {
                            Id = msg.SenderConnection.RemoteUniqueIdentifier,
                        };

                        SendToAll(dcObj, PacketType.PlayerDisconnect, 0);

                        Console.WriteLine("Player disconnected: " + name);

                        if (_gamemode != null)
                        {
                            _gamemode.OnPlayerDisconnect(msg.SenderConnection);
                        }
                        if (_filterscripts != null)
                        {
                            _filterscripts.ForEach(fs => fs.OnPlayerDisconnect(msg.SenderConnection));
                        }

                        Clients.Remove(msg.SenderConnection);
                        NickNames.Remove(msg.SenderConnection.RemoteUniqueIdentifier);
                    }
                    break;

                case NetIncomingMessageType.DiscoveryRequest:
                    NetOutgoingMessage response = Server.CreateMessage();
                    var obj = new DiscoveryResponse();
                    obj.ServerName        = Name;
                    obj.MaxPlayers        = MaxPlayers;
                    obj.PasswordProtected = PasswordProtected;
                    obj.PlayerCount       = Clients.Count;
                    obj.Port = Port;

                    var bin = SerializeBinary(obj);

                    response.Write((int)PacketType.DiscoveryResponse);
                    response.Write(bin.Length);
                    response.Write(bin);

                    Server.SendDiscoveryResponse(response, msg.SenderEndPoint);
                    break;

                case NetIncomingMessageType.Data:
                    var packetType = (PacketType)msg.ReadInt32();

                    switch (packetType)
                    {
                    case PacketType.ChatData:
                    {
                        try
                        {
                            var len  = msg.ReadInt32();
                            var data = DeserializeBinary <ChatData>(msg.ReadBytes(len)) as ChatData;
                            if (data != null)
                            {
                                var pass = true;
                                if (_gamemode != null)
                                {
                                    pass = _gamemode.OnChatMessage(msg.SenderConnection, data.Message);
                                }

                                if (_filterscripts != null)
                                {
                                    _filterscripts.ForEach(fs => pass = pass && fs.OnChatMessage(msg.SenderConnection, data.Message));
                                }

                                if (pass)
                                {
                                    data.Id     = msg.SenderConnection.RemoteUniqueIdentifier;
                                    data.Sender = NickNames[msg.SenderConnection.RemoteUniqueIdentifier];
                                    SendToAll(data, PacketType.ChatData, 0);
                                    Console.WriteLine(data.Sender + ": " + data.Message);
                                }
                            }
                        }
                        catch (IndexOutOfRangeException)
                        { }
                    }
                    break;

                    case PacketType.VehiclePositionData:
                    {
                        try
                        {
                            var name = "";
                            if (NickNames.ContainsKey(msg.SenderConnection.RemoteUniqueIdentifier))
                            {
                                name = NickNames[msg.SenderConnection.RemoteUniqueIdentifier];
                            }

                            var len  = msg.ReadInt32();
                            var data =
                                DeserializeBinary <VehicleData>(msg.ReadBytes(len)) as
                                VehicleData;
                            if (data != null)
                            {
                                data.Id   = msg.SenderConnection.RemoteUniqueIdentifier;
                                data.Name = name;
                                if (KnownLatencies.ContainsKey(msg.SenderConnection.RemoteUniqueIdentifier))
                                {
                                    data.Latency =
                                        KnownLatencies[msg.SenderConnection.RemoteUniqueIdentifier];
                                }

                                SendToAll(data, PacketType.VehiclePositionData, GetChannelIdForConnection(msg.SenderConnection), msg.SenderConnection.RemoteUniqueIdentifier);
                            }
                        }
                        catch (IndexOutOfRangeException)
                        { }
                    }
                    break;

                    case PacketType.PedPositionData:
                    {
                        try
                        {
                            var name = "";
                            if (NickNames.ContainsKey(msg.SenderConnection.RemoteUniqueIdentifier))
                            {
                                name = NickNames[msg.SenderConnection.RemoteUniqueIdentifier];
                            }
                            var len  = msg.ReadInt32();
                            var data =
                                DeserializeBinary <PedData>(msg.ReadBytes(len)) as PedData;
                            if (data != null)
                            {
                                data.Id   = msg.SenderConnection.RemoteUniqueIdentifier;
                                data.Name = name;
                                if (KnownLatencies.ContainsKey(msg.SenderConnection.RemoteUniqueIdentifier))
                                {
                                    data.Latency =
                                        KnownLatencies[msg.SenderConnection.RemoteUniqueIdentifier];
                                }
                                SendToAll(data, PacketType.PedPositionData, GetChannelIdForConnection(msg.SenderConnection), msg.SenderConnection.RemoteUniqueIdentifier);
                            }
                        }
                        catch (IndexOutOfRangeException)
                        { }
                    }
                    break;

                    case PacketType.NpcVehPositionData:
                    {
                        try
                        {
                            var len  = msg.ReadInt32();
                            var data =
                                DeserializeBinary <VehicleData>(msg.ReadBytes(len)) as
                                VehicleData;
                            if (data != null)
                            {
                                data.Id = msg.SenderConnection.RemoteUniqueIdentifier;
                                SendToAll(data, PacketType.NpcVehPositionData, GetChannelIdForConnection(msg.SenderConnection), msg.SenderConnection.RemoteUniqueIdentifier);
                            }
                        }
                        catch (IndexOutOfRangeException)
                        { }
                    }
                    break;

                    case PacketType.NpcPedPositionData:
                    {
                        try
                        {
                            var len  = msg.ReadInt32();
                            var data =
                                DeserializeBinary <PedData>(msg.ReadBytes(len)) as PedData;
                            if (data != null)
                            {
                                data.Id = msg.SenderConnection.RemoteUniqueIdentifier;
                                SendToAll(data, PacketType.NpcPedPositionData, GetChannelIdForConnection(msg.SenderConnection), msg.SenderConnection.RemoteUniqueIdentifier);
                            }
                        }
                        catch (IndexOutOfRangeException)
                        { }
                    }
                    break;

                    case PacketType.WorldSharingStop:
                    {
                        var dcObj = new PlayerDisconnect()
                        {
                            Id = msg.SenderConnection.RemoteUniqueIdentifier,
                        };
                        SendToAll(dcObj, PacketType.WorldSharingStop, 0);
                    }
                    break;

                    case PacketType.NativeResponse:
                    {
                        var len  = msg.ReadInt32();
                        var data = DeserializeBinary <NativeResponse>(msg.ReadBytes(len)) as NativeResponse;
                        if (data == null || !_callbacks.ContainsKey(data.Id))
                        {
                            continue;
                        }
                        object resp = null;
                        if (data.Response is IntArgument)
                        {
                            resp = ((IntArgument)data.Response).Data;
                        }
                        else if (data.Response is UIntArgument)
                        {
                            resp = ((UIntArgument)data.Response).Data;
                        }
                        else if (data.Response is StringArgument)
                        {
                            resp = ((StringArgument)data.Response).Data;
                        }
                        else if (data.Response is FloatArgument)
                        {
                            resp = ((FloatArgument)data.Response).Data;
                        }
                        else if (data.Response is BooleanArgument)
                        {
                            resp = ((BooleanArgument)data.Response).Data;
                        }
                        else if (data.Response is Vector3Argument)
                        {
                            var tmp = (Vector3Argument)data.Response;
                            resp = new Vector3()
                            {
                                X = tmp.X,
                                Y = tmp.Y,
                                Z = tmp.Z,
                            };
                        }
                        if (_callbacks.ContainsKey(data.Id))
                        {
                            _callbacks[data.Id].Invoke(resp);
                        }
                        _callbacks.Remove(data.Id);
                    }
                    break;

                    case PacketType.PlayerKilled:
                    {
                        if (_gamemode != null)
                        {
                            _gamemode.OnPlayerKilled(msg.SenderConnection);
                        }
                        if (_filterscripts != null)
                        {
                            _filterscripts.ForEach(fs => fs.OnPlayerKilled(msg.SenderConnection));
                        }
                    }
                    break;
                    }
                    break;

                default:
                    Console.WriteLine("WARN: Unhandled type: " + msg.MessageType);
                    break;
                }
                Server.Recycle(msg);
            }
            if (_gamemode != null)
            {
                _gamemode.OnTick();
            }
            if (_filterscripts != null)
            {
                _filterscripts.ForEach(fs => fs.OnTick());
            }
        }