public static async Task <bool> Announce(HostedGameData announce) { var payload = announce.ToJson(); var isDupeRequest = (_lastPayloadSent != null && _lastPayloadSent == payload); var enoughTimeHasPassed = (_lastSentAt == null || (DateTime.Now - _lastSentAt.Value).TotalMinutes >= ANNOUNCE_INTERVAL_MINS); if (isDupeRequest && !enoughTimeHasPassed) { // An identical payload was already sent out! // Do not send a dupe unless enough time has passed return(true); } Plugin.Log?.Info($"Sending host announcement [{announce.Describe()}] for code {announce.ServerCode}"); _lastPayloadSent = payload; _lastSentAt = DateTime.Now; var responseOk = await PerformWebRequest("POST", "/announce", payload) != null; if (!responseOk) { // Request failed, allow immediate retry _lastPayloadSent = null; _lastSentAt = null; } return(responseOk); }
private static HostedGameData GenerateAnnounce() { var sessionManager = MpSession.SessionManager; var localPlayer = sessionManager.localPlayer; var connectedPlayers = sessionManager.connectedPlayers; if (_mpExVersion == null) { _mpExVersion = MpExHelper.GetInstalledVersion(); if (_mpExVersion != null) { Plugin.Log?.Info($"Detected MultiplayerExtensions, version {_mpExVersion}"); } } var lobbyAnnounce = new HostedGameData() { ServerCode = _lobbyCode, GameName = MpSession.GetHostGameName(), OwnerId = localPlayer.userId, OwnerName = localPlayer.userName, PlayerCount = MpSession.GetPlayerCount(), PlayerLimit = MpSession.GetPlayerLimit(), IsModded = localPlayer.HasState("modded") || localPlayer.HasState("customsongs") || _mpExVersion != null, LobbyState = MpLobbyStatePatch.LobbyState, LevelId = _level?.levelID, SongName = _level?.songName, SongAuthor = _level?.songAuthorName, Difficulty = _difficulty, Platform = MpLocalPlayer.PlatformId, MasterServerHost = MpConnect.LastUsedMasterServer != null ? MpConnect.LastUsedMasterServer.hostName : null, MasterServerPort = MpConnect.LastUsedMasterServer != null ? MpConnect.LastUsedMasterServer.port : MpConnect.DEFAULT_MASTER_PORT, MpExVersion = _mpExVersion }; lobbyAnnounce.Players = new List <HostedGamePlayer>(); lobbyAnnounce.Players.Add(new HostedGamePlayer() { SortIndex = localPlayer.sortIndex, UserId = localPlayer.userId, UserName = localPlayer.userName, IsHost = localPlayer.isConnectionOwner, Latency = localPlayer.currentLatency }); foreach (var connectedPlayer in connectedPlayers) { lobbyAnnounce.Players.Add(new HostedGamePlayer() { SortIndex = connectedPlayer.sortIndex, UserId = connectedPlayer.userId, UserName = connectedPlayer.userName, IsHost = connectedPlayer.isConnectionOwner, Latency = connectedPlayer.currentLatency }); } return(lobbyAnnounce); }
public static async Task <bool> UnAnnounce(HostedGameData announce) { Plugin.Log?.Info($"Cancelling host announcement: {announce.GameName}, {announce.ServerCode}"); _lastPayloadSent = null; var responseOk = await PerformWebRequest("POST", $"/unannounce?serverCode={announce.ServerCode}&ownerId={announce.OwnerId}") != null; return(responseOk); }
/// <summary> /// Ensures that any host announcements made by us are removed: /// - If a previous announcement was made, a DELETE request is sent to the master server, removing it. /// - If no previous announcement was made, or it was already deleted, this is a no-op. /// </summary> public static async Task UnAnnounce() { if (_lastCompleteAnnounce != null && !_sentUnAnnounce) { _sentUnAnnounce = true; if (await BSSBMasterAPI.UnAnnounce(_lastCompleteAnnounce)) { Plugin.Log?.Info($"Host announcement was deleted OK!"); _didAnnounce = false; _lastCompleteAnnounce = null; } else { _sentUnAnnounce = false; } } }
private static async Task DoAnnounce(HostedGameData announce) { _sentUnAnnounce = false; if (await BSSBMasterAPI.Announce(announce)) { _didAnnounce = true; _lastCompleteAnnounce = announce; StatusText = $"Players can now join from the browser!\r\n{announce.Describe()}"; HasErrored = false; } else { _didAnnounce = false; _lastCompleteAnnounce = null; StatusText = $"Could not announce to master server!"; HasErrored = true; } LobbyConfigPanel.UpdatePanelInstance(); }
public static void HandleUpdate() { #pragma warning disable CS4014 var sessionManager = MpSession.SessionManager; if (sessionManager == null || !MpLobbyConnectionTypePatch.IsPartyMultiplayer || !MpLobbyConnectionTypePatch.IsPartyHost || !MpLobbyStatePatch.IsValidMpState) { // We are not in a party lobby, or we are not the host // Make sure any previous host announcements by us are cancelled and bail StatusText = "You must be the host of a custom multiplayer game."; HasErrored = true; UnAnnounce(); LobbyConfigPanel.UpdatePanelInstance(); return; } if (Plugin.Config.LobbyAnnounceToggle) { // Toggle is on, ensure state is synced if (!_didSetLocalPlayerState.HasValue || _didSetLocalPlayerState.Value == false) { _didSetLocalPlayerState = true; sessionManager.SetLocalPlayerState("lobbyannounce", true); // NB: this calls another update } } else { // Toggle is off, ensure state is synced & do not proceed with announce StatusText = "Lobby announces are toggled off."; HasErrored = true; UnAnnounce(); if (!_didSetLocalPlayerState.HasValue || _didSetLocalPlayerState.Value == true) { _didSetLocalPlayerState = false; sessionManager.SetLocalPlayerState("lobbyannounce", false); // NB: this calls another update } LobbyConfigPanel.UpdatePanelInstance(); return; } if (String.IsNullOrEmpty(_lobbyCode) || !sessionManager.isConnectionOwner || sessionManager.localPlayer == null || !sessionManager.isConnected || sessionManager.maxPlayerCount == 1) { // We do not (yet) have the Server Code, or we're at an in-between state where things aren't ready yet StatusText = "Can't send announcement (invalid lobby state)."; HasErrored = true; UnAnnounce(); LobbyConfigPanel.UpdatePanelInstance(); return; } string finalGameName = $"{sessionManager.localPlayer.userName}'s game"; if (!String.IsNullOrEmpty(_customGameName)) { finalGameName = _customGameName; } else if (!String.IsNullOrEmpty(Plugin.Config.CustomGameName)) { finalGameName = Plugin.Config.CustomGameName; } var lobbyAnnounce = new HostedGameData() { ServerCode = _lobbyCode, GameName = finalGameName, OwnerId = sessionManager.localPlayer.userId, OwnerName = sessionManager.localPlayer.userName, PlayerCount = MpSession.GetPlayerCount(), PlayerLimit = MpSession.GetPlayerLimit(), IsModded = sessionManager.localPlayer.HasState("modded") && sessionManager.localPlayer.HasState("customsongs"), LobbyState = MpLobbyStatePatch.LobbyState, LevelId = _level?.levelID, SongName = _level?.songName, SongAuthor = _level?.songAuthorName, Difficulty = _difficulty, Platform = Plugin.PlatformId, MasterServerHost = MpConnect.LastUsedMasterServer != null ? MpConnect.LastUsedMasterServer.hostName : null, MasterServerPort = MpConnect.LastUsedMasterServer != null ? MpConnect.LastUsedMasterServer.port : MpConnect.DEFAULT_MASTER_PORT }; StatusText = "Announcing your game to the world...\r\n" + lobbyAnnounce.Describe(); HasErrored = false; LobbyConfigPanel.UpdatePanelInstance(); DoAnnounce(lobbyAnnounce); #pragma warning restore CS4014 }