/// <summary> /// Registers all server side handlers. /// </summary> public static void RegisterServerHandlers([NotNull] QNetServer server) { if (server == null) { throw new ArgumentNullException(nameof(server), "Server is null."); } server.SetHandler(new QNetMessage(true, (ushort)QNetUnityLocalHeader.LEVEL_LOADED, QNetHandlerWorldReceiver.OnClientLevelLoaded)); server.SetHandler(new QNetMessage(true, (ushort)QNetUnityLocalHeader.LEVEL_LOADED_ON_FLY, QNetHandlerWorldReceiver.OnClientLevelLoadedOnFly)); server.SetHandler(new QNetMessage(true, (ushort)QNetUnityLocalHeader.WORLD_SERIALIZED, QNetHandlerWorldReceiver.OnClientWorldSerialized)); server.SetHandler(new QNetMessage(true, (ushort)QNetUnityLocalHeader.ENTITY_QUERY, QNetHandlerObjectReceiver.OnClientEntityQuery)); }
/// <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(); }
/// <summary> /// Sends message to given connection. /// </summary> /// <param name="server">Our Server.</param> /// <param name="except">Message will be send to all connections except this.</param> /// <param name="channel">Channel of message.</param> /// <param name="method">Method of message sending.</param> /// <param name="writer">Message to send.</param> public static void SendToAll(this QNetServer server, QNetConnection except, QNetLocalHeader channel, QNetMessageMethod method, QNetMessageWriter writer) { server.SendToAll(except, (byte)channel, method, writer); }
/// <summary> /// Sends message to given connection. /// </summary> /// <param name="server">Our Server.</param> /// <param name="channel">Channel of message.</param> /// <param name="method">Method of message sending.</param> /// <param name="writer">Message to send.</param> public static void SendToAll(this QNetServer server, QNetLocalChannel channel, QNetMessageMethod method, QNetMessageWriter writer) { server.SendToAll((byte)channel, method, writer); }
/// <summary> /// Sends message to given connection. /// </summary> /// <param name="server">Our Server.</param> /// <param name="channel">Channel of message.</param> /// <param name="method">Method of message sending.</param> /// <param name="header">Header</param> public static void SendToAll(this QNetServer server, QNetLocalChannel channel, QNetMessageMethod method, QNetUnityLocalHeader header) { server.SendToAll((byte)channel, method, (ushort)header); }
/// <summary> /// Sends message to given connection. /// </summary> /// <param name="server">Our Server.</param> /// <param name="connection">Target connection of message.</param> /// <param name="channel">Channel of message.</param> /// <param name="method">Method of message sending.</param> /// <param name="writer">Message to send.</param> public static void Send(this QNetServer server, QNetConnection connection, QNetLocalChannel channel, QNetMessageMethod method, QNetMessageWriter writer) { server.Send(connection, (byte)channel, method, writer); }
/// <summary> /// Sends message to given connection. /// </summary> /// <param name="server">Our Server.</param> /// <param name="connection">Target connection of message.</param> /// <param name="channel">Channel of message.</param> /// <param name="method">Method of message sending.</param> /// <param name="header"></param> public static void Send(this QNetServer server, QNetConnection connection, QNetLocalChannel channel, QNetMessageMethod method, QNetUnityLocalHeader header) { server.Send(connection, (byte)channel, method, (ushort)header); }