Exemple #1
0
        // ReSharper restore FunctionNeverReturns
        private static void ListenForNewConnectionThread()
        {
            try
            {
                _tcpListener.Start();
            }
            catch (SocketException ex)
            {
                //todo: this will cause hard crash on the client, need a nicer way for the client to handle errors here
                if (ex.ErrorCode == 10048) throw new Exception("Only one server allowed at a time.");
            }

            while (true)
            {
                TcpClient client;
                System.Net.EndPoint endPoint;
                //blocks until a client has connected to the server
                try
                {
                    client = _tcpListener.AcceptTcpClient();
                    client.GetStream().WriteTimeout = 30000;
                    endPoint = client.Client.RemoteEndPoint;
                }
                catch
                {
                    WriteToServerConsoleLog("Failed to accept connection");
                    continue;
                }

                try
                {
                    WriteToServerConsoleLog(string.Format("Accepting connection from {0}", endPoint));
                    var connect = new Connect();
                    connect.AcceptNewConnection(client); //backdoor constructor because a player does not exist yet

                    var player = new NetworkPlayer(_nextPlayerId, connect.UserName, client) {Coords = new Coords(WorldData.SizeInBlocksX / 2f, 0, WorldData.SizeInBlocksZ / 2f)};
                    player.Coords.Yf = WorldData.Chunks[player.Coords].HeightMap[player.Coords.Xblock % Chunk.CHUNK_SIZE, player.Coords.Zblock % Chunk.CHUNK_SIZE] + 1; //start player on block above the surface
                    new Connect(player.Id, player.UserName, player.Coords) { ConnectedPlayer = player, Immediate = true }.Send();
                    _nextPlayerId++;

                    WriteToServerConsoleLog(String.Format("{0} (id {1}, ip {2}) Connected", player.UserName, player.Id, player.IpAddress));
                    var tcpThread = new Thread(() => PlayerThread(player)) { IsBackground = true, Name = "PlayerThread" };
                    tcpThread.Start();
                }
                catch (Exception ex)
                {
                    WriteToServerConsoleLog(string.Format("Failed to accept connection from {0}: {1}", endPoint, ex.Message));
                }
            }
            // ReSharper disable FunctionNeverReturns
        }
Exemple #2
0
        internal static void Connect(object sender, DoWorkEventArgs e)
        {
            var args = (object[])e.Argument;

            ServerIp   = (IPAddress)args[0];
            ServerPort = (ushort)args[1];
            Players.Clear();

            //when running client and server it takes a second for the server to start listening so make multiple connection attempts
            //when joining a server only try once because the attempt can take a long time ~22secs
            var connectionAttempts = (Config.IsSinglePlayer ? 4 : 1);

            for (var tries = 0; tries < connectionAttempts; tries++)
            {
                Settings.Launcher.UpdateProgressInvokable(string.Format("Connecting ({0} of {1})", tries + 1, connectionAttempts), tries + 1, connectionAttempts);
                try
                {
                    TcpClient = new TcpClient();
                    TcpClient.Connect(ServerIp, ServerPort);
                    break;
                }
                catch (SocketException)
                {
                    if (tries == connectionAttempts - 1)
                    {
                        throw new ServerConnectException();
                    }
                    Thread.Sleep(1000);                     //wait one second before trying again
                }
            }

            _tcpStream             = TcpClient.GetStream();
            _tcpStream.ReadTimeout = 15000;             //15s timeout during connect

            Settings.Launcher.UpdateProgressInvokable("Connected...", 0, 0);
            var connect = new Connect(-1, Config.UserName, new Coords());

            try
            {
                connect.Send();
                //server will immediately reply to tell us where we are and our Id, or disconnect us
                var actionTypebytes = new byte[sizeof(ushort)];
                var bytesRead       = 0;
                while (bytesRead < actionTypebytes.Length)
                {
                    bytesRead += _tcpStream.Read(actionTypebytes, bytesRead, actionTypebytes.Length - bytesRead);
                }
                var actionType = (ActionType)BitConverter.ToUInt16(actionTypebytes, 0);
                if (actionType == ActionType.Connect)
                {
                    connect.Receive();
                }
                else if (actionType == ActionType.Disconnect)
                {
                    var disconnect = new Disconnect();
                    disconnect.Receive();
                }
                else
                {
                    throw new Exception(string.Format("Received {0} packet out of order during connect sequence.", actionType));
                }

                Game.Player = Players[connect.PlayerId];

                //then a list of the players connected, followed by the world
                Settings.Launcher.UpdateProgressInvokable("Waiting for World...", 0, 0);
                while (!WorldData.IsLoaded)
                {
                    bytesRead = 0;
                    while (bytesRead < actionTypebytes.Length)
                    {
                        bytesRead += _tcpStream.Read(actionTypebytes, bytesRead, actionTypebytes.Length - bytesRead);
                    }

                    actionType = (ActionType)BitConverter.ToUInt16(actionTypebytes, 0);
                    switch (actionType)
                    {
                    case ActionType.Connect:
                        var recvPlayerList = new Connect();
                        recvPlayerList.Receive();
                        break;

                    case ActionType.GetWorld:
                        var getWorld = new GetWorld();
                        getWorld.Receive();
                        break;

                    default:
                        throw new Exception(string.Format("Received {0} packet out of order during connect sequence.", actionType));
                    }
                }
            }
            catch (Exception ex)
            {
                //HandleNetworkError(ex);
                throw new ServerConnectException(ex);
            }

            _tcpStream.ReadTimeout = -1;
            TcpClient.NoDelay      = true;
            var listenerThread = new Thread(ListenForServerMessageThread)
            {
                IsBackground = true, Name = "ListenForServerMessageThread"
            };

            listenerThread.Start();

            //send misc player information to server periodically (ie fps, memory).
            _playerInfoTimer = new System.Timers.Timer(PlayerInfo.PLAYER_INFO_SEND_INTERVAL);
            _playerInfoTimer.Start();
            _playerInfoTimer.Elapsed += _playerInfoTimer_Elapsed;             //wire elapsed event handler
        }
        internal static void Connect(object sender, DoWorkEventArgs e)
        {
            var args = (object[])e.Argument;
            ServerIp = (IPAddress)args[0];
            ServerPort = (ushort)args[1];
            Players.Clear();

            //when running client and server it takes a second for the server to start listening so make multiple connection attempts
            //when joining a server only try once because the attempt can take a long time ~22secs
            var connectionAttempts = (Config.IsSinglePlayer ? 4 : 1);
            for (var tries = 0; tries < connectionAttempts; tries++)
            {
                Settings.Launcher.UpdateProgressInvokable(string.Format("Connecting ({0} of {1})", tries + 1, connectionAttempts), tries + 1, connectionAttempts);
                try
                {
                    TcpClient = new TcpClient();
                    TcpClient.Connect(ServerIp, ServerPort);
                    break;
                }
                catch (SocketException)
                {
                    if (tries == connectionAttempts - 1) throw new ServerConnectException();
                    Thread.Sleep(1000); //wait one second before trying again
                }
            }

            _tcpStream = TcpClient.GetStream();
            _tcpStream.ReadTimeout = 15000; //15s timeout during connect

            Settings.Launcher.UpdateProgressInvokable("Connected...", 0, 0);
            var connect = new Connect(-1, Config.UserName, new Coords());
            try
            {
                connect.Send();
                //server will immediately reply to tell us where we are and our Id, or disconnect us
                var actionTypebytes = new byte[sizeof(ushort)];
                var bytesRead = 0;
                while (bytesRead < actionTypebytes.Length) bytesRead += _tcpStream.Read(actionTypebytes, bytesRead, actionTypebytes.Length - bytesRead);
                var actionType = (ActionType)BitConverter.ToUInt16(actionTypebytes, 0);
                if (actionType == ActionType.Connect)
                {
                    connect.Receive();
                }
                else if(actionType == ActionType.Disconnect)
                {
                    var disconnect = new Disconnect();
                    disconnect.Receive();
                }
                else
                {
                    throw new Exception(string.Format("Received {0} packet out of order during connect sequence.", actionType));
                }

                Game.Player = Players[connect.PlayerId];

                //then a list of the players connected, followed by the world
                Settings.Launcher.UpdateProgressInvokable("Waiting for World...", 0, 0);
                while (!WorldData.IsLoaded)
                {
                    bytesRead = 0;
                    while (bytesRead < actionTypebytes.Length) bytesRead += _tcpStream.Read(actionTypebytes, bytesRead, actionTypebytes.Length - bytesRead);

                    actionType = (ActionType)BitConverter.ToUInt16(actionTypebytes, 0);
                    switch (actionType)
                    {
                        case ActionType.Connect:
                            var recvPlayerList = new Connect();
                            recvPlayerList.Receive();
                            break;
                        case ActionType.GetWorld:
                            var getWorld = new GetWorld();
                            getWorld.Receive();
                            break;
                        default:
                            throw new Exception(string.Format("Received {0} packet out of order during connect sequence.", actionType));
                    }
                }
            }
            catch (Exception ex)
            {
                //HandleNetworkError(ex);
                throw new ServerConnectException(ex);
            }

            _tcpStream.ReadTimeout = -1;
            TcpClient.NoDelay = true;
            var listenerThread = new Thread(ListenForServerMessageThread) { IsBackground = true, Name = "ListenForServerMessageThread" };
            listenerThread.Start();

            //send misc player information to server periodically (ie fps, memory).
            _playerInfoTimer = new System.Timers.Timer(PlayerInfo.PLAYER_INFO_SEND_INTERVAL);
            _playerInfoTimer.Start();
            _playerInfoTimer.Elapsed += _playerInfoTimer_Elapsed; //wire elapsed event handler
        }