예제 #1
0
 private async Task <Result> InvokeOnServerShutdown()
 {
     _logger.LogDebug("Invoking OnServerShutdown event on port {Port}", Port);
     if (OnServerShutdown != null)
     {
         await OnServerShutdown.Invoke(this);
     }
     return(Result.Success());
 }
예제 #2
0
 public string ReceiveNewMessageFromServer()
 {
     try
     {
         while (true)
         {
             NetworkStream stream = client.GetStream();
             byte[]        data   = new byte[65536];
             int           bytes  = stream.Read(data, 0, data.Length);
             string        res    = Encoding.UTF8.GetString(data, 0, bytes);
             HandleMessage(res);
             OnMessageReceivedFromServer?.Invoke(this, new ClientSendMessageEventArgs()
             {
                 Time = DateTime.Now, Message = res
             });
         }
     }
     catch
     {
         OnServerShutdown?.Invoke(this, new EventArgs());
         IsConnected = false;
         return(null);
     }
 }
        public void Update()
        {
            if (m_state == ManagerState.Connected && m_prevState == ManagerState.Connecting)
            {
                // client just connected: invoke event handlers
                OnClientConnected?.Invoke();
            }
            else if (!m_connectionRequested && m_prevState == ManagerState.Connected)
            {
                // client about to disconnect: invoke event handlers
                OnClientDisconnecting?.Invoke();
                // transition to actual disconnect
                m_state = ManagerState.Disconnecting;
            }

            if (m_client.IsConnected())
            {
                // process server updates and events here so entity updates are processed in the render loop
                m_client.ProcessServerUpdates();
            }

            // relay events to handlers in render loop:
            // registered clients
            lock (m_registeredClients)
            {
                // transfer list content to temp list to avoid deadlock through event handler using client functions
                m_processingClients.AddRange(m_registeredClients);
                m_registeredClients.Clear();
            }
            if (m_processingClients.Count > 0)
            {
                // process newly registered client events
                foreach (ClientData client in m_processingClients)
                {
                    OnClientRegistered?.Invoke(client);
                }
                m_processingClients.Clear();
            }

            // unregistered clients
            lock (m_unregisteredClients)
            {
                // transfer list content to temp list to avoid deadlock through event handler using client functions
                m_processingClients.AddRange(m_unregisteredClients);
                m_unregisteredClients.Clear();
            }
            if (m_processingClients.Count > 0)
            {
                // process newly unregistered client events
                foreach (ClientData client in m_processingClients)
                {
                    OnClientUnregistered?.Invoke(client);
                }
                m_processingClients.Clear();
            }

            // publishing entities
            lock (m_publishedEntities)
            {
                // transfer list content to temp list to avoid deadlock through event handler using client functions
                m_processingEntities.AddRange(m_publishedEntities);
                m_publishedEntities.Clear();
            }
            if (m_processingEntities.Count > 0)
            {
                // process published entity events
                OnEntitiesPublished?.Invoke(m_processingEntities);
                m_processingEntities.Clear();
            }

            // revoking entities
            lock (m_revokedEntities)
            {
                // transfer list content to temp list to avoid deadlock through event handler using client functions
                m_processingEntities.AddRange(m_revokedEntities);
                m_revokedEntities.Clear();
            }
            if (m_processingEntities.Count > 0)
            {
                // process revoked entity events
                OnEntitiesRevoked?.Invoke(m_processingEntities);
                m_processingEntities.Clear();
            }

            lock (m_controlledEntities)
            {
                // transfer list content to temp list to avoid deadlock through event handler using client functions
                m_processingEntities.AddRange(m_controlledEntities);
                m_controlledEntities.Clear();
            }
            if (m_processingEntities.Count > 0)
            {
                // process control-changed entity events
                OnEntityControlChanged?.Invoke(m_processingEntities);
                m_processingEntities.Clear();
            }

            // broadcasts
            lock (m_broadcasts)
            {
                // transfer list content to temp list to avoid deadlock through event handler using client functions
                m_processingBroadcasts.AddRange(m_broadcasts);
                m_broadcasts.Clear();
            }
            if (m_processingBroadcasts.Count > 0)
            {
                // handle broadcasts
                foreach (Broadcast broadcast in m_processingBroadcasts)
                {
                    OnClientBroadcastReceived?.Invoke(broadcast);
                }
                m_processingBroadcasts.Clear();
            }

            lock (m_serverShutdown)
            {
                if (m_serverShutdown.Count > 0)
                {
                    bool restart = m_serverShutdown[0];
                    OnServerShutdown?.Invoke(restart);
                    StartCoroutine(AutoDisconnectAsync(restart));
                    m_serverShutdown.Clear();
                }
            }

            m_prevState = m_state;
        }
 public void Dispose()
 {
     Shutdown();
     OnServerShutdown?.Invoke(this);
 }
예제 #5
0
 internal static void RunServerShutdown() => OnServerShutdown?.Invoke();
예제 #6
0
        /// <summary>
        ///     Starts local server based on given or local configuration.
        /// </summary>
        public static void StartServer(QNetConfiguration configuration = null)
        {
            if (IsServerActive)
            {
                throw new InvalidOperationException(
                          "QNet is unable to start server while there is already active instance of server.");
            }
            if (configuration == null)
            {
                configuration = new QNetConfiguration();
            }

            var hostIsActive = IsHostActive;

            Server = new QNetServer();
            Server = InternalStartPeer(Server, configuration, () =>
            {
                QNetHandlerStack.RegisterServerHandlers(Server);
                OnServerRegisterHeaders?.Invoke();
            });
            OnServerPrepare?.Invoke();

            Server.OnBeforeMessage += message =>
            {
                // server should always send the server frame to the client!
                message.Write(QNetTime.ServerFrame);
            };

            Server.OnConnectionAuthorizing += (QNetConnection connection, QNetMessageWriter writer, ref bool refuse) =>
            {
                writer.WriteInt32(QNetTime.TickRate);
                writer.WriteUInt32(QNetTime.ServerFrame);

                OnServerAuthorizePlayer?.Invoke(connection, writer, ref refuse);
            };

            Server.OnConnectionReady += reader =>
            {
                // read player nickname and create its QNetPlayer instance
                var nickname = reader.ReadString();
                var token    = reader.ReadUInt32();
                var version  = reader.ReadString();
                if (JEMBuild.BuildVersion != version)
                {
                    JEMLogger.LogError(
                        $"Newly received connection don't have right version of the game -> {version} ( is {JEMBuild.BuildVersion} )");
                    Server.CloseConnection(reader.Connection, "InvalidBuildVersion");
                }
                else
                {
                    if (IsHostActive && (reader.Connection.ConnectionIdentity == 0 ||
                                         reader.Connection.ConnectionIdentity == Client.ConnectionIdentity))
                    {
                        HostClientConnection = reader.Connection;
                        JEMLogger.Log("QNetUnity received host client connection.");
                    }

                    if (QNetPlayer.GetQNetPlayerByToken(token) != null)
                    {
                        JEMLogger.LogError("Newly received connection is using already used token. Disconnecting!");
                        Server.CloseConnection(reader.Connection, "TokenAlreadyInUse");
                        return;
                    }

                    var qNetPlayer = QNetPlayer.CreateQNetPlayer(reader.Connection.ConnectionIdentity, nickname, token);
                    if (qNetPlayer == null)
                    {
                        JEMLogger.LogError(
                            "Newly received connection don't have his QNetPlayer instance. Disconnecting!");
                        Server.CloseConnection(reader.Connection, "InternalQNetPlayerError");
                        return;
                    }

                    OnServerNewPlayer?.Invoke(qNetPlayer, reader);
                    QNetServerConnectionInit.PrepareNewConnection(reader.Connection);
                }
            };

            Server.OnConnectionLost += (connection, reason) =>
            {
                var qNetPlayer = QNetPlayer.GetQNetPlayer(connection);
                if (qNetPlayer != null) // if QNetPlayer of this connection not exists, just ignore
                {
                    OnServerPlayerLost?.Invoke(qNetPlayer, reason);

                    // the only thing to do here is to tag player as not ready (if ready)
                    if (qNetPlayer.Ready)
                    {
                        qNetPlayer.TagAsNotReady();
                    }

                    // and remove QNetPlayer from local machine
                    QNetPlayer.DestroyQNetPlayer(qNetPlayer);
                }
            };

            Server.OnServerStop += reason =>
            {
                // server has been stopped, try to de-initialize game
                if (!ShuttingDownByApplicationQuit)
                {
                    QNetGameInitializer.DeInitialize(() => { OnServerShutdown?.Invoke(hostIsActive); });
                }
                else
                {
                    OnServerShutdown?.Invoke(hostIsActive);
                }

                IsServerActive = false;
                IsHostActive   = false;
            };

            IsServerActive = true;
            OnServerStarted?.Invoke();
        }