/// <summary>
        /// Start the Forge Networking server on this Facepunch Steamworks client
        /// </summary>
        /// <param name="haveLobby">Boolean used internally to tell whether we have already created the lobby</param>
        public void Host(bool haveLobby = false)
        {
            if (Disposed)
            {
                throw new ObjectDisposedException("FacepunchP2PServer", "This object has been disposed and can not be used to connect, please use a new FacepunchP2PServer");
            }

            try
            {
                if (!haveLobby)
                {
                    CreateLobby();
                    return;
                }

                var selfSteamId = SteamClient.SteamId;
                Client = new CachedFacepunchP2PClient(selfSteamId);
                Me     = new NetworkingPlayer(ServerPlayerCounter++, selfSteamId, true, this)
                {
                    InstanceGuid = InstanceGuid.ToString()
                };

                // Do any generic initialization in result of the successful bind
                OnBindSuccessful();

                // Create the thread that will be listening for new data from connected clients and start its execution
                Task.Queue(ReadClients);

                // Create the thread that will check for player timeouts
                Task.Queue(() =>
                {
                    commonServerLogic.CheckClientTimeout((player) =>
                    {
                        Disconnect(player, true);
                        OnPlayerTimeout(player);
                        CleanupDisconnections();
                    });
                });

                // Let myself know I connected successfully
                OnPlayerConnected(Me);
                // Set myself as a connected client
                Me.Connected = true;
                OnServerCreated();
                StartAcceptingConnections();
            }
            catch (Exception e)
            {
                Logging.BMSLog.LogException(e);
                // Do any generic initialization in result of the binding failure
                OnBindFailure();

                throw new FailedBindingException("Failed to bind to SteamClient.SteamId, see inner exception", e);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Connect this FacepunchP2PClient directly to a steam user's FacepunchP2PServer with SteamId specified
        /// </summary>
        /// <param name="hostId">The host's <see cref="SteamId"/> SteamId object</param>
        /// <param name="pendCreates">Immediately set the NetWorker::PendCreates to true</param>
        public void Connect(SteamId hostId, bool pendCreates = false)
        {
            if (Disposed)
            {
                throw new ObjectDisposedException("FacepunchP2PClient", "This object has been disposed and can not be used to connect, please use a new FacepunchP2PClient");
            }

            // By default pending creates should be true and flushed when ready
            if (!pendCreates)
            {
                PendCreates = true;
            }

            try
            {
                ushort clientPort = DEFAULT_PORT;

                // Make sure not to listen on the same port as the server for local networks
                if (clientPort == DEFAULT_PORT)
                {
                    clientPort++;
                }

                Client = new CachedFacepunchP2PClient(hostId);

                // Do any generic initialization in result of the successful bind
                OnBindSuccessful();

                // Get a random hash key that needs to be used for validating that the server was connected to
                headerHash = Websockets.HeaderHashKey();

                // This is a typical Websockets accept header to be validated
                byte[] connectHeader = Websockets.ConnectionHeader(headerHash, DEFAULT_PORT);

                // Setup the identity of the server as a player
                server = new NetworkingPlayer(0, hostId, true, this);

                // Create the thread that will be listening for new data from connected clients and start its execution
                Task.Queue(ReadNetwork);

                //Let myself know I connected successfully
                OnPlayerConnected(server);

                // Set myself as a connected client
                server.Connected = true;

                //Set the port
                SetPort(clientPort);

                int connectCounter = 0;
                Task.Queue(() =>
                {
                    do
                    {
                        // Send the accept headers to the server to validate
                        Client.Send(connectHeader, connectHeader.Length, hostId, P2PSend.Reliable);
                        Thread.Sleep(3000);
                    } while (!headerExchanged && IsBound && ++connectCounter < CONNECT_TRIES);

                    if (connectCounter >= CONNECT_TRIES)
                    {
                        if (connectAttemptFailed != null)
                        {
                            connectAttemptFailed(this);
                        }
                    }
                });
            }
            catch (Exception e)
            {
                Logging.BMSLog.LogException(e);
                // Do any generic initialization in result of the binding failure
                OnBindFailure();

                throw new FailedBindingException("Failed to bind to server's SteamId, see inner exception", e);
            }
        }