public void LeaveRoom() { try { if (joined) { InGameOnlineController.Instance.needToSendUpdates = false; Client.Instance.LeaveRoom(); joined = false; } if (Client.Instance.Connected) { Client.Instance.Disconnect(); } } catch { Logger.Info("Unable to disconnect from ServerHub properly!"); } if (songToDownload != null) { songToDownload.songQueueState = SongQueueState.Error; Client.Instance.playerInfo.playerState = PlayerState.Lobby; } InGameOnlineController.Instance.DestroyAvatars(); PreviewPlayer.CrossfadeToDefault(); lastSelectedSong = ""; _lastCharacteristic = _standardCharacteristic; _lastSortMode = SortMode.Default; _lastSearchRequest = ""; PopAllViewControllers(_roomNavigationController); didFinishEvent?.Invoke(); }
public void StartLevel(BeatmapLevelSO level, BeatmapCharacteristicSO characteristic, BeatmapDifficulty difficulty, GameplayModifiers modifiers, float startTime = 0f) { Client.Instance.playerInfo.playerComboBlocks = 0; Client.Instance.playerInfo.playerCutBlocks = 0; Client.Instance.playerInfo.playerTotalBlocks = 0; Client.Instance.playerInfo.playerEnergy = 0f; Client.Instance.playerInfo.playerScore = 0; MenuTransitionsHelperSO menuSceneSetupData = Resources.FindObjectsOfTypeAll <MenuTransitionsHelperSO>().FirstOrDefault(); if (_playerManagementViewController != null) { _playerManagementViewController.SetGameplayModifiers(modifiers); } if (menuSceneSetupData != null) { if (Config.Instance.SpectatorMode) { Client.Instance.playerInfo.playerState = PlayerState.Spectating; modifiers.noFail = true; } else { Client.Instance.playerInfo.playerState = PlayerState.Game; } PlayerSpecificSettings playerSettings = Resources.FindObjectsOfTypeAll <PlayerDataModelSO>().FirstOrDefault().currentLocalPlayer.playerSpecificSettings; roomInfo.roomState = RoomState.InGame; IDifficultyBeatmap difficultyBeatmap = level.GetDifficultyBeatmap(characteristic, difficulty, true); #if DEBUG Logger.Info($"Starting song: name={level.songName}, levelId={level.levelID}, difficulty={difficulty}"); #endif Client.Instance.MessageReceived -= PacketReceived; try { BS_Utils.Gameplay.Gamemode.NextLevelIsIsolated("Beat Saber Multiplayer"); } catch { } PracticeSettings practiceSettings = new PracticeSettings(PracticeSettings.defaultPracticeSettings); practiceSettings.startSongTime = startTime + 1.5f; practiceSettings.songSpeedMul = modifiers.songSpeedMul; menuSceneSetupData.StartStandardLevel(difficultyBeatmap, modifiers, playerSettings, (startTime > 1f ? practiceSettings : null), false, () => {}, (StandardLevelScenesTransitionSetupDataSO sender, LevelCompletionResults levelCompletionResults) => { InGameOnlineController.Instance.SongFinished(sender, levelCompletionResults, difficultyBeatmap, modifiers, false); }); return; } else { Logger.Error("SceneSetupData is null!"); } }
private void PacketReceived(NetIncomingMessage msg) { if (msg == null) { DisconnectCommandReceived(null); return; } CommandType commandType = (CommandType)msg.ReadByte(); if (!joined) { if (commandType == CommandType.JoinRoom) { switch (msg.ReadByte()) { case 0: { Client.Instance.playerInfo.playerState = PlayerState.DownloadingSongs; Client.Instance.RequestRoomInfo(); Client.Instance.SendPlayerInfo(); Client.Instance.InRoom = true; joined = true; InGameOnlineController.Instance.needToSendUpdates = true; if (Config.Instance.EnableVoiceChat) { InGameOnlineController.Instance.VoiceChatStartRecording(); } } break; case 1: { _roomNavigationController.DisplayError("Unable to join room!\nRoom not found"); } break; case 2: { _roomNavigationController.DisplayError("Unable to join room!\nIncorrect password"); } break; case 3: { _roomNavigationController.DisplayError("Unable to join room!\nToo much players"); } break; default: { _roomNavigationController.DisplayError("Unable to join room!\nUnknown error"); } break; } } } else { try { switch (commandType) { case CommandType.GetRoomInfo: { Client.Instance.playerInfo.playerState = PlayerState.Room; roomInfo = new RoomInfo(msg); Client.Instance.isHost = Client.Instance.playerInfo.Equals(roomInfo.roomHost); UpdateUI(roomInfo.roomState); } break; case CommandType.SetSelectedSong: { if (msg.LengthBytes < 16) { roomInfo.roomState = RoomState.SelectingSong; roomInfo.selectedSong = null; PreviewPlayer.CrossfadeToDefault(); UpdateUI(roomInfo.roomState); if (songToDownload != null) { songToDownload.songQueueState = SongQueueState.Error; Client.Instance.playerInfo.playerState = PlayerState.Room; } } else { roomInfo.roomState = RoomState.Preparing; SongInfo selectedSong = new SongInfo(msg); roomInfo.selectedSong = selectedSong; if (roomInfo.startLevelInfo == null) { roomInfo.startLevelInfo = new StartLevelInfo(BeatmapDifficulty.Hard, GameplayModifiers.defaultModifiers, "Standard"); } if (songToDownload != null) { songToDownload.songQueueState = SongQueueState.Error; } UpdateUI(roomInfo.roomState); } } break; case CommandType.SetLevelOptions: { if (roomInfo.roomState == RoomState.SelectingSong) { roomInfo.startLevelInfo = new StartLevelInfo(msg); _playerManagementViewController.SetGameplayModifiers(roomInfo.startLevelInfo.modifiers); _difficultySelectionViewController.SetBeatmapCharacteristic(_beatmapCharacteristics.First(x => x.serializedName == roomInfo.startLevelInfo.characteristicName)); if (!roomInfo.perPlayerDifficulty) { _difficultySelectionViewController.SetBeatmapDifficulty(roomInfo.startLevelInfo.difficulty); } } } break; case CommandType.GetRandomSongInfo: { SongInfo random = new SongInfo(SongLoader.CustomBeatmapLevelPackCollectionSO.beatmapLevelPacks.SelectMany(x => x.beatmapLevelCollection.beatmapLevels).ToArray().Random() as BeatmapLevelSO); Client.Instance.SetSelectedSong(random); } break; case CommandType.TransferHost: { roomInfo.roomHost = new PlayerInfo(msg); Client.Instance.isHost = Client.Instance.playerInfo.Equals(roomInfo.roomHost); if (Client.Instance.playerInfo.playerState == PlayerState.DownloadingSongs) { return; } UpdateUI(roomInfo.roomState); } break; case CommandType.StartLevel: { if (Client.Instance.playerInfo.playerState == PlayerState.DownloadingSongs) { return; } StartLevelInfo levelInfo = new StartLevelInfo(msg); BeatmapCharacteristicSO characteristic = _beatmapCharacteristics.First(x => x.serializedName == levelInfo.characteristicName); SongInfo songInfo = new SongInfo(msg); BeatmapLevelSO level = SongLoader.CustomBeatmapLevelPackCollectionSO.beatmapLevelPacks.SelectMany(x => x.beatmapLevelCollection.beatmapLevels).FirstOrDefault(x => x.levelID.StartsWith(songInfo.levelId)) as BeatmapLevelSO; if (level == null) { Logger.Error("Unable to start level! Level is null! LevelID=" + songInfo.levelId); } if (roomInfo.perPlayerDifficulty && _difficultySelectionViewController != null) { StartLevel(level, characteristic, _difficultySelectionViewController.selectedDifficulty, levelInfo.modifiers); } else { StartLevel(level, characteristic, levelInfo.difficulty, levelInfo.modifiers); } } break; case CommandType.LeaveRoom: { LeaveRoom(); } break; case CommandType.UpdatePlayerInfo: { if (roomInfo != null) { currentTime = msg.ReadFloat(); totalTime = msg.ReadFloat(); int playersCount = msg.ReadInt32(); List <PlayerInfo> playerInfos = new List <PlayerInfo>(); for (int j = 0; j < playersCount; j++) { try { playerInfos.Add(new PlayerInfo(msg)); } catch (Exception e) { #if DEBUG Misc.Logger.Exception($"Unable to parse PlayerInfo! Excpetion: {e}"); #endif } } switch (roomInfo.roomState) { case RoomState.InGame: playerInfos = playerInfos.Where(x => x.playerScore > 0 && x.playerState == PlayerState.Game).ToList(); UpdateLeaderboard(playerInfos, currentTime, totalTime, false); break; case RoomState.Results: playerInfos = playerInfos.Where(x => x.playerScore > 0 && (x.playerState == PlayerState.Game || x.playerState == PlayerState.Room)).ToList(); UpdateLeaderboard(playerInfos, currentTime, totalTime, true); break; } _playerManagementViewController.UpdatePlayerList(playerInfos, roomInfo.roomState); } } break; case CommandType.PlayerReady: { int playersReady = msg.ReadInt32(); int playersTotal = msg.ReadInt32(); if (roomInfo.roomState == RoomState.Preparing && _difficultySelectionViewController != null) { _difficultySelectionViewController.SetPlayersReady(playersReady, playersTotal); } } break; case CommandType.Disconnect: { DisconnectCommandReceived(msg); } break; } }catch (Exception e) { Logger.Exception($"Unable to parse packet! Packet={commandType}, DataLength={msg.LengthBytes}\nException: {e}"); } } }
private void PacketReceived(NetIncomingMessage msg) { CommandType commandType = (CommandType)msg.ReadByte(); if (!joined) { if (commandType == CommandType.JoinRoom) { switch (msg.ReadByte()) { case 0: { Client.Instance.playerInfo.playerState = PlayerState.DownloadingSongs; Client.Instance.RequestRoomInfo(); Client.Instance.SendPlayerInfo(); joined = true; InGameOnlineController.Instance.needToSendUpdates = true; } break; case 1: { _roomNavigationController.DisplayError("Unable to join room!\nRoom not found"); } break; case 2: { _roomNavigationController.DisplayError("Unable to join room!\nIncorrect password"); } break; case 3: { _roomNavigationController.DisplayError("Unable to join room!\nToo much players"); } break; default: { _roomNavigationController.DisplayError("Unable to join room!\nUnknown error"); } break; } } } else { try { switch (commandType) { case CommandType.GetRoomInfo: { Client.Instance.playerInfo.playerState = PlayerState.Room; roomInfo = new RoomInfo(msg); Client.Instance.isHost = Client.Instance.playerInfo.Equals(roomInfo.roomHost); UpdateUI(roomInfo.roomState); } break; case CommandType.SetSelectedSong: { if (msg.LengthBytes < 16) { roomInfo.roomState = RoomState.SelectingSong; roomInfo.selectedSong = null; PreviewPlayer.CrossfadeToDefault(); UpdateUI(roomInfo.roomState); if (songToDownload != null) { songToDownload.songQueueState = SongQueueState.Error; Client.Instance.playerInfo.playerState = PlayerState.Room; } } else { roomInfo.roomState = RoomState.Preparing; SongInfo selectedSong = new SongInfo(msg); roomInfo.selectedSong = selectedSong; if (songToDownload != null) { songToDownload.songQueueState = SongQueueState.Error; } UpdateUI(roomInfo.roomState); } } break; case CommandType.TransferHost: { roomInfo.roomHost = new PlayerInfo(msg); Client.Instance.isHost = Client.Instance.playerInfo.Equals(roomInfo.roomHost); if (Client.Instance.playerInfo.playerState == PlayerState.DownloadingSongs) { return; } UpdateUI(roomInfo.roomState); } break; case CommandType.StartLevel: { if (Client.Instance.playerInfo.playerState == PlayerState.DownloadingSongs) { return; } lastSelectedSong = ""; Client.Instance.playerInfo.playerComboBlocks = 0; Client.Instance.playerInfo.playerCutBlocks = 0; Client.Instance.playerInfo.playerEnergy = 0f; Client.Instance.playerInfo.playerScore = 0; byte difficulty = msg.ReadByte(); SongInfo songInfo = new SongInfo(msg); MenuSceneSetupDataSO menuSceneSetupData = Resources.FindObjectsOfTypeAll <MenuSceneSetupDataSO>().FirstOrDefault(); if (menuSceneSetupData != null) { GameplayModifiers gameplayModifiers = new GameplayModifiers(); if (Config.Instance.SpectatorMode) { Client.Instance.playerInfo.playerState = PlayerState.Spectating; gameplayModifiers.noFail = true; } else { Client.Instance.playerInfo.playerState = PlayerState.Game; gameplayModifiers.noFail = roomInfo.noFail; } PlayerSpecificSettings playerSettings = Resources.FindObjectsOfTypeAll <PlayerDataModelSO>().FirstOrDefault().currentLocalPlayer.playerSpecificSettings; roomInfo.roomState = RoomState.InGame; Client.Instance.MessageReceived -= PacketReceived; LevelSO level = _levelCollection.levels.First(x => x.levelID.StartsWith(songInfo.levelId)); IDifficultyBeatmap difficultyBeatmap = level.GetDifficultyBeatmap((BeatmapDifficulty)difficulty); Logger.Info($"Starting song: name={level.songName}, levelId={level.levelID}, difficulty={(BeatmapDifficulty)difficulty}"); Client.Instance.MessageReceived -= PacketReceived; menuSceneSetupData.StartStandardLevel(difficultyBeatmap, gameplayModifiers, playerSettings, null, null, (StandardLevelSceneSetupDataSO sender, LevelCompletionResults levelCompletionResults) => { InGameOnlineController.Instance.SongFinished(sender, levelCompletionResults, difficultyBeatmap, gameplayModifiers, false); }); return; } else { Logger.Error("SceneSetupData is null!"); } } break; case CommandType.LeaveRoom: { LeaveRoom(); } break; case CommandType.UpdatePlayerInfo: { if (roomInfo != null) { if (roomInfo.roomState != RoomState.SelectingSong) { float currentTime = msg.ReadFloat(); float totalTime = msg.ReadFloat(); int playersCount = msg.ReadInt32(); List <PlayerInfo> playerInfos = new List <PlayerInfo>(); for (int j = 0; j < playersCount; j++) { try { playerInfos.Add(new PlayerInfo(msg)); } catch (Exception e) { #if DEBUG Misc.Logger.Exception($"Unable to parse PlayerInfo! Excpetion: {e}"); #endif } } switch (roomInfo.roomState) { case RoomState.InGame: playerInfos = playerInfos.Where(x => x.playerScore > 0 && x.playerState == PlayerState.Game).ToList(); UpdateLeaderboard(playerInfos, currentTime, totalTime, false); break; case RoomState.Results: playerInfos = playerInfos.Where(x => x.playerScore > 0 && (x.playerState == PlayerState.Game || x.playerState == PlayerState.Room)).ToList(); UpdateLeaderboard(playerInfos, currentTime, totalTime, true); break; case RoomState.Preparing: _roomManagementViewController.UpdatePlayerList(playerInfos); break; } } } } break; case CommandType.PlayerReady: { int playersReady = msg.ReadInt32(); int playersTotal = msg.ReadInt32(); if (roomInfo.roomState == RoomState.Preparing && _difficultySelectionViewController != null) { _difficultySelectionViewController.SetPlayersReady(playersReady, playersTotal); } } break; case CommandType.Disconnect: { InGameOnlineController.Instance.needToSendUpdates = false; if (msg.LengthBytes > 3) { string reason = msg.ReadString(); PopAllViewControllers(_roomNavigationController); InGameOnlineController.Instance.DestroyAvatars(); PreviewPlayer.CrossfadeToDefault(); joined = false; lastSelectedSong = ""; _roomNavigationController.DisplayError(reason); } else { _roomNavigationController.DisplayError("ServerHub refused connection!"); } } break; } }catch (Exception e) { Logger.Exception("Unable to parse packet!"); if (msg != null) { Logger.Exception($"Packet={commandType}, DataLength={msg.LengthBytes}"); } Logger.Exception(e.ToString()); } } }