public override void Start() { if (loadSaveFile) { SaveManager.LoadServerData(); } foreach (Assembly assembly in AssembliesUtils.GetNebulaAssemblies()) { PacketUtils.RegisterAllPacketNestedTypesInAssembly(assembly, PacketProcessor); } PacketUtils.RegisterAllPacketProcessorsInCallingAssembly(PacketProcessor, true); foreach (Assembly assembly in NebulaModAPI.TargetAssemblies) { PacketUtils.RegisterAllPacketNestedTypesInAssembly(assembly, PacketProcessor); PacketUtils.RegisterAllPacketProcessorsInAssembly(assembly, PacketProcessor, true); } #if DEBUG PacketProcessor.SimulateLatency = true; #endif if (Config.Options.EnableUPnpOrPmpSupport) { Task.Run(async() => { var discoverer = new NatDiscoverer(); try { var device = await discoverer.DiscoverDeviceAsync(); await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, port, port, "DSP nebula")); NebulaModel.Logger.Log.Info($"Successfully created UPnp or Pmp port mapping for {port}"); } catch (NatDeviceNotFoundException) { NebulaModel.Logger.Log.WarnInform("No UPnp or Pmp compatible/enabled NAT device found"); } catch (MappingException) { NebulaModel.Logger.Log.WarnInform("Could not create UPnp or Pmp port mapping"); } }); } ngrokManager = new Ngrok.NgrokManager(port); socket = new WebSocketServer(System.Net.IPAddress.IPv6Any, port); socket.Log.Level = LogLevel.Debug; socket.AllowForwardedRequest = true; // This is required to make the websocket play nice with tunneling services like ngrok if (!string.IsNullOrWhiteSpace(Config.Options.ServerPassword)) { socket.AuthenticationSchemes = AuthenticationSchemes.Basic; socket.UserCredentialsFinder = id => { var name = id.Name; // Return user name, password, and roles. return(name == "nebula-player" ? new NetworkCredential(name, Config.Options.ServerPassword) : null); // If the user credentials are not found. }; } DisableNagleAlgorithm(socket); WebSocketService.PacketProcessor = PacketProcessor; WebSocketService.PlayerManager = PlayerManager; socket.AddWebSocketService <WebSocketService>("/socket", wse => new WebSocketService()); try { socket.KeepClean = Config.Options.CleanupInactiveSessions; socket.Start(); }catch (System.InvalidOperationException e) { InGamePopup.ShowError("Error", "An error occurred while hosting the game: " + e.Message, "Close"); Stop(); return; } ((LocalPlayer)Multiplayer.Session.LocalPlayer).IsHost = true; ((LocalPlayer)Multiplayer.Session.LocalPlayer).SetPlayerData(new PlayerData( PlayerManager.GetNextAvailablePlayerId(), GameMain.localPlanet?.id ?? -1, Config.Options.GetMechaColors(), !string.IsNullOrWhiteSpace(Config.Options.Nickname) ? Config.Options.Nickname : GameMain.data.account.userName), loadSaveFile); Task.Run(async() => { if (ngrokManager.IsNgrokActive()) { DiscordManager.UpdateRichPresence(ip: await ngrokManager.GetNgrokAddressAsync(), updateTimestamp: true); } else { DiscordManager.UpdateRichPresence(ip: $"{(Config.Options.IPConfiguration != IPUtils.IPConfiguration.IPv6 ? await IPUtils.GetWANv4Address() : string.Empty)};" + $"{(Config.Options.IPConfiguration != IPUtils.IPConfiguration.IPv4 ? await IPUtils.GetWANv6Address() : string.Empty)};" + $"{port}", updateTimestamp: true); } }); NebulaModAPI.OnMultiplayerGameStarted?.Invoke(); }