/// <summary> /// Start the server /// <para>If <paramref name="localClient"/> is given then will start in host mode</para> /// </summary> /// <param name="config">Config for <see cref="Peer"/></param> /// <param name="localClient">if not null then start the server and client in hostmode</param> // Has to be called "StartServer" to stop unity complaining about "Start" method public void StartServer(NetworkClient localClient = null) { ThrowIfActive(); ThrowIfSocketIsMissing(); Application.quitting += Stop; if (logger.LogEnabled()) { logger.Log($"NetworkServer created, Mirage version: {Version.Current}"); } logger.Assert(Players.Count == 0, "Player should have been reset since previous session"); logger.Assert(_connections.Count == 0, "Connections should have been reset since previous session"); World = new NetworkWorld(); SyncVarSender = new SyncVarSender(); LocalClient = localClient; MessageHandler = new MessageHandler(World, DisconnectOnException); MessageHandler.RegisterHandler <NetworkPingMessage>(World.Time.OnServerPing); var dataHandler = new DataHandler(MessageHandler, _connections); Metrics = EnablePeerMetrics ? new Metrics(MetricsSize) : null; var config = PeerConfig; if (config == null) { config = new Config { // only use MaxConnections if config was null MaxConnections = MaxConnections, }; } var maxPacketSize = SocketFactory.MaxPacketSize; NetworkWriterPool.Configure(maxPacketSize); // Are we listening for incoming connections? // If yes, set up a socket for incoming connections (we're a multiplayer game). // If not, that's okay. Some games use a non-listening server for their single player game mode (Battlefield, Call of Duty...) if (Listening) { // Create a server specific socket. var socket = SocketFactory.CreateServerSocket(); // Tell the peer to use that newly created socket. _peer = new Peer(socket, maxPacketSize, dataHandler, config, LogFactory.GetLogger <Peer>(), Metrics); _peer.OnConnected += Peer_OnConnected; _peer.OnDisconnected += Peer_OnDisconnected; // Bind it to the endpoint. _peer.Bind(SocketFactory.GetBindEndPoint()); if (logger.LogEnabled()) { logger.Log($"Server started, listening for connections. Using socket {socket.GetType()}"); } if (RunInBackground) { Application.runInBackground = RunInBackground; } } else { // Nicely mention that we're going live, but not listening for connections. if (logger.LogEnabled()) { logger.Log("Server started, but not listening for connections: Attempts to connect to this instance will fail!"); } } InitializeAuthEvents(); Active = true; _started?.Invoke(); if (LocalClient != null) { // we should call onStartHost after transport is ready to be used // this allows server methods like NetworkServer.Spawn to be called in there _onStartHost?.Invoke(); localClient.ConnectHost(this, dataHandler); if (logger.LogEnabled()) { logger.Log("NetworkServer StartHost"); } } }