From 940584f6e9da2cb8048120342d3d31fca24db2e5 Mon Sep 17 00:00:00 2001 From: MT Date: Tue, 20 Jul 2021 17:07:31 -0400 Subject: [PATCH 01/41] made mod compile and load --- .../ExtendedLevelLoader.cs} | 4 +- .../ExtendedPlayerTableCell.cs} | 14 +- .../ExtendedPlayersDataModel.cs} | 79 +++--- .../HarmonyPatches/CustomSongsPatches.cs | 26 +- .../HarmonyPatches/HarmonyManager.cs | 1 - .../HarmonyPatches/InstallerPatches.cs | 26 +- .../Installers/MPMenuInstaller.cs | 13 +- MultiplayerExtensions/MPState.cs | 7 + .../MultiplayerExtensions.csproj | 8 +- .../GameStateControllerStub.cs | 216 --------------- .../Sessions/SessionManager.cs | 1 + .../UI/ClientLobbySetupPanel.bsml | 17 -- .../UI/ClientLobbySetupPanel.cs | 250 ------------------ ...bySetupPanel.bsml => LobbySetupPanel.bsml} | 0 ...tLobbySetupPanel.cs => LobbySetupPanel.cs} | 6 +- 15 files changed, 84 insertions(+), 584 deletions(-) rename MultiplayerExtensions/{OverrideClasses/LevelLoaderStub.cs => Extensions/ExtendedLevelLoader.cs} (95%) rename MultiplayerExtensions/{OverrideClasses/PlayerTableCellStub.cs => Extensions/ExtendedPlayerTableCell.cs} (93%) rename MultiplayerExtensions/{OverrideClasses/PlayersDataModelStub.cs => Extensions/ExtendedPlayersDataModel.cs} (72%) delete mode 100644 MultiplayerExtensions/OverrideClasses/GameStateControllerStub.cs delete mode 100644 MultiplayerExtensions/UI/ClientLobbySetupPanel.bsml delete mode 100644 MultiplayerExtensions/UI/ClientLobbySetupPanel.cs rename MultiplayerExtensions/UI/{HostLobbySetupPanel.bsml => LobbySetupPanel.bsml} (100%) rename MultiplayerExtensions/UI/{HostLobbySetupPanel.cs => LobbySetupPanel.cs} (97%) diff --git a/MultiplayerExtensions/OverrideClasses/LevelLoaderStub.cs b/MultiplayerExtensions/Extensions/ExtendedLevelLoader.cs similarity index 95% rename from MultiplayerExtensions/OverrideClasses/LevelLoaderStub.cs rename to MultiplayerExtensions/Extensions/ExtendedLevelLoader.cs index 181cb2e..d94c413 100644 --- a/MultiplayerExtensions/OverrideClasses/LevelLoaderStub.cs +++ b/MultiplayerExtensions/Extensions/ExtendedLevelLoader.cs @@ -4,9 +4,9 @@ using System.Threading.Tasks; using Zenject; -namespace MultiplayerExtensions.OverrideClasses +namespace MultiplayerExtensions.Extensions { - class LevelLoaderStub : MultiplayerLevelLoader, IProgress + class ExtendedLevelLoader : MultiplayerLevelLoader, IProgress { public event Action progressUpdated = null!; diff --git a/MultiplayerExtensions/OverrideClasses/PlayerTableCellStub.cs b/MultiplayerExtensions/Extensions/ExtendedPlayerTableCell.cs similarity index 93% rename from MultiplayerExtensions/OverrideClasses/PlayerTableCellStub.cs rename to MultiplayerExtensions/Extensions/ExtendedPlayerTableCell.cs index ba65832..0dffce6 100644 --- a/MultiplayerExtensions/OverrideClasses/PlayerTableCellStub.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayerTableCell.cs @@ -10,7 +10,7 @@ namespace MultiplayerExtensions.OverrideClasses { - class PlayerTableCellStub : GameServerPlayerTableCell + class ExtendedPlayerTableCell : GameServerPlayerTableCell { protected NetworkPlayerEntitlementChecker _entitlementChecker = null!; protected ILobbyPlayersDataModel _playersDataModel = null!; @@ -70,11 +70,11 @@ public override void Awake() { __buttonBinder.AddBinding(_useModifiersButton, new Action(base.HandleUseModifiersButtonPressed)); } - public override void SetData(IConnectedPlayer connectedPlayer, ILobbyPlayerDataModel playerDataModel, bool isHost, Task getLevelEntitlementTask) + public override void SetData(IConnectedPlayer connectedPlayer, ILobbyPlayerData playerData, bool hasKickPermissions, bool allowSelection, Task getLevelEntitlementTask) { if (getLevelEntitlementTask != null) getLevelEntitlementTask = getLevelEntitlementTask.ContinueWith(r => AdditionalContentModel.EntitlementStatus.Owned); - base.SetData(connectedPlayer, playerDataModel, isHost, getLevelEntitlementTask); + base.SetData(connectedPlayer, playerData, hasKickPermissions, allowSelection, getLevelEntitlementTask); GetLevelEntitlement(connectedPlayer); lastPlayer = connectedPlayer; } @@ -85,16 +85,16 @@ private async void GetLevelEntitlement(IConnectedPlayer player) entitlementCts.Cancel(); entitlementCts = new CancellationTokenSource(); - string? levelId = _playersDataModel.GetPlayerBeatmapLevel(_playersDataModel.hostUserId)?.levelID; + string? levelId = _playersDataModel.GetPlayerBeatmapLevel(_playersDataModel.partyOwnerId)?.levelID; if (levelId == null) return; lastLevelId = levelId; bool needsRpc = false; - Task entitlement = player.isMe ? - _entitlementChecker.GetEntitlementStatus(levelId) : - _entitlementChecker.GetTcsTaskCanPlayerPlayLevel(player, levelId, entitlementCts.Token, out needsRpc); + Task entitlement = player.isMe ? + _entitlementChecker.GetEntitlementStatus(levelId) : + Task.FromResult(EntitlementsStatus.Ok); if (needsRpc) _menuRpcManager.GetIsEntitledToLevel(levelId); SetLevelEntitlement(player, await entitlement); diff --git a/MultiplayerExtensions/OverrideClasses/PlayersDataModelStub.cs b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs similarity index 72% rename from MultiplayerExtensions/OverrideClasses/PlayersDataModelStub.cs rename to MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs index 576bc80..39d7025 100644 --- a/MultiplayerExtensions/OverrideClasses/PlayersDataModelStub.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs @@ -6,14 +6,14 @@ using System.Linq; using System.Threading.Tasks; -namespace MultiplayerExtensions.OverrideClasses +namespace MultiplayerExtensions.Extensions { - class PlayersDataModelStub : LobbyPlayersDataModel, ILobbyPlayersDataModel, IDisposable + class ExtendedPlayersDataModel : LobbyPlayersDataModel, ILobbyPlayersDataModel, IDisposable { protected readonly PacketManager _packetManager; protected readonly ExtendedPlayerManager _playerManager; - internal PlayersDataModelStub(PacketManager packetManager, ExtendedPlayerManager playerManager) + internal ExtendedPlayersDataModel(PacketManager packetManager, ExtendedPlayerManager playerManager) { _packetManager = packetManager; _playerManager = playerManager; @@ -26,16 +26,16 @@ internal PlayersDataModelStub(PacketManager packetManager, ExtendedPlayerManager _packetManager.RegisterCallback(HandlePreviewBeatmapPacket); base.Activate(); - _menuRpcManager.selectedBeatmapEvent -= base.HandleMenuRpcManagerSelectedBeatmap; - _menuRpcManager.selectedBeatmapEvent += HandleMenuRpcManagerSelectedBeatmap; - _menuRpcManager.getSelectedBeatmapEvent -= base.HandleMenuRpcManagerGetSelectedBeatmap; - _menuRpcManager.getSelectedBeatmapEvent += HandleMenuRpcManagerGetSelectedBeatmap; - _menuRpcManager.clearSelectedBeatmapEvent -= base.HandleMenuRpcManagerClearBeatmap; - _menuRpcManager.clearSelectedBeatmapEvent += HandleMenuRpcManagerClearBeatmap; - _menuRpcManager.selectedGameplayModifiersEvent -= base.HandleMenuRpcManagerSelectedGameplayModifiers; - _menuRpcManager.selectedGameplayModifiersEvent += HandleMenuRpcManagerSelectedGameplayModifiers; - _menuRpcManager.clearSelectedGameplayModifiersEvent -= base.HandleMenuRpcManagerClearSelectedGameplayModifiers; - _menuRpcManager.clearSelectedGameplayModifiersEvent += HandleMenuRpcManagerClearSelectedGameplayModifiers; + _menuRpcManager.recommendBeatmapEvent -= base.HandleMenuRpcManagerRecommendBeatmap; + _menuRpcManager.recommendBeatmapEvent += HandleMenuRpcManagerRecommendBeatmap; + _menuRpcManager.getRecommendedBeatmapEvent -= base.HandleMenuRpcManagerGetRecommendedBeatmap; + _menuRpcManager.getRecommendedBeatmapEvent += HandleMenuRpcManagerGetRecommendedBeatmap; + _menuRpcManager.clearRecommendedBeatmapEvent -= base.HandleMenuRpcManagerClearBeatmap; + _menuRpcManager.clearRecommendedBeatmapEvent += HandleMenuRpcManagerClearBeatmap; + _menuRpcManager.recommendGameplayModifiersEvent -= base.HandleMenuRpcManagerRecommendGameplayModifiers; + _menuRpcManager.recommendGameplayModifiersEvent += HandleMenuRpcManagerRecommendGameplayModifiers; + _menuRpcManager.clearRecommendedGameplayModifiersEvent -= base.HandleMenuRpcManagerClearRecommendedGameplayModifiers; + _menuRpcManager.clearRecommendedGameplayModifiersEvent += HandleMenuRpcManagerClearRecommendedGameplayModifiers; } public new void Deactivate() @@ -44,16 +44,16 @@ internal PlayersDataModelStub(PacketManager packetManager, ExtendedPlayerManager MPEvents.FreeModChanged -= HandleFreeModChanged; _packetManager.UnregisterCallback(); - _menuRpcManager.selectedBeatmapEvent -= HandleMenuRpcManagerSelectedBeatmap; - _menuRpcManager.selectedBeatmapEvent += base.HandleMenuRpcManagerSelectedBeatmap; - _menuRpcManager.getSelectedBeatmapEvent -= HandleMenuRpcManagerGetSelectedBeatmap; - _menuRpcManager.getSelectedBeatmapEvent += base.HandleMenuRpcManagerGetSelectedBeatmap; - _menuRpcManager.clearSelectedBeatmapEvent -= HandleMenuRpcManagerClearBeatmap; - _menuRpcManager.clearSelectedBeatmapEvent += base.HandleMenuRpcManagerClearBeatmap; - _menuRpcManager.selectedGameplayModifiersEvent -= HandleMenuRpcManagerSelectedGameplayModifiers; - _menuRpcManager.selectedGameplayModifiersEvent += base.HandleMenuRpcManagerSelectedGameplayModifiers; - _menuRpcManager.clearSelectedGameplayModifiersEvent -= HandleMenuRpcManagerClearSelectedGameplayModifiers; - _menuRpcManager.clearSelectedGameplayModifiersEvent += base.HandleMenuRpcManagerClearSelectedGameplayModifiers; + _menuRpcManager.recommendBeatmapEvent -= HandleMenuRpcManagerRecommendBeatmap; + _menuRpcManager.recommendBeatmapEvent += base.HandleMenuRpcManagerRecommendBeatmap; + _menuRpcManager.getRecommendedBeatmapEvent -= HandleMenuRpcManagerGetRecommendedBeatmap; + _menuRpcManager.getRecommendedBeatmapEvent += base.HandleMenuRpcManagerGetRecommendedBeatmap; + _menuRpcManager.clearRecommendedBeatmapEvent -= HandleMenuRpcManagerClearBeatmap; + _menuRpcManager.clearRecommendedBeatmapEvent += base.HandleMenuRpcManagerClearBeatmap; + _menuRpcManager.recommendGameplayModifiersEvent -= HandleMenuRpcManagerRecommendGameplayModifiers; + _menuRpcManager.recommendGameplayModifiersEvent += base.HandleMenuRpcManagerRecommendGameplayModifiers; + _menuRpcManager.clearRecommendedGameplayModifiersEvent -= HandleMenuRpcManagerClearRecommendedGameplayModifiers; + _menuRpcManager.clearRecommendedGameplayModifiersEvent += base.HandleMenuRpcManagerClearRecommendedGameplayModifiers; base.Deactivate(); } @@ -73,10 +73,10 @@ private void HandleCustomSongsChanged(object sender, bool value) private void HandleFreeModChanged(object sender, bool value) { - if (value && localUserId != hostUserId) + if (value && localUserId != partyOwnerId) { GameplayModifiers localModifiers = GetPlayerGameplayModifiers(localUserId); - GameplayModifiers hostModifiers = GetPlayerGameplayModifiers(hostUserId); + GameplayModifiers hostModifiers = GetPlayerGameplayModifiers(partyOwnerId); if (localModifiers.songSpeed != hostModifiers.songSpeed) base.SetLocalPlayerGameplayModifiers(localModifiers.CopyWith(songSpeed: hostModifiers.songSpeed)); } @@ -111,19 +111,20 @@ public override void HandleMenuRpcManagerClearBeatmap(string userId) /// If the newly joined player is not modded or the selected song isn't custom, sends back a vanilla packet. /// Otherwise, sends a /// - public override void HandleMenuRpcManagerGetSelectedBeatmap(string userId) + public override void HandleMenuRpcManagerGetRecommendedBeatmap(string userId) { - ILobbyPlayerDataModel lobbyPlayerDataModel = this.GetLobbyPlayerDataModel(this.localUserId); - if (lobbyPlayerDataModel != null && MPState.CurrentGameType != MultiplayerGameType.QuickPlay && _multiplayerSessionManager.GetPlayerByUserId(userId).HasState("modded") && lobbyPlayerDataModel?.beatmapLevel != null && lobbyPlayerDataModel?.beatmapLevel is PreviewBeatmapStub preview) + ILobbyPlayerData lobbyPlayerDataModel = this.GetLobbyPlayerDataModel(this.localUserId); + IConnectedPlayer user = _multiplayerSessionManager.GetPlayerByUserId(userId); + if (lobbyPlayerDataModel != null && MPState.CurrentGameType != MultiplayerGameType.QuickPlay && user != null && user.HasState("modded") && lobbyPlayerDataModel?.beatmapLevel != null && lobbyPlayerDataModel?.beatmapLevel is PreviewBeatmapStub preview) _packetManager.Send(new PreviewBeatmapPacket(preview, lobbyPlayerDataModel.beatmapCharacteristic.serializedName, lobbyPlayerDataModel.beatmapDifficulty)); else if (lobbyPlayerDataModel != null && lobbyPlayerDataModel.beatmapLevel != null) - this._menuRpcManager.SelectBeatmap(new BeatmapIdentifierNetSerializable(lobbyPlayerDataModel.beatmapLevel.levelID, lobbyPlayerDataModel.beatmapCharacteristic.serializedName, lobbyPlayerDataModel.beatmapDifficulty)); + this._menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(lobbyPlayerDataModel.beatmapLevel.levelID, lobbyPlayerDataModel.beatmapCharacteristic.serializedName, lobbyPlayerDataModel.beatmapDifficulty)); } /// /// Triggered when a player selects a song using a vanilla packet. /// - public async override void HandleMenuRpcManagerSelectedBeatmap(string userId, BeatmapIdentifierNetSerializable beatmapId) + public async override void HandleMenuRpcManagerRecommendBeatmap(string userId, BeatmapIdentifierNetSerializable beatmapId) { OnSelectedBeatmap(userId, beatmapId); string? hash = Utilities.Utils.LevelIdToHash(beatmapId.levelID); @@ -148,7 +149,7 @@ public async override void HandleMenuRpcManagerSelectedBeatmap(string userId, Be } } else - base.HandleMenuRpcManagerSelectedBeatmap(userId, beatmapId); + base.HandleMenuRpcManagerRecommendBeatmap(userId, beatmapId); } /// @@ -164,7 +165,7 @@ public async override void HandleMenuRpcManagerSelectedBeatmap(string userId, Be { PreviewBeatmapStub? preview = GetExistingPreview(levelId); HMMainThreadDispatcher.instance.Enqueue(() => base.SetPlayerBeatmapLevel(base.localUserId, preview, beatmapDifficulty, characteristic)); - _menuRpcManager.SelectBeatmap(new BeatmapIdentifierNetSerializable(levelId, characteristic.serializedName, beatmapDifficulty)); + _menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(levelId, characteristic.serializedName, beatmapDifficulty)); } else { @@ -178,19 +179,19 @@ public async override void HandleMenuRpcManagerSelectedBeatmap(string userId, Be HMMainThreadDispatcher.instance.Enqueue(() => base.SetPlayerBeatmapLevel(base.localUserId, preview, beatmapDifficulty, characteristic)); _packetManager.Send(new PreviewBeatmapPacket(preview!, characteristic.serializedName, beatmapDifficulty)); if (!_multiplayerSessionManager.connectedPlayers.All(x => x.HasState("modded"))) - _menuRpcManager.SelectBeatmap(new BeatmapIdentifierNetSerializable(levelId, characteristic.serializedName, beatmapDifficulty)); + _menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(levelId, characteristic.serializedName, beatmapDifficulty)); } }else base.SetLocalPlayerBeatmapLevel(levelId, beatmapDifficulty, characteristic); } - public override void HandleMenuRpcManagerSelectedGameplayModifiers(string userId, GameplayModifiers gameplayModifiers) + public override void HandleMenuRpcManagerRecommendGameplayModifiers(string userId, GameplayModifiers gameplayModifiers) { ExtendedPlayer? player = _playerManager.GetExtendedPlayer(userId); if (player != null) player.lastModifiers = gameplayModifiers; - base.HandleMenuRpcManagerSelectedGameplayModifiers(userId, gameplayModifiers); - if (userId == hostUserId && MPState.FreeModEnabled) + base.HandleMenuRpcManagerRecommendGameplayModifiers(userId, gameplayModifiers); + if (userId == partyOwnerId && MPState.FreeModEnabled) { GameplayModifiers localModifiers = GetPlayerGameplayModifiers(localUserId); if (localModifiers.songSpeed != gameplayModifiers.songSpeed) @@ -198,13 +199,13 @@ public override void HandleMenuRpcManagerSelectedGameplayModifiers(string userId } } - public override void HandleMenuRpcManagerClearSelectedGameplayModifiers(string userId) + public override void HandleMenuRpcManagerClearRecommendedGameplayModifiers(string userId) { ExtendedPlayer? player = _playerManager.GetExtendedPlayer(userId); if (player != null) player.lastModifiers = null; - base.HandleMenuRpcManagerClearSelectedGameplayModifiers(userId); - if (userId == hostUserId && MPState.FreeModEnabled) + base.HandleMenuRpcManagerClearRecommendedGameplayModifiers(userId); + if (userId == partyOwnerId && MPState.FreeModEnabled) { GameplayModifiers localModifiers = GetPlayerGameplayModifiers(localUserId); if (localModifiers.songSpeed != GameplayModifiers.SongSpeed.Normal) diff --git a/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs b/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs index 5f24bb5..6ab05ca 100644 --- a/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs @@ -17,21 +17,21 @@ internal class EnableCustomLevelsPatch /// static bool Prefix(ref bool __result) { - __result = MPState.CurrentGameType == MultiplayerGameType.Private && MPState.CustomSongsEnabled; + __result = MPState.CurrentGameType != MultiplayerGameType.QuickPlay && MPState.CustomSongsEnabled; return false; } } - [HarmonyPatch(typeof(HostLobbySetupViewController), nameof(HostLobbySetupViewController.SetPlayersMissingLevelText), MethodType.Normal)] + [HarmonyPatch(typeof(LobbySetupViewController), nameof(LobbySetupViewController.SetPlayersMissingLevelText), MethodType.Normal)] internal class MissingLevelStartPatch { /// /// Disables starting of game if not all players have song. /// - static void Prefix(HostLobbySetupViewController __instance, string playersMissingLevelText, ref Button ____startGameButton) + static void Prefix(LobbySetupViewController __instance, string playersMissingLevelText, ref Button ____startGameButton) { if (____startGameButton.interactable) - __instance.SetStartGameEnabled(playersMissingLevelText == null, HostLobbySetupViewController.CannotStartGameReason.None); + __instance.SetStartGameEnabled(CannotStartGameReason.None); } } @@ -62,24 +62,6 @@ static bool Prefix(string levelId, ref Task __result) } } - [HarmonyPatch(typeof(NetworkPlayerEntitlementChecker), nameof(NetworkPlayerEntitlementChecker.GetPlayerLevelEntitlementsAsync), MethodType.Normal)] - internal class StartGameLevelEntitlementPatch - { - /// - /// Changes the return value if it returns 'NotDownloaded' so that the host can start the game. - /// - static void Postfix(ref Task __result) - { - __result = __result.ContinueWith(r => - { - if (r.Result == EntitlementsStatus.NotDownloaded) - return EntitlementsStatus.Ok; - else - return r.Result; - }); - } - } - [HarmonyPatch(typeof(CenterStageScreenController), nameof(CenterStageScreenController.HandleLobbyPlayersDataModelDidChange), MethodType.Normal)] internal class CenterStageGameDataPatch { diff --git a/MultiplayerExtensions/HarmonyPatches/HarmonyManager.cs b/MultiplayerExtensions/HarmonyPatches/HarmonyManager.cs index b5ba8e2..bdc6738 100644 --- a/MultiplayerExtensions/HarmonyPatches/HarmonyManager.cs +++ b/MultiplayerExtensions/HarmonyPatches/HarmonyManager.cs @@ -34,7 +34,6 @@ static HarmonyManager() AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); - AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); diff --git a/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs b/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs index ffb0457..7647047 100644 --- a/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs @@ -1,5 +1,5 @@ using HarmonyLib; -using MultiplayerExtensions.OverrideClasses; +using MultiplayerExtensions.Extensions; using MultiplayerExtensions.Sessions; using System; using System.Collections.Generic; @@ -17,7 +17,7 @@ class LobbyPlayersDataModelPatch #pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. private static readonly MethodInfo _playersDataModelAttacher = SymbolExtensions.GetMethodInfo(() => PlayerDataModelAttacher(null)); - private static readonly MethodInfo _gameStateControllerAttacher = SymbolExtensions.GetMethodInfo(() => GameStateControllerAttacher(null)); + //private static readonly MethodInfo _gameStateControllerAttacher = SymbolExtensions.GetMethodInfo(() => GameStateControllerAttacher(null)); #pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. private static readonly MethodInfo _playersDataModelMethod = _rootMethod.MakeGenericMethod(new Type[] { typeof(LobbyPlayersDataModel) }); @@ -36,11 +36,11 @@ static IEnumerable Transpiler(IEnumerable inst codes[i] = newCode; } - if (codes[i].Calls(_gameStateControllerMethod)) - { - CodeInstruction newCode = new CodeInstruction(OpCodes.Callvirt, _gameStateControllerAttacher); - codes[i] = newCode; - } + //if (codes[i].Calls(_gameStateControllerMethod)) + //{ + // CodeInstruction newCode = new CodeInstruction(OpCodes.Callvirt, _gameStateControllerAttacher); + // codes[i] = newCode; + //} } } @@ -49,13 +49,13 @@ static IEnumerable Transpiler(IEnumerable inst private static FromBinderNonGeneric PlayerDataModelAttacher(ConcreteBinderNonGeneric contract) { - return contract.To(); + return contract.To(); } - private static FromBinderNonGeneric GameStateControllerAttacher(ConcreteBinderNonGeneric contract) - { - return contract.To(); - } + //private static FromBinderNonGeneric GameStateControllerAttacher(ConcreteBinderNonGeneric contract) + //{ + // //return contract.To(); + //} } [HarmonyPatch(typeof(MultiplayerMenuInstaller), nameof(MultiplayerMenuInstaller.InstallBindings))] @@ -85,7 +85,7 @@ static IEnumerable Transpiler(IEnumerable inst private static FromBinderNonGeneric LevelLoaderAttacher(DiContainer contract) { - return contract.Bind(typeof(MultiplayerLevelLoader), typeof(ITickable)).To(); + return contract.Bind(typeof(MultiplayerLevelLoader), typeof(ITickable)).To(); } } diff --git a/MultiplayerExtensions/Installers/MPMenuInstaller.cs b/MultiplayerExtensions/Installers/MPMenuInstaller.cs index 1942381..d1b54fc 100644 --- a/MultiplayerExtensions/Installers/MPMenuInstaller.cs +++ b/MultiplayerExtensions/Installers/MPMenuInstaller.cs @@ -19,21 +19,18 @@ public override void Start() { Plugin.Log?.Info("Installing Interface"); - HostLobbySetupViewController hostViewController = Container.Resolve(); - Container.InstantiateComponent(hostViewController.gameObject); - - ClientLobbySetupViewController clientViewController = Container.Resolve(); - Container.InstantiateComponent(clientViewController.gameObject); + LobbySetupViewController lobbySetupViewController = Container.Resolve(); + Container.InstantiateComponent(lobbySetupViewController.gameObject); CenterStageScreenController centerScreenController = Container.Resolve(); Container.InstantiateComponent(centerScreenController.gameObject); - ServerPlayerListController playerListController = Container.Resolve(); - GameServerPlayersTableView playersTableView = playerListController.GetField("_gameServerPlayersTableView"); + ServerPlayerListViewController playerListController = Container.Resolve(); + GameServerPlayersTableView playersTableView = playerListController.GetField("_gameServerPlayersTableView"); GameServerPlayerTableCell playerTableCell = playersTableView.GetField("_gameServerPlayerCellPrefab"); GameServerPlayerTableCell newPlayerTableCell = GameObject.Instantiate(playerTableCell); newPlayerTableCell.gameObject.SetActive(false); - PlayerTableCellStub playerTableCellStub = newPlayerTableCell.gameObject.AddComponent(); + ExtendedPlayerTableCell playerTableCellStub = newPlayerTableCell.gameObject.AddComponent(); playerTableCellStub.Construct(newPlayerTableCell); Destroy(newPlayerTableCell.GetComponent()); playersTableView.SetField("_gameServerPlayerCellPrefab", playerTableCellStub); diff --git a/MultiplayerExtensions/MPState.cs b/MultiplayerExtensions/MPState.cs index 3da9e82..f249bb1 100644 --- a/MultiplayerExtensions/MPState.cs +++ b/MultiplayerExtensions/MPState.cs @@ -146,4 +146,11 @@ internal set } } } + + public enum MultiplayerGameType + { + QuickPlay, + Private, + None + } } diff --git a/MultiplayerExtensions/MultiplayerExtensions.csproj b/MultiplayerExtensions/MultiplayerExtensions.csproj index 48dbee0..12a5951 100644 --- a/MultiplayerExtensions/MultiplayerExtensions.csproj +++ b/MultiplayerExtensions/MultiplayerExtensions.csproj @@ -36,8 +36,7 @@ - - + @@ -202,7 +201,7 @@ - + @@ -222,9 +221,6 @@ - - - diff --git a/MultiplayerExtensions/OverrideClasses/GameStateControllerStub.cs b/MultiplayerExtensions/OverrideClasses/GameStateControllerStub.cs deleted file mode 100644 index ce2ee5e..0000000 --- a/MultiplayerExtensions/OverrideClasses/GameStateControllerStub.cs +++ /dev/null @@ -1,216 +0,0 @@ -using IPA.Utilities; -using MultiplayerExtensions.Packets; -using MultiplayerExtensions.Sessions; -using MultiplayerExtensions.Utilities; -using Polyglot; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace MultiplayerExtensions.OverrideClasses -{ - class GameStateControllerStub : LobbyGameStateController, ILobbyHostGameStateController, ILobbyGameStateController, IDisposable - { - protected readonly PacketManager _packetManager; - protected readonly ExtendedPlayerManager _extendedPlayerManager; - - private static readonly SemVer.Version _minVersionStartPrimed = new SemVer.Version("0.4.5"); - - internal GameStateControllerStub(PacketManager packetManager, ExtendedPlayerManager extendedPlayerManager) - { - _packetManager = packetManager; - _extendedPlayerManager = extendedPlayerManager; - } - - public new void Activate() - { - _multiplayerSessionManager.playerStateChangedEvent += OnPlayerStateChanged; - _lobbyGameState.gameStateDidChangeEvent -= base.HandleGameStateDidChange; - _lobbyGameState.gameStateDidChangeEvent += HandleGameStateDidChange; - base.Activate(); - - (this as ILobbyGameStateController).levelFinishedEvent += handleLevelFinished; - } - - public new void Deactivate() - { - _multiplayerSessionManager.playerStateChangedEvent -= OnPlayerStateChanged; - _menuRpcManager.startedLevelEvent -= HandleRpcStartedLevel; - _menuRpcManager.cancelledLevelStartEvent -= HandleRpcCancelledLevel; - _lobbyGameState.gameStateDidChangeEvent -= HandleGameStateDidChange; - _lobbyGameState.gameStateDidChangeEvent += base.HandleGameStateDidChange; - base.Deactivate(); - - (this as ILobbyGameStateController).levelFinishedEvent -= handleLevelFinished; - } - - public new void StartListeningToGameStart() - { - base.StartListeningToGameStart(); - _menuRpcManager.startedLevelEvent -= HandleRpcStartedLevel; - _menuRpcManager.startedLevelEvent += HandleRpcStartedLevel; - _menuRpcManager.startedLevelEvent -= base.HandleMenuRpcManagerStartedLevel; - _menuRpcManager.cancelledLevelStartEvent -= HandleRpcCancelledLevel; - _menuRpcManager.cancelledLevelStartEvent += HandleRpcCancelledLevel; - _menuRpcManager.cancelledLevelStartEvent -= base.HandleMenuRpcManagerCancelledLevelStart; - } - - public override void StopListeningToGameStart() - { - _menuRpcManager.startedLevelEvent -= HandleRpcStartedLevel; - _menuRpcManager.cancelledLevelStartEvent -= HandleRpcCancelledLevel; - base.StopListeningToGameStart(); - } - - private bool IsPlayerReady(IConnectedPlayer player) - { - if (player.HasState("start_primed")) return true; - - // player is not modded: always assume ready - if (!player.HasState("modded")) return true; - - var extendedPlayer = _extendedPlayerManager.GetExtendedPlayer(player); - // did not receive mpexVersion from player or the version is too old: assume the player is ready to prevent getting stuck at "Loading..." screen - if (extendedPlayer == null) return true; - if (extendedPlayer.mpexVersion == null || extendedPlayer.mpexVersion < _minVersionStartPrimed) return true; - - return false; - } - - private void OnPlayerStateChanged(IConnectedPlayer player) - { - if (starting) - { - if (_multiplayerSessionManager.connectedPlayers.All(IsPlayerReady) && _multiplayerSessionManager.LocalPlayerHasState("start_primed")) - { - Plugin.Log.Debug("All players ready, starting game."); - StartLevel(); - } - } - } - - public new void StartGame() - { - _multiplayerSessionManager.SetLocalPlayerState("start_primed", false); - starting = true; - - if (!Plugin.Config.HostPick) - { - ILobbyPlayerDataModel localPlayerDataModel = _lobbyPlayersDataModel.GetLobbyPlayerDataModel(_lobbyPlayersDataModel.localUserId); - IEnumerable validDataModels = _lobbyPlayersDataModel.playersData.Values.Where(data => data.beatmapLevel != null); - ILobbyPlayerDataModel chosenPlayerDataModel = validDataModels.ElementAt(new Random().Next(0, validDataModels.Count())); - localPlayerDataModel.beatmapLevel = chosenPlayerDataModel.beatmapLevel; - localPlayerDataModel.beatmapDifficulty = chosenPlayerDataModel.beatmapDifficulty; - localPlayerDataModel.beatmapCharacteristic = chosenPlayerDataModel.beatmapCharacteristic; - localPlayerDataModel.gameplayModifiers = chosenPlayerDataModel.gameplayModifiers; - _menuRpcManager.SelectBeatmap(new BeatmapIdentifierNetSerializable(chosenPlayerDataModel.beatmapLevel.levelID, chosenPlayerDataModel.beatmapCharacteristic.serializedName, chosenPlayerDataModel.beatmapDifficulty)); - _menuRpcManager.SelectGameplayModifiers(chosenPlayerDataModel.gameplayModifiers); - if (_lobbyPlayersDataModel is LobbyPlayersDataModel playersDataModel) - playersDataModel.NotifyModelChange(_lobbyPlayersDataModel.localUserId); - } - - base.StartGame(); - _multiplayerLevelLoader.countdownFinishedEvent -= base.HandleMultiplayerLevelLoaderCountdownFinished; - _multiplayerLevelLoader.countdownFinishedEvent += HandleCountdown; - } - - public new void CancelGame() - { - starting = false; - _multiplayerSessionManager.SetLocalPlayerState("start_primed", false); - _multiplayerLevelLoader.countdownFinishedEvent -= HandleCountdown; - _multiplayerLevelLoader.countdownFinishedEvent += base.HandleMultiplayerLevelLoaderCountdownFinished; - base.CancelGame(); - } - - public new void HandleGameStateDidChange(MultiplayerGameState newGameState) - { - base.HandleGameStateDidChange(newGameState); - MPState.CurrentGameState = newGameState; - MPEvents.RaiseGameStateChanged(_lobbyGameState, newGameState); - } - - public new void SetMultiplayerGameType(MultiplayerGameType multiplayerGameType) - { - base.SetMultiplayerGameType(multiplayerGameType); - MPState.CurrentGameType = multiplayerGameType; - } - - private void HandleRpcStartedLevel(string userId, BeatmapIdentifierNetSerializable beatmapId, GameplayModifiers gameplayModifiers, float startTime) - { - if (_multiplayerSessionManager.connectionOwner.HasState("freemod")) - gameplayModifiers = _lobbyPlayersDataModel.GetPlayerGameplayModifiers(_lobbyPlayersDataModel.localUserId); - - _multiplayerSessionManager.SetLocalPlayerState("start_primed", false); - starting = true; - base.HandleMenuRpcManagerStartedLevel(userId, beatmapId, gameplayModifiers, startTime); - _multiplayerLevelLoader.countdownFinishedEvent -= base.HandleMultiplayerLevelLoaderCountdownFinished; - _multiplayerLevelLoader.countdownFinishedEvent += HandleCountdown; - } - - private void HandleRpcCancelledLevel(string userId) - { - starting = false; - _multiplayerSessionManager.SetLocalPlayerState("start_primed", false); - _multiplayerLevelLoader.countdownFinishedEvent -= HandleCountdown; - _multiplayerLevelLoader.countdownFinishedEvent += base.HandleMultiplayerLevelLoaderCountdownFinished; - base.HandleMenuRpcManagerCancelledLevelStart(userId); - } - - private void HandleCountdown(IPreviewBeatmapLevel previewBeatmapLevel, BeatmapDifficulty beatmapDifficulty, BeatmapCharacteristicSO beatmapCharacteristic, IDifficultyBeatmap difficultyBeatmap, GameplayModifiers gameplayModifiers) - { - Plugin.Log?.Debug("Map finished loading, waiting for other players..."); - - this.previewBeatmapLevel = previewBeatmapLevel; - this.beatmapDifficulty = beatmapDifficulty; - this.beatmapCharacteristic = beatmapCharacteristic; - this.difficultyBeatmap = difficultyBeatmap; - this.gameplayModifiers = gameplayModifiers; - - _multiplayerSessionManager.SetLocalPlayerState("start_primed", true); - if (this._levelStartedOnTime && difficultyBeatmap != null && this._multiplayerSessionManager.localPlayer.WantsToPlayNextLevel()) - { - OnPlayerStateChanged(_multiplayerSessionManager.localPlayer); - } - else - { - Plugin.Log?.Debug($"Starting level in a maybe bad way. levelStartedOnTime:{_levelStartedOnTime} | difficultyBeatmap:{difficultyBeatmap?.level?.songName ?? "NULL"} | localPlayer.WantsToPlayNextLevel:{_multiplayerSessionManager.localPlayer.WantsToPlayNextLevel()}"); - StartLevel(); - } - } - - private void StartLevel() - { - starting = false; - base.HandleMultiplayerLevelLoaderCountdownFinished(previewBeatmapLevel, beatmapDifficulty, beatmapCharacteristic, difficultyBeatmap, gameplayModifiers); - } - - private void handleLevelFinished(MultiplayerLevelScenesTransitionSetupDataSO sceneSetupData, MultiplayerResultsData resultsData) - { - if (resultsData.localPlayerResultData.levelCompletionResults == null || !Plugin.Config.Statistics) - return; - - string difficulty = sceneSetupData.beatmapDifficulty.ToString(); - string characteristic = sceneSetupData.beatmapCharacteristic.serializedName; - int timePlayed = (int)Math.Floor(resultsData.localPlayerResultData.levelCompletionResults.endSongTime); - bool pass = resultsData.localPlayerResultData.levelCompletionResults.levelEndStateType == LevelCompletionResults.LevelEndStateType.Cleared; - int cutNotes = resultsData.localPlayerResultData.levelCompletionResults.badCutsCount + resultsData.localPlayerResultData.levelCompletionResults.notGoodCount + resultsData.localPlayerResultData.levelCompletionResults.okCount + resultsData.localPlayerResultData.levelCompletionResults.goodCutsCount; - int missedNotes = resultsData.localPlayerResultData.levelCompletionResults.missedCount; - int score = resultsData.localPlayerResultData.levelCompletionResults.rawScore; - double accuracy = score != 0 ? Math.Floor(100 *((double)ScoreModel.MaxRawScoreForNumberOfNotes(sceneSetupData.difficultyBeatmap.beatmapData.cuttableNotesType) / score))/100 : 0; - string ? hash = Utilities.Utils.LevelIdToHash(sceneSetupData.previewBeatmapLevel.levelID); - if (hash != null) - _ = Statistics.PlayMap(ExtendedPlayerManager.localPlatformID, (int)ExtendedPlayerManager.localPlatform, MPState.CurrentMasterServer.hostname, hash, difficulty, characteristic, timePlayed, pass, cutNotes, missedNotes, score, accuracy); - //_ = Statistics.PlayMap(hash, sceneSetupData.beatmapDifficulty.ToString(), sceneSetupData.beatmapCharacteristic.serializedName, (int)Math.Floor(resultsData.localPlayerResultData.levelCompletionResults.endSongTime), (int)ExtendedPlayerManager.localPlatform, MPState.CurrentMasterServer.hostname); - } - - private bool starting; - - private IPreviewBeatmapLevel? previewBeatmapLevel; - private BeatmapDifficulty beatmapDifficulty; - private BeatmapCharacteristicSO? beatmapCharacteristic; - private IDifficultyBeatmap? difficultyBeatmap; - private GameplayModifiers? gameplayModifiers; - } -} diff --git a/MultiplayerExtensions/Sessions/SessionManager.cs b/MultiplayerExtensions/Sessions/SessionManager.cs index cf7d460..43b1157 100644 --- a/MultiplayerExtensions/Sessions/SessionManager.cs +++ b/MultiplayerExtensions/Sessions/SessionManager.cs @@ -32,6 +32,7 @@ public void Initialize() public void Dispose() { + _sessionManager.connectedEvent -= HandleConnected; _sessionManager.playerStateChangedEvent -= HandlePlayerStateChanged; } diff --git a/MultiplayerExtensions/UI/ClientLobbySetupPanel.bsml b/MultiplayerExtensions/UI/ClientLobbySetupPanel.bsml deleted file mode 100644 index d43ec43..0000000 --- a/MultiplayerExtensions/UI/ClientLobbySetupPanel.bsml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/MultiplayerExtensions/UI/ClientLobbySetupPanel.cs b/MultiplayerExtensions/UI/ClientLobbySetupPanel.cs deleted file mode 100644 index 65e3fd6..0000000 --- a/MultiplayerExtensions/UI/ClientLobbySetupPanel.cs +++ /dev/null @@ -1,250 +0,0 @@ -using BeatSaberMarkupLanguage.Attributes; -using BeatSaberMarkupLanguage.Components; -using BeatSaberMarkupLanguage.Components.Settings; -using BeatSaberMarkupLanguage.ViewControllers; -using HMUI; -using MultiplayerExtensions.OverrideClasses; -using Polyglot; -using System.Linq; -using UnityEngine; -using Zenject; - -namespace MultiplayerExtensions.UI -{ - class ClientLobbySetupPanel : BSMLResourceViewController - { - - public override string ResourceName => "MultiplayerExtensions.UI.HostLobbySetupPanel.bsml"; - private IMultiplayerSessionManager sessionManager; - - CurvedTextMeshPro? modifierText; - - [Inject] - internal void Inject(IMultiplayerSessionManager sessionManager, ClientLobbySetupViewController clientViewController, MultiplayerLevelLoader levelLoader) - { - this.sessionManager = sessionManager; - base.DidActivate(true, false, true); - - clientViewController.didActivateEvent += OnActivate; - } - - #region UIComponents - [UIComponent("CustomSongsToggle")] - public ToggleSetting customSongsToggle = null!; - - [UIComponent("FreeModToggle")] - public ToggleSetting freeModToggle = null!; - - [UIComponent("HostPickToggle")] - public ToggleSetting hostPickToggle = null!; - - [UIComponent("VerticalHUDToggle")] - public ToggleSetting verticalHUDToggle = null!; - - [UIComponent("DefaultHUDToggle")] - public ToggleSetting defaultHUDToggle = null!; - - [UIComponent("HologramToggle")] - public ToggleSetting hologramToggle = null!; - - [UIComponent("LagReducerToggle")] - public ToggleSetting lagReducerToggle = null!; - - [UIComponent("MissLightingToggle")] - public ToggleSetting missLightingToggle = null!; - - [UIComponent("DownloadProgressText")] - public FormattableText downloadProgressText = null!; - #endregion - - #region UIValues - [UIValue("CustomSongs")] - public bool CustomSongs - { - get => MPState.CustomSongsEnabled; - set { - if (MPState.CustomSongsEnabled != value) - { - MPState.CustomSongsEnabled = value; - MPEvents.RaiseCustomSongsChanged(this, value); - } - } - } - - [UIValue("FreeMod")] - public bool FreeMod - { - get => MPState.FreeModEnabled; - set { - if (MPState.FreeModEnabled != value) - { - MPState.FreeModEnabled = value; - MPEvents.RaiseFreeModChanged(this, value); - } - } - } - - [UIValue("HostPick")] - public bool HostPick - { - get => MPState.HostPickEnabled; - set - { - if (MPState.HostPickEnabled != value) - { - MPState.HostPickEnabled = value; - MPEvents.RaiseHostPickChanged(this, value); - } - } - } - - [UIValue("VerticalHUD")] - public bool VerticalHUD - { - get => Plugin.Config.VerticalHUD; - set { Plugin.Config.VerticalHUD = value; } - } - - [UIValue("DefaultHUD")] - public bool DefaultHUD - { - get => Plugin.Config.SingleplayerHUD; - set { Plugin.Config.SingleplayerHUD = value; } - } - - [UIValue("Hologram")] - public bool Hologram - { - get => Plugin.Config.Hologram; - set { Plugin.Config.Hologram = value; } - } - - [UIValue("LagReducer")] - public bool LagReducer - { - get => Plugin.Config.LagReducer; - set { Plugin.Config.LagReducer = value; } - } - - [UIValue("MissLighting")] - public bool MissLighting - { - get => Plugin.Config.MissLighting; - set { Plugin.Config.MissLighting = value; } - } - - [UIValue("DownloadProgress")] - public string DownloadProgress - { - get => downloadProgressText.text; - set { downloadProgressText.text = value; } - } - #endregion - - #region UIActions - [UIAction("SetCustomSongs")] - public void SetCustomSongs(bool value) - { - CustomSongs = value; - customSongsToggle.Value = value; - } - - [UIAction("SetFreeMod")] - public void SetFreeMod(bool value) - { - FreeMod = value; - freeModToggle.Value = value; - SetModifierText(); - } - - [UIAction("SetHostPick")] - public void SetHostPick(bool value) - { - HostPick = value; - hostPickToggle.Value = value; - } - - [UIAction("SetVerticalHUD")] - public void SetVerticalHUD(bool value) - { - VerticalHUD = value; - verticalHUDToggle.Value = value; - - DefaultHUD = !(!DefaultHUD || !value); - defaultHUDToggle.Value = !(!DefaultHUD || !value); - } - - [UIAction("SetDefaultHUD")] - public void SetDefaultHUD(bool value) - { - DefaultHUD = value; - defaultHUDToggle.Value = value; - - VerticalHUD = VerticalHUD || value; - verticalHUDToggle.Value = VerticalHUD || value; - } - - [UIAction("SetHologram")] - public void SetHologram(bool value) - { - Hologram = value; - hologramToggle.Value = value; - } - - [UIAction("SetLagReducer")] - public void SetLagReducer(bool value) - { - LagReducer = value; - lagReducerToggle.Value = value; - } - - [UIAction("SetMissLighting")] - public void SetMissLighting(bool value) - { - MissLighting = value; - missLightingToggle.Value = value; - } - #endregion - - private void OnActivate(bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling) - { - sessionManager.playerStateChangedEvent += OnPlayerStateChanged; - customSongsToggle.interactable = false; - freeModToggle.interactable = false; - - if (firstActivation) - { - Transform spectatorText = transform.Find("Wrapper").Find("SpectatorModeWarningText"); - spectatorText.position = new Vector3(spectatorText.position.x, 0.25f, spectatorText.position.z); - } - - if (sessionManager.connectionOwner != null) - OnPlayerStateChanged(sessionManager.connectionOwner); - } - - private void OnPlayerStateChanged(IConnectedPlayer player) - { - customSongsToggle.interactable = false; - freeModToggle.interactable = false; - hostPickToggle.interactable = false; - if (player.userId != sessionManager.localPlayer.userId && player.isConnectionOwner) - { - SetCustomSongs(player.HasState("customsongs")); - SetFreeMod(player.HasState("freemod")); - SetHostPick(player.HasState("hostpick")); - } - } - - private void SetModifierText() - { - if (modifierText == null) - { - modifierText = Resources.FindObjectsOfTypeAll().ToList().Find(text => text.gameObject.name == "SuggestedModifiers"); - Destroy(modifierText.gameObject.GetComponent()); - } - - if (modifierText != null) - modifierText.text = MPState.FreeModEnabled ? "Selected Modifiers" : Localization.Get("SUGGESTED_MODIFIERS"); - } - } -} diff --git a/MultiplayerExtensions/UI/HostLobbySetupPanel.bsml b/MultiplayerExtensions/UI/LobbySetupPanel.bsml similarity index 100% rename from MultiplayerExtensions/UI/HostLobbySetupPanel.bsml rename to MultiplayerExtensions/UI/LobbySetupPanel.bsml diff --git a/MultiplayerExtensions/UI/HostLobbySetupPanel.cs b/MultiplayerExtensions/UI/LobbySetupPanel.cs similarity index 97% rename from MultiplayerExtensions/UI/HostLobbySetupPanel.cs rename to MultiplayerExtensions/UI/LobbySetupPanel.cs index 953e04e..1291c1f 100644 --- a/MultiplayerExtensions/UI/HostLobbySetupPanel.cs +++ b/MultiplayerExtensions/UI/LobbySetupPanel.cs @@ -12,15 +12,15 @@ namespace MultiplayerExtensions.UI { - class HostLobbySetupPanel : BSMLResourceViewController + class LobbySetupPanel : BSMLResourceViewController { - public override string ResourceName => "MultiplayerExtensions.UI.HostLobbySetupPanel.bsml"; + public override string ResourceName => "MultiplayerExtensions.UI.LobbySetupPanel.bsml"; private IMultiplayerSessionManager sessionManager; CurvedTextMeshPro? modifierText; [Inject] - internal void Inject(IMultiplayerSessionManager sessionManager, HostLobbySetupViewController hostViewController, MultiplayerLevelLoader levelLoader) + internal void Inject(IMultiplayerSessionManager sessionManager, LobbySetupViewController hostViewController, MultiplayerLevelLoader levelLoader) { this.sessionManager = sessionManager; base.DidActivate(true, false, true); From 8ddf104dea1b8fb0cd13781d28ce795afa4cdf71 Mon Sep 17 00:00:00 2001 From: MT Date: Tue, 20 Jul 2021 19:57:57 -0400 Subject: [PATCH 02/41] ExtendedSessionManager --- .../Environments/LobbyAvatarManager.cs | 14 +- .../Environments/LobbyAvatarNameTag.cs | 2 +- .../Environments/LobbyEnvironmentManager.cs | 19 +-- .../Environments/MultiplayerActivePlayer.cs | 10 +- .../MultiplayerGameplayLighting.cs | 8 +- .../Extensions/ExtendedEntitlementChecker.cs | 91 ++++++++++ .../Extensions/ExtendedGameStateController.cs | 6 + .../ExtendedPlayer.cs | 58 ++++++- .../Extensions/ExtendedPlayersDataModel.cs | 14 +- .../Extensions/ExtendedSessionManager.cs | 160 ++++++++++++++++++ .../HarmonyPatches/CustomSongsPatches.cs | 35 +--- .../HarmonyPatches/EnvironmentPatches.cs | 2 +- .../HarmonyPatches/HarmonyManager.cs | 2 +- .../HarmonyPatches/InstallerPatches.cs | 80 +++++++-- .../Installers/MPCoreInstaller.cs | 11 +- .../Installers/MPGameInstaller.cs | 3 +- MultiplayerExtensions/MPState.cs | 28 ++- .../MultiplayerExtensions.csproj | 2 +- MultiplayerExtensions/Plugin.cs | 1 - .../Sessions/ExtendedPlayerManager.cs | 118 ------------- .../Sessions/ExtendedPlayerPacket.cs | 56 ------ .../Sessions/SessionManager.cs | 66 -------- MultiplayerExtensions/UI/LobbySetupPanel.bsml | 1 - MultiplayerExtensions/UI/LobbySetupPanel.cs | 24 --- MultiplayerExtensions/Utilities/Config.cs | 1 - MultiplayerExtensions/Utilities/Utils.cs | 2 +- MultiplayerExtensions/manifest.json | 4 +- 27 files changed, 434 insertions(+), 384 deletions(-) create mode 100644 MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs create mode 100644 MultiplayerExtensions/Extensions/ExtendedGameStateController.cs rename MultiplayerExtensions/{Sessions => Extensions}/ExtendedPlayer.cs (53%) create mode 100644 MultiplayerExtensions/Extensions/ExtendedSessionManager.cs delete mode 100644 MultiplayerExtensions/Sessions/ExtendedPlayerManager.cs delete mode 100644 MultiplayerExtensions/Sessions/ExtendedPlayerPacket.cs delete mode 100644 MultiplayerExtensions/Sessions/SessionManager.cs diff --git a/MultiplayerExtensions/Environments/LobbyAvatarManager.cs b/MultiplayerExtensions/Environments/LobbyAvatarManager.cs index cc22b72..4741009 100644 --- a/MultiplayerExtensions/Environments/LobbyAvatarManager.cs +++ b/MultiplayerExtensions/Environments/LobbyAvatarManager.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using IPA.Utilities; -using MultiplayerExtensions.Sessions; +using MultiplayerExtensions.Extensions; using UnityEngine; using Zenject; @@ -9,18 +9,16 @@ namespace MultiplayerExtensions.Environments { public class LobbyAvatarManager : IInitializable, IDisposable { - protected readonly IMultiplayerSessionManager _sessionManager; - protected readonly ExtendedPlayerManager _playerManager; + protected readonly ExtendedSessionManager _sessionManager; protected readonly MultiplayerLobbyAvatarManager _avatarManager; protected Dictionary? _refPlayerIdToAvatarMap; private Dictionary _extendedPlayers; - internal LobbyAvatarManager(IMultiplayerSessionManager sessionManager, ExtendedPlayerManager playerManager, MultiplayerLobbyAvatarManager avatarManager) + internal LobbyAvatarManager(IMultiplayerSessionManager sessionManager, MultiplayerLobbyAvatarManager avatarManager) { - _sessionManager = sessionManager; - _playerManager = playerManager; + _sessionManager = (sessionManager as ExtendedSessionManager)!; _avatarManager = avatarManager; _refPlayerIdToAvatarMap = null; @@ -32,14 +30,14 @@ public void Initialize() { MPEvents.LobbyAvatarCreated += HandleLobbyAvatarCreated; _sessionManager.playerDisconnectedEvent += HandlePlayerDisconnected; - _playerManager.extendedPlayerConnectedEvent += HandleExtendedPlayerConnected; + _sessionManager.extendedPlayerConnectedEvent += HandleExtendedPlayerConnected; } public void Dispose() { MPEvents.LobbyAvatarCreated -= HandleLobbyAvatarCreated; _sessionManager.playerDisconnectedEvent -= HandlePlayerDisconnected; - _playerManager.extendedPlayerConnectedEvent -= HandleExtendedPlayerConnected; + _sessionManager.extendedPlayerConnectedEvent -= HandleExtendedPlayerConnected; } #region Events diff --git a/MultiplayerExtensions/Environments/LobbyAvatarNameTag.cs b/MultiplayerExtensions/Environments/LobbyAvatarNameTag.cs index 2828c0d..7ab74af 100644 --- a/MultiplayerExtensions/Environments/LobbyAvatarNameTag.cs +++ b/MultiplayerExtensions/Environments/LobbyAvatarNameTag.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using HMUI; -using MultiplayerExtensions.Sessions; +using MultiplayerExtensions.Extensions; using MultiplayerExtensions.Utilities; using UnityEngine; using UnityEngine.UI; diff --git a/MultiplayerExtensions/Environments/LobbyEnvironmentManager.cs b/MultiplayerExtensions/Environments/LobbyEnvironmentManager.cs index 6700692..b0c03d8 100644 --- a/MultiplayerExtensions/Environments/LobbyEnvironmentManager.cs +++ b/MultiplayerExtensions/Environments/LobbyEnvironmentManager.cs @@ -1,7 +1,6 @@ using System; using IPA.Utilities; -using MultiplayerExtensions.Sessions; -using System; +using MultiplayerExtensions.Extensions; using UnityEngine; using Zenject; @@ -9,12 +8,11 @@ namespace MultiplayerExtensions.Environments { public class LobbyEnvironmentManager : IInitializable, IDisposable { - protected readonly IMultiplayerSessionManager _sessionManager; + protected readonly ExtendedSessionManager _sessionManager; protected readonly ILobbyStateDataModel _lobbyStateDataModel; protected readonly MenuEnvironmentManager _menuEnvironmentManager; protected readonly MultiplayerLobbyAvatarPlaceManager _placeManager; protected readonly MultiplayerLobbyCenterStageManager _stageManager; - protected readonly ExtendedPlayerManager _playerManager; private LobbyAvatarPlaceLighting[] _avatarPlaces = Array.Empty(); private float _innerCircleRadius; @@ -22,20 +20,19 @@ public class LobbyEnvironmentManager : IInitializable, IDisposable private float _angleBetweenPlayersWithEvenAdjustment; private float _outerCircleRadius; - internal LobbyEnvironmentManager(IMultiplayerSessionManager sessionManager, ILobbyStateDataModel lobbyStateDataModel, MenuEnvironmentManager menuEnvironmentManager, MultiplayerLobbyAvatarPlaceManager placeManager, MultiplayerLobbyCenterStageManager stageManager, ExtendedPlayerManager playerManager) + internal LobbyEnvironmentManager(IMultiplayerSessionManager sessionManager, ILobbyStateDataModel lobbyStateDataModel, MenuEnvironmentManager menuEnvironmentManager, MultiplayerLobbyAvatarPlaceManager placeManager, MultiplayerLobbyCenterStageManager stageManager) { - _sessionManager = sessionManager; + _sessionManager = (sessionManager as ExtendedSessionManager)!; _lobbyStateDataModel = lobbyStateDataModel; _menuEnvironmentManager = menuEnvironmentManager; _placeManager = placeManager; _stageManager = stageManager; - _playerManager = playerManager; } public void Initialize() { MPEvents.LobbyEnvironmentLoaded += HandleLobbyEnvironmentLoaded; - _playerManager.extendedPlayerConnectedEvent += HandleExtendedPlayerConnected; + _sessionManager.extendedPlayerConnectedEvent += HandleExtendedPlayerConnected; _sessionManager.playerConnectedEvent += HandlePlayerConnected; _sessionManager.playerDisconnectedEvent += HandlePlayerDisconnected; } @@ -43,7 +40,7 @@ public void Initialize() public void Dispose() { MPEvents.LobbyEnvironmentLoaded -= HandleLobbyEnvironmentLoaded; - _playerManager.extendedPlayerConnectedEvent -= HandleExtendedPlayerConnected; + _sessionManager.extendedPlayerConnectedEvent -= HandleExtendedPlayerConnected; _sessionManager.playerConnectedEvent -= HandlePlayerConnected; _sessionManager.playerDisconnectedEvent -= HandlePlayerDisconnected; } @@ -81,12 +78,12 @@ private void HandleLobbyEnvironmentLoaded(object sender, System.EventArgs e) public void SetDefaultPlayerPlaceColors() { SetAllPlayerPlaceColors(Color.black, true); - SetPlayerPlaceColor(_sessionManager.localPlayer, ExtendedPlayerManager.localColor, true); + SetPlayerPlaceColor(_sessionManager.localPlayer, ExtendedSessionManager.localColor, true); foreach (var player in _sessionManager.connectedPlayers) SetPlayerPlaceColor(player, ExtendedPlayer.DefaultColor, false); - foreach (var extendedPlayer in _playerManager.players.Values) + foreach (var extendedPlayer in _sessionManager.extendedPlayers.Values) SetPlayerPlaceColor(extendedPlayer, extendedPlayer.playerColor, true); } diff --git a/MultiplayerExtensions/Environments/MultiplayerActivePlayer.cs b/MultiplayerExtensions/Environments/MultiplayerActivePlayer.cs index 7c8cf41..d2597c8 100644 --- a/MultiplayerExtensions/Environments/MultiplayerActivePlayer.cs +++ b/MultiplayerExtensions/Environments/MultiplayerActivePlayer.cs @@ -1,4 +1,4 @@ -using MultiplayerExtensions.Sessions; +using MultiplayerExtensions.Extensions; using UnityEngine; using Zenject; @@ -8,16 +8,16 @@ public class MultiplayerActivePlayer : MonoBehaviour { protected IConnectedPlayer _connectedPlayer = null!; protected MultiplayerController _multiplayerController = null!; - protected ExtendedPlayerManager _extendedPlayerManager = null!; + protected ExtendedSessionManager _sessionManager = null!; protected IScoreSyncStateManager _scoreProvider = null!; protected MultiplayerLeadPlayerProvider _leadPlayerProvider = null!; [Inject] - internal void Inject(IConnectedPlayer connectedPlayer, MultiplayerController multiplayerController, ExtendedPlayerManager extendedPlayerManager, IScoreSyncStateManager scoreProvider, MultiplayerLeadPlayerProvider leadPlayerProvider) + internal void Inject(IConnectedPlayer connectedPlayer, MultiplayerController multiplayerController, IMultiplayerSessionManager sessionManager, IScoreSyncStateManager scoreProvider, MultiplayerLeadPlayerProvider leadPlayerProvider) { _connectedPlayer = connectedPlayer; _multiplayerController = multiplayerController; - _extendedPlayerManager = extendedPlayerManager; + _sessionManager = (sessionManager as ExtendedSessionManager)!; _scoreProvider = scoreProvider; _leadPlayerProvider = leadPlayerProvider; } @@ -28,7 +28,7 @@ protected void Awake() { MultiplayerGameplayAnimator gameplayAnimator = transform.GetComponentInChildren(); MultiplayerGameplayLighting gameplayLighting = gameplayAnimator.gameObject.AddComponent(); - gameplayLighting.Construct(_connectedPlayer, _multiplayerController, _scoreProvider, _leadPlayerProvider, gameplayAnimator, _extendedPlayerManager); + gameplayLighting.Construct(_connectedPlayer, _multiplayerController, _scoreProvider, _leadPlayerProvider, gameplayAnimator, _sessionManager); } } } diff --git a/MultiplayerExtensions/Environments/MultiplayerGameplayLighting.cs b/MultiplayerExtensions/Environments/MultiplayerGameplayLighting.cs index d7c2831..d093a22 100644 --- a/MultiplayerExtensions/Environments/MultiplayerGameplayLighting.cs +++ b/MultiplayerExtensions/Environments/MultiplayerGameplayLighting.cs @@ -1,5 +1,5 @@ using IPA.Utilities; -using MultiplayerExtensions.Sessions; +using MultiplayerExtensions.Extensions; using UnityEngine; namespace MultiplayerExtensions.Environments @@ -11,7 +11,7 @@ class MultiplayerGameplayLighting : MonoBehaviour protected IScoreSyncStateManager _scoreProvider = null!; protected MultiplayerLeadPlayerProvider _leadPlayerProvider = null!; protected MultiplayerGameplayAnimator _gameplayAnimator = null!; - protected ExtendedPlayerManager _extendedPlayerManager = null!; + protected ExtendedSessionManager _sessionManager = null!; protected LightsAnimator[] _allLights = null!; protected LightsAnimator[] _gameplayLights = null!; @@ -26,14 +26,14 @@ class MultiplayerGameplayLighting : MonoBehaviour protected MultiplayerSyncState _syncState = null!; - internal void Construct(IConnectedPlayer connectedPlayer, MultiplayerController multiplayerController, IScoreSyncStateManager scoreProvider, MultiplayerLeadPlayerProvider leadPlayerProvider, MultiplayerGameplayAnimator gameplayAnimator, ExtendedPlayerManager extendedPlayerManager) + internal void Construct(IConnectedPlayer connectedPlayer, MultiplayerController multiplayerController, IScoreSyncStateManager scoreProvider, MultiplayerLeadPlayerProvider leadPlayerProvider, MultiplayerGameplayAnimator gameplayAnimator, ExtendedSessionManager sessionManager) { _connectedPlayer = connectedPlayer; _multiplayerController = multiplayerController; _scoreProvider = scoreProvider; _leadPlayerProvider = leadPlayerProvider; _gameplayAnimator = gameplayAnimator; - _extendedPlayerManager = extendedPlayerManager; + _sessionManager = sessionManager; _allLights = gameplayAnimator.GetField("_allLightsAnimators"); _gameplayLights = gameplayAnimator.GetField("_gameplayLightsAnimators"); diff --git a/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs b/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs new file mode 100644 index 0000000..2f5d762 --- /dev/null +++ b/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs @@ -0,0 +1,91 @@ +using BeatSaverSharp; +using System.Collections.Generic; +using System.Threading.Tasks; +using Zenject; + +namespace MultiplayerExtensions.Extensions +{ + public class ExtendedEntitlementChecker : NetworkPlayerEntitlementChecker + { + protected IMultiplayerSessionManager _sessionManager = null!; + + protected Dictionary> _entitlementsDictionary = new Dictionary>(); + protected Dictionary>> _tcsDictionary = new Dictionary>>(); + + [Inject] + internal void Inject(IMultiplayerSessionManager multiplayerSessionManager) + { + _sessionManager = multiplayerSessionManager; + } + + public override void Start() + { + base.Start(); + + this._rpcManager.getIsEntitledToLevelEvent -= base.HandleGetIsEntitledToLevel; + this._rpcManager.getIsEntitledToLevelEvent += HandleGetIsEntitledToLevel; + + this._rpcManager.setIsEntitledToLevelEvent += HandleSetIsEntitledToLevel; + } + + public override void OnDestroy() + { + if (this._rpcManager != null) + { + this._rpcManager.getIsEntitledToLevelEvent -= HandleGetIsEntitledToLevel; + this._rpcManager.getIsEntitledToLevelEvent += base.HandleGetIsEntitledToLevel; + + this._rpcManager.setIsEntitledToLevelEvent -= HandleSetIsEntitledToLevel; + } + + base.OnDestroy(); + } + + public override void HandleGetIsEntitledToLevel(string userId, string levelId) + { + base.HandleGetIsEntitledToLevel(userId, levelId); + } + + public void HandleSetIsEntitledToLevel(string userId, string levelId, EntitlementsStatus entitlement) + { + _entitlementsDictionary[userId][levelId] = entitlement; + + if (_tcsDictionary.TryGetValue(userId, out Dictionary> userDictionary)) + if (userDictionary.TryGetValue(levelId, out TaskCompletionSource entitlementTcs)) + entitlementTcs.SetResult(entitlement); + } + + public override Task GetEntitlementStatus(string levelId) + { + Plugin.Log?.Debug($"Checking level entitlement for '{levelId}'"); + + string? hash = Utilities.Utils.LevelIdToHash(levelId); + if (hash == null) + return base.GetEntitlementStatus(levelId); + + if (SongCore.Collections.songWithHashPresent(hash)) + return Task.FromResult(EntitlementsStatus.Ok); + return Plugin.BeatSaver.Hash(hash).ContinueWith(r => + { + Beatmap? beatmap = r.Result; + if (beatmap == null) + return EntitlementsStatus.NotOwned; + return EntitlementsStatus.NotDownloaded; + }); + } + + public Task GetUserEntitlementStatus(string userId, string levelId) + { + if (userId == _sessionManager.localPlayer.userId) + return GetEntitlementStatus(levelId); + + if (_entitlementsDictionary.TryGetValue(userId, out Dictionary userDictionary)) + if (userDictionary.TryGetValue(levelId, out EntitlementsStatus entitlement)) + return Task.FromResult(entitlement); + + _tcsDictionary[userId][levelId] = new TaskCompletionSource(); + _rpcManager.GetIsEntitledToLevel(levelId); + return _tcsDictionary[userId][levelId].Task; + } + } +} diff --git a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs new file mode 100644 index 0000000..9fb51af --- /dev/null +++ b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs @@ -0,0 +1,6 @@ +namespace MultiplayerExtensions.Extensions +{ + class ExtendedGameStateController : LobbyGameStateController, ILobbyGameStateController + { + } +} diff --git a/MultiplayerExtensions/Sessions/ExtendedPlayer.cs b/MultiplayerExtensions/Extensions/ExtendedPlayer.cs similarity index 53% rename from MultiplayerExtensions/Sessions/ExtendedPlayer.cs rename to MultiplayerExtensions/Extensions/ExtendedPlayer.cs index 17dbb29..dd949f2 100644 --- a/MultiplayerExtensions/Sessions/ExtendedPlayer.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayer.cs @@ -1,11 +1,12 @@ -using UnityEngine; +using LiteNetLib.Utils; +using UnityEngine; -namespace MultiplayerExtensions.Sessions +namespace MultiplayerExtensions.Extensions { public class ExtendedPlayer : IConnectedPlayer { public static readonly Color DefaultColor = new Color(0.031f, 0.752f, 1f); - + private IConnectedPlayer _connectedPlayer; /// @@ -52,4 +53,55 @@ public ExtendedPlayer(IConnectedPlayer player, string platformID, Platform platf public DisconnectedReason disconnectedReason => _connectedPlayer.disconnectedReason; public bool HasState(string state) => _connectedPlayer.HasState(state); } + + public class ExtendedPlayerPacket : INetSerializable, IPoolablePacket + { + public void Release() => ThreadStaticPacketPool.pool.Release(this); + + public void Serialize(NetDataWriter writer) + { + writer.Put(platformID); + writer.Put(mpexVersion); + writer.Put("#" + ColorUtility.ToHtmlStringRGB(playerColor)); + writer.Put((int)platform); + } + + public void Deserialize(NetDataReader reader) + { + this.platformID = reader.GetString(); + this.mpexVersion = reader.GetString(); + + if (!ColorUtility.TryParseHtmlString(reader.GetString(), out playerColor)) + this.playerColor = ExtendedPlayer.DefaultColor; + + //Plugin.Log.Warn($"AvailableBytes: {reader.AvailableBytes}"); + if (reader.AvailableBytes >= 4) // Verify this works when the platform int exists. + this.platform = (Platform)reader.GetInt(); + else + this.platform = Platform.Unknown; + } + + public ExtendedPlayerPacket Init(string platformID, Platform platform, Color playerColor) + { + this.platformID = platformID; + this.mpexVersion = Plugin.PluginMetadata.Version.ToString(); + this.playerColor = playerColor; + this.platform = platform; + return this; + } + + public string platformID = null!; + public Platform platform; + public string mpexVersion = null!; + public Color playerColor; + } + + public enum Platform + { + Unknown = 0, + Steam = 1, + OculusPC = 2, + OculusQuest = 3, + PS4 = 4 + } } diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs index 39d7025..3229b24 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs @@ -1,7 +1,7 @@ using BeatSaverSharp; using MultiplayerExtensions.Beatmaps; using MultiplayerExtensions.Packets; -using MultiplayerExtensions.Sessions; +using MultiplayerExtensions.Extensions; using System; using System.Linq; using System.Threading.Tasks; @@ -11,12 +11,12 @@ namespace MultiplayerExtensions.Extensions class ExtendedPlayersDataModel : LobbyPlayersDataModel, ILobbyPlayersDataModel, IDisposable { protected readonly PacketManager _packetManager; - protected readonly ExtendedPlayerManager _playerManager; + protected readonly ExtendedSessionManager _sessionManager; - internal ExtendedPlayersDataModel(PacketManager packetManager, ExtendedPlayerManager playerManager) + internal ExtendedPlayersDataModel(PacketManager packetManager, IMultiplayerSessionManager sessionManager) { _packetManager = packetManager; - _playerManager = playerManager; + _sessionManager = (sessionManager as ExtendedSessionManager)!; } public new void Activate() @@ -115,7 +115,7 @@ public override void HandleMenuRpcManagerGetRecommendedBeatmap(string userId) { ILobbyPlayerData lobbyPlayerDataModel = this.GetLobbyPlayerDataModel(this.localUserId); IConnectedPlayer user = _multiplayerSessionManager.GetPlayerByUserId(userId); - if (lobbyPlayerDataModel != null && MPState.CurrentGameType != MultiplayerGameType.QuickPlay && user != null && user.HasState("modded") && lobbyPlayerDataModel?.beatmapLevel != null && lobbyPlayerDataModel?.beatmapLevel is PreviewBeatmapStub preview) + if (lobbyPlayerDataModel != null && user != null && user.HasState("modded") && lobbyPlayerDataModel?.beatmapLevel != null && lobbyPlayerDataModel?.beatmapLevel is PreviewBeatmapStub preview) _packetManager.Send(new PreviewBeatmapPacket(preview, lobbyPlayerDataModel.beatmapCharacteristic.serializedName, lobbyPlayerDataModel.beatmapDifficulty)); else if (lobbyPlayerDataModel != null && lobbyPlayerDataModel.beatmapLevel != null) this._menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(lobbyPlayerDataModel.beatmapLevel.levelID, lobbyPlayerDataModel.beatmapCharacteristic.serializedName, lobbyPlayerDataModel.beatmapDifficulty)); @@ -187,7 +187,7 @@ public async override void HandleMenuRpcManagerRecommendBeatmap(string userId, B public override void HandleMenuRpcManagerRecommendGameplayModifiers(string userId, GameplayModifiers gameplayModifiers) { - ExtendedPlayer? player = _playerManager.GetExtendedPlayer(userId); + ExtendedPlayer? player = _sessionManager.GetExtendedPlayer(userId); if (player != null) player.lastModifiers = gameplayModifiers; base.HandleMenuRpcManagerRecommendGameplayModifiers(userId, gameplayModifiers); @@ -201,7 +201,7 @@ public override void HandleMenuRpcManagerRecommendGameplayModifiers(string userI public override void HandleMenuRpcManagerClearRecommendedGameplayModifiers(string userId) { - ExtendedPlayer? player = _playerManager.GetExtendedPlayer(userId); + ExtendedPlayer? player = _sessionManager.GetExtendedPlayer(userId); if (player != null) player.lastModifiers = null; base.HandleMenuRpcManagerClearRecommendedGameplayModifiers(userId); diff --git a/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs b/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs new file mode 100644 index 0000000..64d555b --- /dev/null +++ b/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs @@ -0,0 +1,160 @@ +using MultiplayerExtensions.Packets; +using MultiplayerExtensions.Utilities; +using System; +using System.Collections.Generic; +using UnityEngine; +using Zenject; + +namespace MultiplayerExtensions.Extensions +{ + public class ExtendedSessionManager : MultiplayerSessionManager, IMultiplayerSessionManager + { + protected PacketManager _packetManager = null!; + protected IPlatformUserModel _platformUserModel = null!; + + private Dictionary _extendedPlayers = new Dictionary(); + public Dictionary extendedPlayers { get => _extendedPlayers; } + internal static string? localPlatformID; + internal static Platform localPlatform; + internal static Color localColor; + + public event Action? extendedPlayerConnectedEvent; + + [Inject] + internal void Inject([InjectOptional] PacketManager packetManager, [InjectOptional] IPlatformUserModel platformUserModel) + { + _packetManager = packetManager; + _platformUserModel = platformUserModel; + } + + public new void StartSession(ConnectedPlayerManager connectedPlayerManager) + { + Plugin.Log?.Info("Setting up SessionManager"); + + base.StartSession(connectedPlayerManager); + + MPState.FreeModEnabled = Plugin.Config.FreeMod; + MPState.HostPickEnabled = Plugin.Config.HostPick; + + SetLocalPlayerState("modded", true); + SetLocalPlayerState("freemod", Plugin.Config.FreeMod); + SetLocalPlayerState("hostpick", Plugin.Config.HostPick); + + connectedEvent += HandleConnected; + playerStateChangedEvent += HandlePlayerStateChanged; + + playerConnectedEvent += HandlePlayerConnected; + playerDisconnectedEvent += HandlePlayerDisconnected; + _packetManager.RegisterCallback(HandleExtendedPlayerPacket); + + if (!ColorUtility.TryParseHtmlString(Plugin.Config.Color, out localColor)) + localColor = new Color(0.031f, 0.752f, 1f); + + _platformUserModel.GetUserInfo().ContinueWith(r => + { + localPlatformID = r.Result.platformUserId; + localPlatform = r.Result.platform.ToPlatform(); + + if (Plugin.Config.Statistics) + { + _ = Statistics.AddUser(localPlatformID, (int)localPlatform); + } + }); + } + + public new void EndSession() + { + connectedEvent -= HandleConnected; + playerStateChangedEvent -= HandlePlayerStateChanged; + + playerConnectedEvent -= HandlePlayerConnected; + playerDisconnectedEvent -= HandlePlayerDisconnected; + _packetManager.UnregisterCallback(); + + base.EndSession(); + } + + private void HandleConnected() + { + MPState.LocalPlayerIsHost = localPlayer.isConnectionOwner; + if (Plugin.Config.Statistics) + { + _ = Statistics.UseMaster(localPlatformID, (int)localPlatform, MPState.CurrentMasterServer.hostname, MPState.LocalPlayerIsHost); + } + } + + private void HandlePlayerConnected(IConnectedPlayer player) + { + Plugin.Log?.Info($"Player '{player.userId}' joined"); + if (localPlatformID != null) + { + ExtendedPlayerPacket localPlayerPacket = new ExtendedPlayerPacket().Init(localPlatformID, localPlatform, localColor); + _packetManager.Send(localPlayerPacket); + } + } + + private void HandlePlayerDisconnected(IConnectedPlayer player) + { + Plugin.Log?.Info($"Player '{player.userId}' disconnected"); + // var extendedPlayer = _players[player.userId]; + _extendedPlayers.Remove(player.userId); + } + + private void HandleExtendedPlayerPacket(ExtendedPlayerPacket packet, IConnectedPlayer player) + { + if (_extendedPlayers.ContainsKey(player.userId)) + { + ExtendedPlayer extendedPlayer = _extendedPlayers[player.userId]; + extendedPlayer.platformID = packet.platformID; + extendedPlayer.platform = packet.platform; + extendedPlayer.playerColor = packet.playerColor; + extendedPlayer.mpexVersion = new SemVer.Version(packet.mpexVersion); + } + else + { + Plugin.Log?.Info($"Received 'ExtendedPlayerPacket' from '{player.userId}' with platformID: '{packet.platformID}' mpexVersion: '{packet.mpexVersion}'"); + ExtendedPlayer extendedPlayer = new ExtendedPlayer(player, packet.platformID, packet.platform, new SemVer.Version(packet.mpexVersion), packet.playerColor); + + if (Plugin.PluginMetadata.Version != extendedPlayer.mpexVersion) + { + Plugin.Log?.Warn("###################################################################"); + Plugin.Log?.Warn("Different MultiplayerExtensions version detected!"); + Plugin.Log?.Warn($"The player '{player.userName}' is using MultiplayerExtensions {extendedPlayer.mpexVersion} while you are using MultiplayerExtensions {Plugin.PluginMetadata.Version}"); + Plugin.Log?.Warn("For best compatibility all players should use the same version of MultiplayerExtensions."); + Plugin.Log?.Warn("###################################################################"); + } + + _extendedPlayers[player.userId] = extendedPlayer; + extendedPlayerConnectedEvent?.Invoke(extendedPlayer); + } + } + + private void HandlePlayerStateChanged(IConnectedPlayer player) + { + if (player.isConnectionOwner) + { + if (MPState.CustomSongsEnabled != player.HasState("customsongs")) + { + MPState.CustomSongsEnabled = player.HasState("customsongs"); + MPEvents.RaiseCustomSongsChanged(this, player.HasState("customsongs")); + } + + if (MPState.FreeModEnabled != player.HasState("freemod")) + { + MPState.FreeModEnabled = player.HasState("freemod"); + MPEvents.RaiseCustomSongsChanged(this, player.HasState("freemod")); + } + } + } + + public ExtendedPlayer? GetExtendedPlayer(IConnectedPlayer player) + => GetExtendedPlayer(player.userId); + + public ExtendedPlayer? GetExtendedPlayer(string userId) + { + if (_extendedPlayers.TryGetValue(userId, out ExtendedPlayer extendedPlayer)) + return extendedPlayer; + return null; + } + } +} diff --git a/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs b/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs index 6ab05ca..e3782a1 100644 --- a/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs @@ -17,7 +17,7 @@ internal class EnableCustomLevelsPatch /// static bool Prefix(ref bool __result) { - __result = MPState.CurrentGameType != MultiplayerGameType.QuickPlay && MPState.CustomSongsEnabled; + __result = MPState.CustomSongsEnabled; return false; } } @@ -28,40 +28,13 @@ internal class MissingLevelStartPatch /// /// Disables starting of game if not all players have song. /// - static void Prefix(LobbySetupViewController __instance, string playersMissingLevelText, ref Button ____startGameButton) + static void Prefix(LobbySetupViewController __instance, string playersMissingLevelText, ref Button ____startGameReadyButton) { - if (____startGameButton.interactable) + if (____startGameReadyButton.interactable) __instance.SetStartGameEnabled(CannotStartGameReason.None); } } - [HarmonyPatch(typeof(NetworkPlayerEntitlementChecker), nameof(NetworkPlayerEntitlementChecker.GetEntitlementStatus), MethodType.Normal)] - internal class CustomLevelEntitlementPatch - { - /// - /// Changes the return value of the entitlement checker if it is a custom song. - /// - static bool Prefix(string levelId, ref Task __result) - { - string? hash = Utilities.Utils.LevelIdToHash(levelId); - if (hash == null) - return true; - - if (SongCore.Collections.songWithHashPresent(hash)) - __result = Task.FromResult(EntitlementsStatus.Ok); - else - __result = Plugin.BeatSaver.Hash(hash).ContinueWith(r => - { - Beatmap? beatmap = r.Result; - if (beatmap == null) - return EntitlementsStatus.NotOwned; - return EntitlementsStatus.NotDownloaded; - }); - - return false; - } - } - [HarmonyPatch(typeof(CenterStageScreenController), nameof(CenterStageScreenController.HandleLobbyPlayersDataModelDidChange), MethodType.Normal)] internal class CenterStageGameDataPatch { @@ -89,7 +62,7 @@ static void Postfix(ref GameplayModifierToggle[] ____gameplayModifierToggles) // Plugin.Log.Warn(toggle.gameplayModifier.modifierNameLocalizationKey); //} - bool speedModsEnabled = MPState.CurrentGameType != MultiplayerGameType.Private || !MPState.FreeModEnabled || MPState.LocalPlayerIsHost; + bool speedModsEnabled = !MPState.FreeModEnabled || MPState.LocalPlayerIsHost; ____gameplayModifierToggles.ToList().Find(toggle => toggle.gameplayModifier.modifierNameLocalizationKey == "MODIFIER_SUPER_FAST_SONG").toggle.interactable = speedModsEnabled; ____gameplayModifierToggles.ToList().Find(toggle => toggle.gameplayModifier.modifierNameLocalizationKey == "MODIFIER_FASTER_SONG").toggle.interactable = speedModsEnabled; ____gameplayModifierToggles.ToList().Find(toggle => toggle.gameplayModifier.modifierNameLocalizationKey == "MODIFIER_SLOWER_SONG").toggle.interactable = speedModsEnabled; diff --git a/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs b/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs index 408deec..689b333 100644 --- a/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs @@ -135,7 +135,7 @@ internal class CoreGameHUDController_Start { static void Postfix(CoreGameHUDController __instance, ref GameObject ____songProgressPanelGO, ref GameObject ____energyPanelGO) { - if (MPState.CurrentGameType != MultiplayerGameType.None && Plugin.Config.VerticalHUD) + if (Plugin.Config.VerticalHUD) { Plugin.Log?.Debug("Setting up multiplayer HUD"); diff --git a/MultiplayerExtensions/HarmonyPatches/HarmonyManager.cs b/MultiplayerExtensions/HarmonyPatches/HarmonyManager.cs index bdc6738..00e96c1 100644 --- a/MultiplayerExtensions/HarmonyPatches/HarmonyManager.cs +++ b/MultiplayerExtensions/HarmonyPatches/HarmonyManager.cs @@ -27,7 +27,6 @@ internal static Harmony Harmony static HarmonyManager() { AddDefaultPatch(); - AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); @@ -52,6 +51,7 @@ static HarmonyManager() AddDefaultPatch(); //AddDefaultPatch(); (doesn't support generics) AddDefaultPatch(); + AddDefaultPatch(); } private static void AddDefaultPatch() where T : class diff --git a/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs b/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs index 7647047..094224f 100644 --- a/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs @@ -1,6 +1,5 @@ using HarmonyLib; using MultiplayerExtensions.Extensions; -using MultiplayerExtensions.Sessions; using System; using System.Collections.Generic; using System.Linq; @@ -11,13 +10,13 @@ namespace MultiplayerExtensions.HarmonyPatches { [HarmonyPatch(typeof(LobbyDataModelInstaller), nameof(LobbyDataModelInstaller.InstallBindings))] - class LobbyPlayersDataModelPatch + internal class LobbyPlayersDataModelPatch { private static readonly MethodInfo _rootMethod = typeof(ConcreteBinderNonGeneric).GetMethod(nameof(ConcreteBinderNonGeneric.To), Array.Empty()); #pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. private static readonly MethodInfo _playersDataModelAttacher = SymbolExtensions.GetMethodInfo(() => PlayerDataModelAttacher(null)); - //private static readonly MethodInfo _gameStateControllerAttacher = SymbolExtensions.GetMethodInfo(() => GameStateControllerAttacher(null)); + private static readonly MethodInfo _gameStateControllerAttacher = SymbolExtensions.GetMethodInfo(() => GameStateControllerAttacher(null)); #pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. private static readonly MethodInfo _playersDataModelMethod = _rootMethod.MakeGenericMethod(new Type[] { typeof(LobbyPlayersDataModel) }); @@ -36,11 +35,11 @@ static IEnumerable Transpiler(IEnumerable inst codes[i] = newCode; } - //if (codes[i].Calls(_gameStateControllerMethod)) - //{ - // CodeInstruction newCode = new CodeInstruction(OpCodes.Callvirt, _gameStateControllerAttacher); - // codes[i] = newCode; - //} + if (codes[i].Calls(_gameStateControllerMethod)) + { + CodeInstruction newCode = new CodeInstruction(OpCodes.Callvirt, _gameStateControllerAttacher); + codes[i] = newCode; + } } } @@ -52,14 +51,63 @@ private static FromBinderNonGeneric PlayerDataModelAttacher(ConcreteBinderNonGen return contract.To(); } - //private static FromBinderNonGeneric GameStateControllerAttacher(ConcreteBinderNonGeneric contract) - //{ - // //return contract.To(); - //} + private static FromBinderNonGeneric GameStateControllerAttacher(ConcreteBinderNonGeneric contract) + { + return contract.To(); + } + } + + [HarmonyPatch(typeof(MainSystemInit), nameof(MainSystemInit.InstallBindings), MethodType.Normal)] + internal class EntitlementCheckerPatch + { + private static readonly MethodInfo _rootMethod = typeof(FromBinder).GetMethod(nameof(FromBinder.FromComponentInNewPrefab), new[] { typeof(UnityEngine.Object) }); + private static readonly FieldInfo _sessionManagerPrefab = typeof(MainSystemInit).GetField("_multiplayerSessionManagerPrefab", BindingFlags.NonPublic | BindingFlags.Instance); + private static readonly FieldInfo _entitlementCheckerPrefab = typeof(MainSystemInit).GetField("_networkPlayerEntitlementCheckerPrefab", BindingFlags.NonPublic | BindingFlags.Instance); +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. + private static readonly MethodInfo _sessionManagerAttacher = SymbolExtensions.GetMethodInfo(() => SessionManagerAttacher(null, null)); + private static readonly MethodInfo _entitlementCheckerAttacher = SymbolExtensions.GetMethodInfo(() => EntitlementCheckerAttacher(null, null)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. + + static IEnumerable Transpiler(IEnumerable instructions) + { + var codes = instructions.ToList(); + for (int i = 0; i < codes.Count; i++) + { + if (codes[i].opcode == OpCodes.Ldfld && codes[i].OperandIs(_sessionManagerPrefab)) + { + if (codes[i + 1].opcode == OpCodes.Callvirt && codes[i + 1].Calls(_rootMethod)) + { + CodeInstruction newCode = new CodeInstruction(OpCodes.Callvirt, _sessionManagerAttacher); + codes[i + 1] = newCode; + } + } + + if (codes[i].opcode == OpCodes.Ldfld && codes[i].OperandIs(_entitlementCheckerPrefab)) + { + if (codes[i + 1].opcode == OpCodes.Callvirt && codes[i + 1].Calls(_rootMethod)) + { + CodeInstruction newCode = new CodeInstruction(OpCodes.Callvirt, _entitlementCheckerAttacher); + codes[i + 1] = newCode; + } + } + } + + return codes.AsEnumerable(); + } + + private static ScopeConcreteIdArgConditionCopyNonLazyBinder SessionManagerAttacher(ConcreteIdBinderGeneric contract, UnityEngine.Object prefab) + { + return contract.To().FromNewComponentOnRoot(); + } + + private static ScopeConcreteIdArgConditionCopyNonLazyBinder EntitlementCheckerAttacher(ConcreteIdBinderGeneric contract, UnityEngine.Object prefab) + { + return contract.To().FromNewComponentOnRoot(); + } } [HarmonyPatch(typeof(MultiplayerMenuInstaller), nameof(MultiplayerMenuInstaller.InstallBindings))] - class LevelLoaderPatch + internal class LevelLoaderPatch { private static readonly MethodInfo _rootMethod = typeof(DiContainer).GetMethod(nameof(DiContainer.BindInterfacesAndSelfTo), Array.Empty()); @@ -99,9 +147,9 @@ internal static void Prefix(ref GameplayCoreInstaller __instance, ref IConnected var mib = __instance as MonoInstallerBase; var Container = SiraUtil.Accessors.GetDiContainer(ref mib); - ExtendedPlayerManager exPlayerManager = Container.Resolve(); - ExtendedPlayer? exPlayer = exPlayerManager.GetExtendedPlayer(____connectedPlayer); - ExtendedPlayer? hostPlayer = exPlayerManager.GetExtendedPlayer(Container.Resolve().connectionOwner); + ExtendedSessionManager sessionManager = (Container.Resolve() as ExtendedSessionManager)!; + ExtendedPlayer? exPlayer = sessionManager.GetExtendedPlayer(____connectedPlayer); + ExtendedPlayer? hostPlayer = sessionManager.GetExtendedPlayer(sessionManager.connectionOwner); GameplayModifiers? newModifiers; if (____connectedPlayer.HasState("modded") && MPState.FreeModEnabled && exPlayer?.mpexVersion >= _minVersionFreeMod) diff --git a/MultiplayerExtensions/Installers/MPCoreInstaller.cs b/MultiplayerExtensions/Installers/MPCoreInstaller.cs index 065a6c1..cd4216d 100644 --- a/MultiplayerExtensions/Installers/MPCoreInstaller.cs +++ b/MultiplayerExtensions/Installers/MPCoreInstaller.cs @@ -1,6 +1,6 @@ -using MultiplayerExtensions.HarmonyPatches; +using MultiplayerExtensions.Extensions; +using MultiplayerExtensions.HarmonyPatches; using MultiplayerExtensions.Packets; -using MultiplayerExtensions.Sessions; using Zenject; namespace MultiplayerExtensions.Installers @@ -13,11 +13,12 @@ class MPCoreInstaller : MonoInstaller public override void InstallBindings() { Plugin.Log?.Info("Injecting Dependencies"); + Container.BindInterfacesAndSelfTo().AsSingle(); - Container.BindInterfacesAndSelfTo().AsSingle(); - Container.BindInterfacesAndSelfTo().AsSingle(); var _ = Container.Resolve().masterServerEndPoint; - } + + Container.Inject(Container.Resolve() as ExtendedSessionManager); + } public override void Start() { diff --git a/MultiplayerExtensions/Installers/MPGameInstaller.cs b/MultiplayerExtensions/Installers/MPGameInstaller.cs index 621ae2c..4469900 100644 --- a/MultiplayerExtensions/Installers/MPGameInstaller.cs +++ b/MultiplayerExtensions/Installers/MPGameInstaller.cs @@ -1,11 +1,10 @@ using IPA.Utilities; using MultiplayerExtensions.Environments; -using UnityEngine.Playables; using Zenject; namespace MultiplayerExtensions.Installers { - class MPGameInstaller : MonoInstaller + class MPGameInstaller : Installer { public override void InstallBindings() { diff --git a/MultiplayerExtensions/MPState.cs b/MultiplayerExtensions/MPState.cs index f249bb1..d1fc45d 100644 --- a/MultiplayerExtensions/MPState.cs +++ b/MultiplayerExtensions/MPState.cs @@ -50,21 +50,20 @@ internal set } } - private static MultiplayerGameType? _currentGameType = MultiplayerGameType.None; + private static bool _lobbyIsModded; /// - /// The current multiplayer game type. + /// Whether the current lobby is custom (true) or official (false). /// - public static MultiplayerGameType? CurrentGameType - { - get => _currentGameType; + public static bool LobbyIsModded + { + get => _lobbyIsModded; internal set - { - if (_currentGameType == value) + { + if (_lobbyIsModded == value) return; - _currentGameType = value; - Plugin.Log?.Debug($"Updated game type to '{value}'"); - } - } + _lobbyIsModded = value; + } + } private static bool _customSongsEnabled; /// @@ -146,11 +145,4 @@ internal set } } } - - public enum MultiplayerGameType - { - QuickPlay, - Private, - None - } } diff --git a/MultiplayerExtensions/MultiplayerExtensions.csproj b/MultiplayerExtensions/MultiplayerExtensions.csproj index 12a5951..76d83f0 100644 --- a/MultiplayerExtensions/MultiplayerExtensions.csproj +++ b/MultiplayerExtensions/MultiplayerExtensions.csproj @@ -4,7 +4,7 @@ Library Properties MultiplayerExtensions - 0.5.4 + 0.6.0 net472 true portable diff --git a/MultiplayerExtensions/Plugin.cs b/MultiplayerExtensions/Plugin.cs index d6bf18e..542236f 100644 --- a/MultiplayerExtensions/Plugin.cs +++ b/MultiplayerExtensions/Plugin.cs @@ -17,7 +17,6 @@ using MultiplayerExtensions.UI; using BeatSaberMarkupLanguage.Settings; using System.Net.Http; -using MultiplayerExtensions.Sessions; namespace MultiplayerExtensions { diff --git a/MultiplayerExtensions/Sessions/ExtendedPlayerManager.cs b/MultiplayerExtensions/Sessions/ExtendedPlayerManager.cs deleted file mode 100644 index 12704f6..0000000 --- a/MultiplayerExtensions/Sessions/ExtendedPlayerManager.cs +++ /dev/null @@ -1,118 +0,0 @@ -using MultiplayerExtensions.Packets; -using MultiplayerExtensions.Utilities; -using System; -using System.Collections.Generic; -using UnityEngine; -using Zenject; - -namespace MultiplayerExtensions.Sessions -{ - public class ExtendedPlayerManager : IInitializable, IDisposable - { - protected readonly IMultiplayerSessionManager _sessionManager; - protected readonly PacketManager _packetManager; - protected readonly IPlatformUserModel _platformUserModel; - - private Dictionary _players = new Dictionary(); - internal static string? localPlatformID; - internal static Platform localPlatform; - internal static Color localColor; - - public Dictionary players { get => _players; } - public event Action? extendedPlayerConnectedEvent; - - public ExtendedPlayerManager(IMultiplayerSessionManager sessionManager, PacketManager packetManager, IPlatformUserModel platformUserModel) - { - _sessionManager = sessionManager; - _packetManager = packetManager; - _platformUserModel = platformUserModel; - } - - public void Initialize() - { - Plugin.Log?.Info("Setting up PlayerManager"); - - _sessionManager.playerConnectedEvent += OnPlayerConnected; - _sessionManager.playerDisconnectedEvent += OnPlayerDisconnected; - - _packetManager.RegisterCallback(HandlePlayerPacket); - - if (!ColorUtility.TryParseHtmlString(Plugin.Config.Color, out localColor)) - localColor = new Color(0.031f, 0.752f, 1f); - - _platformUserModel.GetUserInfo().ContinueWith(r => - { - localPlatformID = r.Result.platformUserId; - localPlatform = r.Result.platform.ToPlatform(); - - if (Plugin.Config.Statistics) - { - _ = Statistics.AddUser(localPlatformID, (int)localPlatform); - } - }); - } - - public void Dispose() - { - _sessionManager.playerConnectedEvent -= OnPlayerConnected; - _sessionManager.playerDisconnectedEvent -= OnPlayerDisconnected; - _packetManager.UnregisterCallback(); - } - - private void OnPlayerConnected(IConnectedPlayer player) - { - Plugin.Log?.Info($"Player '{player.userId}' joined"); - if (localPlatformID != null) - { - ExtendedPlayerPacket localPlayerPacket = new ExtendedPlayerPacket().Init(localPlatformID, localPlatform, localColor); - _packetManager.Send(localPlayerPacket); - } - } - - private void OnPlayerDisconnected(IConnectedPlayer player) - { - Plugin.Log?.Info($"Player '{player.userId}' disconnected"); - // var extendedPlayer = _players[player.userId]; - _players.Remove(player.userId); - } - - private void HandlePlayerPacket(ExtendedPlayerPacket packet, IConnectedPlayer player) - { - if (_players.ContainsKey(player.userId)) - { - ExtendedPlayer extendedPlayer = _players[player.userId]; - extendedPlayer.platformID = packet.platformID; - extendedPlayer.platform = packet.platform; - extendedPlayer.playerColor = packet.playerColor; - extendedPlayer.mpexVersion = new SemVer.Version(packet.mpexVersion); - } - else - { - Plugin.Log?.Info($"Received 'ExtendedPlayerPacket' from '{player.userId}' with platformID: '{packet.platformID}' mpexVersion: '{packet.mpexVersion}'"); - ExtendedPlayer extendedPlayer = new ExtendedPlayer(player, packet.platformID, packet.platform, new SemVer.Version(packet.mpexVersion), packet.playerColor); - - if (Plugin.PluginMetadata.Version != extendedPlayer.mpexVersion) - { - Plugin.Log?.Warn("###################################################################"); - Plugin.Log?.Warn("Different MultiplayerExtensions version detected!"); - Plugin.Log?.Warn($"The player '{player.userName}' is using MultiplayerExtensions {extendedPlayer.mpexVersion} while you are using MultiplayerExtensions {Plugin.PluginMetadata.Version}"); - Plugin.Log?.Warn("For best compatibility all players should use the same version of MultiplayerExtensions."); - Plugin.Log?.Warn("###################################################################"); - } - - _players[player.userId] = extendedPlayer; - extendedPlayerConnectedEvent?.Invoke(extendedPlayer); - } - } - - public ExtendedPlayer? GetExtendedPlayer(IConnectedPlayer player) - => GetExtendedPlayer(player.userId); - - public ExtendedPlayer? GetExtendedPlayer(string userId) - { - if (_players.TryGetValue(userId, out ExtendedPlayer extendedPlayer)) - return extendedPlayer; - return null; - } - } -} diff --git a/MultiplayerExtensions/Sessions/ExtendedPlayerPacket.cs b/MultiplayerExtensions/Sessions/ExtendedPlayerPacket.cs deleted file mode 100644 index eda53e9..0000000 --- a/MultiplayerExtensions/Sessions/ExtendedPlayerPacket.cs +++ /dev/null @@ -1,56 +0,0 @@ -using LiteNetLib.Utils; -using UnityEngine; - -namespace MultiplayerExtensions.Sessions -{ - public class ExtendedPlayerPacket : INetSerializable, IPoolablePacket - { - public void Release() => ThreadStaticPacketPool.pool.Release(this); - - public void Serialize(NetDataWriter writer) - { - writer.Put(platformID); - writer.Put(mpexVersion); - writer.Put("#" + ColorUtility.ToHtmlStringRGB(playerColor)); - writer.Put((int)platform); - } - - public void Deserialize(NetDataReader reader) - { - this.platformID = reader.GetString(); - this.mpexVersion = reader.GetString(); - - if (!ColorUtility.TryParseHtmlString(reader.GetString(), out playerColor)) - this.playerColor = ExtendedPlayer.DefaultColor; - - //Plugin.Log.Warn($"AvailableBytes: {reader.AvailableBytes}"); - if (reader.AvailableBytes >= 4) // Verify this works when the platform int exists. - this.platform = (Platform)reader.GetInt(); - else - this.platform = Platform.Unknown; - } - - public ExtendedPlayerPacket Init(string platformID, Platform platform, Color playerColor) - { - this.platformID = platformID; - this.mpexVersion = Plugin.PluginMetadata.Version.ToString(); - this.playerColor = playerColor; - this.platform = platform; - return this; - } - - public string platformID = null!; - public Platform platform; - public string mpexVersion = null!; - public Color playerColor; - } - - public enum Platform - { - Unknown = 0, - Steam = 1, - OculusPC = 2, - OculusQuest = 3, - PS4 = 4 - } -} diff --git a/MultiplayerExtensions/Sessions/SessionManager.cs b/MultiplayerExtensions/Sessions/SessionManager.cs deleted file mode 100644 index 43b1157..0000000 --- a/MultiplayerExtensions/Sessions/SessionManager.cs +++ /dev/null @@ -1,66 +0,0 @@ -using MultiplayerExtensions.Utilities; -using System; -using Zenject; - -namespace MultiplayerExtensions.Sessions -{ - public class SessionManager : IInitializable, IDisposable - { - protected readonly IMultiplayerSessionManager _sessionManager; - - internal SessionManager(IMultiplayerSessionManager sessionManager) - { - _sessionManager = sessionManager; - } - - public void Initialize() - { - Plugin.Log?.Info("Setting up SessionManager"); - - MPState.CustomSongsEnabled = Plugin.Config.CustomSongs; - MPState.FreeModEnabled = Plugin.Config.FreeMod; - MPState.HostPickEnabled = Plugin.Config.HostPick; - - _sessionManager.SetLocalPlayerState("modded", true); - _sessionManager.SetLocalPlayerState("customsongs", Plugin.Config.CustomSongs); - _sessionManager.SetLocalPlayerState("freemod", Plugin.Config.FreeMod); - _sessionManager.SetLocalPlayerState("hostpick", Plugin.Config.HostPick); - - _sessionManager.connectedEvent += HandleConnected; - _sessionManager.playerStateChangedEvent += HandlePlayerStateChanged; - } - - public void Dispose() - { - _sessionManager.connectedEvent -= HandleConnected; - _sessionManager.playerStateChangedEvent -= HandlePlayerStateChanged; - } - - private void HandleConnected() - { - MPState.LocalPlayerIsHost = _sessionManager.localPlayer.isConnectionOwner; - if (Plugin.Config.Statistics) - { - _ = Statistics.UseMaster(ExtendedPlayerManager.localPlatformID, (int)ExtendedPlayerManager.localPlatform, MPState.CurrentMasterServer.hostname, MPState.LocalPlayerIsHost); - } - } - - private void HandlePlayerStateChanged(IConnectedPlayer player) - { - if (player.isConnectionOwner) - { - if (MPState.CustomSongsEnabled != player.HasState("customsongs")) - { - MPState.CustomSongsEnabled = player.HasState("customsongs"); - MPEvents.RaiseCustomSongsChanged(this, player.HasState("customsongs")); - } - - if (MPState.FreeModEnabled != player.HasState("freemod")) - { - MPState.FreeModEnabled = player.HasState("freemod"); - MPEvents.RaiseCustomSongsChanged(this, player.HasState("freemod")); - } - } - } - } -} diff --git a/MultiplayerExtensions/UI/LobbySetupPanel.bsml b/MultiplayerExtensions/UI/LobbySetupPanel.bsml index 7ec14b5..0a549f4 100644 --- a/MultiplayerExtensions/UI/LobbySetupPanel.bsml +++ b/MultiplayerExtensions/UI/LobbySetupPanel.bsml @@ -1,7 +1,6 @@ - diff --git a/MultiplayerExtensions/UI/LobbySetupPanel.cs b/MultiplayerExtensions/UI/LobbySetupPanel.cs index 1291c1f..f65604b 100644 --- a/MultiplayerExtensions/UI/LobbySetupPanel.cs +++ b/MultiplayerExtensions/UI/LobbySetupPanel.cs @@ -58,20 +58,6 @@ internal void Inject(IMultiplayerSessionManager sessionManager, LobbySetupViewCo #endregion #region UIValues - [UIValue("CustomSongs")] - public bool CustomSongs - { - get => Plugin.Config.CustomSongs; - set { - Plugin.Config.CustomSongs = value; - if (MPState.CustomSongsEnabled != value) - { - MPState.CustomSongsEnabled = value; - MPEvents.RaiseCustomSongsChanged(this, value); - } - } - } - [UIValue("FreeMod")] public bool FreeMod { @@ -145,15 +131,6 @@ public string DownloadProgress #endregion #region UIActions - [UIAction("SetCustomSongs")] - public void SetCustomSongs(bool value) - { - CustomSongs = value; - customSongsToggle.Value = value; - - UpdateStates(); - } - [UIAction("SetFreeMod")] public void SetFreeMod(bool value) { @@ -226,7 +203,6 @@ private void OnActivate(bool firstActivation, bool addedToHierarchy, bool screen private void UpdateStates() { - sessionManager?.SetLocalPlayerState("customsongs", CustomSongs); sessionManager?.SetLocalPlayerState("freemod", FreeMod); sessionManager?.SetLocalPlayerState("hostpick", HostPick); } diff --git a/MultiplayerExtensions/Utilities/Config.cs b/MultiplayerExtensions/Utilities/Config.cs index 9fbb485..c387053 100644 --- a/MultiplayerExtensions/Utilities/Config.cs +++ b/MultiplayerExtensions/Utilities/Config.cs @@ -7,7 +7,6 @@ public class PluginConfig public virtual bool VerticalHUD { get; set; } = false; public virtual bool SingleplayerHUD { get; set; } = false; public virtual bool Hologram { get; set; } = true; - public virtual bool CustomSongs { get; set; } = true; public virtual bool FreeMod { get; set; } = false; public virtual bool LagReducer { get; set; } = false; public virtual bool MissLighting { get; set; } = true; diff --git a/MultiplayerExtensions/Utilities/Utils.cs b/MultiplayerExtensions/Utilities/Utils.cs index 6445256..885b135 100644 --- a/MultiplayerExtensions/Utilities/Utils.cs +++ b/MultiplayerExtensions/Utilities/Utils.cs @@ -1,4 +1,4 @@ -using MultiplayerExtensions.Sessions; +using MultiplayerExtensions.Extensions; using System; using System.IO; using System.Linq; diff --git a/MultiplayerExtensions/manifest.json b/MultiplayerExtensions/manifest.json index c237fc6..d0000a5 100644 --- a/MultiplayerExtensions/manifest.json +++ b/MultiplayerExtensions/manifest.json @@ -3,9 +3,9 @@ "id": "MultiplayerExtensions", "name": "MultiplayerExtensions", "author": "Zingabopp and Goobwabber", - "version": "0.5.4", + "version": "0.6.0", "description": "Expands the functionality of Beat Saber Multiplayer.", - "gameVersion": "1.16.1", + "gameVersion": "1.16.3", "dependsOn": { "BSIPA": "^4.1.4", "SongCore": "^3.2.0", From 0d5900740197a11fe37c2ac089b51339d4fbd4b6 Mon Sep 17 00:00:00 2001 From: MT Date: Tue, 20 Jul 2021 20:20:51 -0400 Subject: [PATCH 03/41] lobby permission stuff --- .../Environments/LobbyEnvironmentManager.cs | 2 +- .../Extensions/ExtendedGameStateController.cs | 6 ++-- .../Extensions/ExtendedPlayer.cs | 22 ++++++++++++++- .../Extensions/ExtendedPlayersDataModel.cs | 28 ++++++++++++++++--- .../Extensions/ExtendedSessionManager.cs | 24 ++++++++-------- 5 files changed, 63 insertions(+), 19 deletions(-) diff --git a/MultiplayerExtensions/Environments/LobbyEnvironmentManager.cs b/MultiplayerExtensions/Environments/LobbyEnvironmentManager.cs index b0c03d8..7c3416a 100644 --- a/MultiplayerExtensions/Environments/LobbyEnvironmentManager.cs +++ b/MultiplayerExtensions/Environments/LobbyEnvironmentManager.cs @@ -78,7 +78,7 @@ private void HandleLobbyEnvironmentLoaded(object sender, System.EventArgs e) public void SetDefaultPlayerPlaceColors() { SetAllPlayerPlaceColors(Color.black, true); - SetPlayerPlaceColor(_sessionManager.localPlayer, ExtendedSessionManager.localColor, true); + SetPlayerPlaceColor(_sessionManager.localPlayer, ExtendedSessionManager.localExtendedPlayer.playerColor, true); foreach (var player in _sessionManager.connectedPlayers) SetPlayerPlaceColor(player, ExtendedPlayer.DefaultColor, false); diff --git a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs index 9fb51af..52b5fd3 100644 --- a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs +++ b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs @@ -1,6 +1,8 @@ -namespace MultiplayerExtensions.Extensions +using System; + +namespace MultiplayerExtensions.Extensions { - class ExtendedGameStateController : LobbyGameStateController, ILobbyGameStateController + class ExtendedGameStateController : LobbyGameStateController, ILobbyGameStateController, IDisposable { } } diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayer.cs b/MultiplayerExtensions/Extensions/ExtendedPlayer.cs index dd949f2..7460dab 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayer.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayer.cs @@ -12,7 +12,7 @@ public class ExtendedPlayer : IConnectedPlayer /// /// Platform User ID from /// - public string platformID { get; internal set; } + public string platformID { get; internal set; } = null!; /// /// Platform from @@ -31,6 +31,26 @@ public class ExtendedPlayer : IConnectedPlayer internal GameplayModifiers? lastModifiers; + public bool isPartyOwner { get; internal set; } + public bool hasRecommendBeatmapPermission { get; internal set; } + public bool hasRecommendModifiersPermission { get; internal set; } + public bool hasKickVotePermission { get; internal set; } + + public ExtendedPlayer(IConnectedPlayer player) + { + _connectedPlayer = player; + this.mpexVersion = Plugin.PluginMetadata.Version; + } + + public ExtendedPlayer(IConnectedPlayer player, string platformID, Platform platform, Color playerColor) + { + _connectedPlayer = player; + this.platformID = platformID; + this.platform = platform; + this.mpexVersion = Plugin.PluginMetadata.Version; + this.playerColor = playerColor; + } + public ExtendedPlayer(IConnectedPlayer player, string platformID, Platform platform, SemVer.Version mpexVersion, Color playerColor) { _connectedPlayer = player; diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs index 3229b24..7070c0f 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs @@ -36,6 +36,8 @@ internal ExtendedPlayersDataModel(PacketManager packetManager, IMultiplayerSessi _menuRpcManager.recommendGameplayModifiersEvent += HandleMenuRpcManagerRecommendGameplayModifiers; _menuRpcManager.clearRecommendedGameplayModifiersEvent -= base.HandleMenuRpcManagerClearRecommendedGameplayModifiers; _menuRpcManager.clearRecommendedGameplayModifiersEvent += HandleMenuRpcManagerClearRecommendedGameplayModifiers; + _menuRpcManager.setPlayersPermissionConfigurationEvent -= base.HandleMenuRpcManagerSetPlayersPermissionConfiguration; + _menuRpcManager.setPlayersPermissionConfigurationEvent += HandleMenuRpcManagerSetPlayersPermissionConfiguration; } public new void Deactivate() @@ -54,6 +56,8 @@ internal ExtendedPlayersDataModel(PacketManager packetManager, IMultiplayerSessi _menuRpcManager.recommendGameplayModifiersEvent += base.HandleMenuRpcManagerRecommendGameplayModifiers; _menuRpcManager.clearRecommendedGameplayModifiersEvent -= HandleMenuRpcManagerClearRecommendedGameplayModifiers; _menuRpcManager.clearRecommendedGameplayModifiersEvent += base.HandleMenuRpcManagerClearRecommendedGameplayModifiers; + _menuRpcManager.setPlayersPermissionConfigurationEvent -= HandleMenuRpcManagerSetPlayersPermissionConfiguration; + _menuRpcManager.setPlayersPermissionConfigurationEvent += base.HandleMenuRpcManagerSetPlayersPermissionConfiguration; base.Deactivate(); } @@ -213,10 +217,26 @@ public override void HandleMenuRpcManagerClearRecommendedGameplayModifiers(strin } } - /// - /// Used to raise the event. - /// - private void OnSelectedBeatmap(string userId, BeatmapIdentifierNetSerializable? beatmapId) + public override void HandleMenuRpcManagerSetPlayersPermissionConfiguration(string userId, PlayersLobbyPermissionConfigurationNetSerializable playersLobbyPermissionConfiguration) + { + foreach (PlayerLobbyPermissionConfigurationNetSerializable playerLobbyPermissionConfigurationNetSerializable in playersLobbyPermissionConfiguration.playersPermission) + { + ExtendedPlayer? player = _sessionManager.GetExtendedPlayer(userId); + if (player != null) + { + player.isPartyOwner = playerLobbyPermissionConfigurationNetSerializable.isServerOwner; + player.hasRecommendBeatmapPermission = playerLobbyPermissionConfigurationNetSerializable.hasRecommendBeatmapsPermission; + player.hasRecommendModifiersPermission = playerLobbyPermissionConfigurationNetSerializable.hasRecommendGameplayModifiersPermission; + player.hasKickVotePermission = playerLobbyPermissionConfigurationNetSerializable.hasKickVotePermission; + } + this.SetPlayerIsPartyOwner(playerLobbyPermissionConfigurationNetSerializable.userId, playerLobbyPermissionConfigurationNetSerializable.isServerOwner, true); + } + } + + /// + /// Used to raise the event. + /// + private void OnSelectedBeatmap(string userId, BeatmapIdentifierNetSerializable? beatmapId) { SelectedBeatmapEventArgs args; UserType userType = UserType.None; diff --git a/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs b/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs index 64d555b..b92efd6 100644 --- a/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs +++ b/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs @@ -12,11 +12,11 @@ public class ExtendedSessionManager : MultiplayerSessionManager, IMultiplayerSes protected PacketManager _packetManager = null!; protected IPlatformUserModel _platformUserModel = null!; + public IConnectedPlayer partyOwner { get; internal set; } = null!; + private Dictionary _extendedPlayers = new Dictionary(); public Dictionary extendedPlayers { get => _extendedPlayers; } - internal static string? localPlatformID; - internal static Platform localPlatform; - internal static Color localColor; + public static ExtendedPlayer localExtendedPlayer { get; protected set; } = null!; public event Action? extendedPlayerConnectedEvent; @@ -33,6 +33,8 @@ internal void Inject([InjectOptional] PacketManager packetManager, [InjectOption base.StartSession(connectedPlayerManager); + localExtendedPlayer = new ExtendedPlayer(localPlayer); + MPState.FreeModEnabled = Plugin.Config.FreeMod; MPState.HostPickEnabled = Plugin.Config.HostPick; @@ -47,17 +49,17 @@ internal void Inject([InjectOptional] PacketManager packetManager, [InjectOption playerDisconnectedEvent += HandlePlayerDisconnected; _packetManager.RegisterCallback(HandleExtendedPlayerPacket); - if (!ColorUtility.TryParseHtmlString(Plugin.Config.Color, out localColor)) - localColor = new Color(0.031f, 0.752f, 1f); + if (!ColorUtility.TryParseHtmlString(Plugin.Config.Color, out localExtendedPlayer.playerColor)) + localExtendedPlayer.playerColor = new Color(0.031f, 0.752f, 1f); _platformUserModel.GetUserInfo().ContinueWith(r => { - localPlatformID = r.Result.platformUserId; - localPlatform = r.Result.platform.ToPlatform(); + localExtendedPlayer.platformID = r.Result.platformUserId; + localExtendedPlayer.platform = r.Result.platform.ToPlatform(); if (Plugin.Config.Statistics) { - _ = Statistics.AddUser(localPlatformID, (int)localPlatform); + _ = Statistics.AddUser(localExtendedPlayer.platformID, (int)localExtendedPlayer.platform); } }); } @@ -79,16 +81,16 @@ private void HandleConnected() MPState.LocalPlayerIsHost = localPlayer.isConnectionOwner; if (Plugin.Config.Statistics) { - _ = Statistics.UseMaster(localPlatformID, (int)localPlatform, MPState.CurrentMasterServer.hostname, MPState.LocalPlayerIsHost); + _ = Statistics.UseMaster(localExtendedPlayer.platformID, (int)localExtendedPlayer.platform, MPState.CurrentMasterServer.hostname, MPState.LocalPlayerIsHost); } } private void HandlePlayerConnected(IConnectedPlayer player) { Plugin.Log?.Info($"Player '{player.userId}' joined"); - if (localPlatformID != null) + if (localExtendedPlayer.platformID != null) { - ExtendedPlayerPacket localPlayerPacket = new ExtendedPlayerPacket().Init(localPlatformID, localPlatform, localColor); + ExtendedPlayerPacket localPlayerPacket = new ExtendedPlayerPacket().Init(localExtendedPlayer.platformID, localExtendedPlayer.platform, localExtendedPlayer.playerColor); _packetManager.Send(localPlayerPacket); } } From 2276369ee81ad39f91d2257e31a42333f37dd673 Mon Sep 17 00:00:00 2001 From: Goobwabber <47616186+Goobwabber@users.noreply.github.com> Date: Fri, 23 Jul 2021 09:28:11 -0400 Subject: [PATCH 04/41] Update PR_Build.yml --- .github/workflows/PR_Build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/PR_Build.yml b/.github/workflows/PR_Build.yml index fae5746..0333c26 100644 --- a/.github/workflows/PR_Build.yml +++ b/.github/workflows/PR_Build.yml @@ -18,7 +18,7 @@ jobs: dotnet-version: 3.1.101 - name: GetStrippedRefs env: - FILES_URL: ${{ secrets.BSFILES_URL }} + FILES_URL: ${{ secrets.BSFILES_1_16_3_URL }} run: wget --no-check-certificate "$FILES_URL" -q -O bsfiles.zip - name: ExtractRefs run: unzip -q -n bsfiles.zip -d ./Refs From c32a83c55de9d607eade100ca09609bbded3f6cc Mon Sep 17 00:00:00 2001 From: MT Date: Fri, 23 Jul 2021 15:14:43 -0400 Subject: [PATCH 05/41] IMAGINE WORKING MULTI POGGU --- .../Beatmaps/PreviewBeatmapStub.cs | 3 +- .../Extensions/ExtendedEntitlementChecker.cs | 37 ++++- .../Extensions/ExtendedGameStateController.cs | 148 +++++++++++++++++- .../Extensions/ExtendedPlayerTableCell.cs | 16 +- .../Extensions/ExtendedPlayersDataModel.cs | 87 ++++++---- .../Extensions/ExtendedSessionManager.cs | 11 -- .../HarmonyPatches/CustomSongsPatches.cs | 28 +++- .../HarmonyPatches/InstallerPatches.cs | 2 +- .../HarmonyPatches/MaxPlayerPatches.cs | 4 +- .../Installers/MPCoreInstaller.cs | 1 + .../Installers/MPMenuInstaller.cs | 2 +- MultiplayerExtensions/MPState.cs | 16 ++ MultiplayerExtensions/Plugin.cs | 4 +- MultiplayerExtensions/UI/LobbySetupPanel.cs | 2 - .../Harmony}/HarmonyManager.cs | 16 +- .../Harmony}/HarmonyPatchInfo.cs | 4 +- .../Utilities/{ => Version}/VersionCheck.cs | 0 .../Utilities/{ => Version}/VersionInfo.cs | 2 +- 18 files changed, 301 insertions(+), 82 deletions(-) rename MultiplayerExtensions/{HarmonyPatches => Utilities/Harmony}/HarmonyManager.cs (96%) rename MultiplayerExtensions/{HarmonyPatches => Utilities/Harmony}/HarmonyPatchInfo.cs (97%) rename MultiplayerExtensions/Utilities/{ => Version}/VersionCheck.cs (100%) rename MultiplayerExtensions/Utilities/{ => Version}/VersionInfo.cs (96%) diff --git a/MultiplayerExtensions/Beatmaps/PreviewBeatmapStub.cs b/MultiplayerExtensions/Beatmaps/PreviewBeatmapStub.cs index 97daa33..0e380bf 100644 --- a/MultiplayerExtensions/Beatmaps/PreviewBeatmapStub.cs +++ b/MultiplayerExtensions/Beatmaps/PreviewBeatmapStub.cs @@ -121,10 +121,9 @@ public async Task GetCoverImageAsync(CancellationToken cancellationToken { Plugin.Log?.Warn($"Failed to fetch beatmap cover: {ex.Message}"); } - } - return Sprite.Create(Texture2D.blackTexture, new Rect(0, 0, 2, 2), new Vector2(0, 0), 100.0f); + return null!; } public Task? GetPreviewAudioClipAsync(CancellationToken cancellationToken) => _preview?.GetPreviewAudioClipAsync(cancellationToken); diff --git a/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs b/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs index 2f5d762..810fc86 100644 --- a/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs +++ b/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs @@ -1,4 +1,5 @@ using BeatSaverSharp; +using System; using System.Collections.Generic; using System.Threading.Tasks; using Zenject; @@ -12,6 +13,8 @@ public class ExtendedEntitlementChecker : NetworkPlayerEntitlementChecker protected Dictionary> _entitlementsDictionary = new Dictionary>(); protected Dictionary>> _tcsDictionary = new Dictionary>>(); + public event Action? receivedEntitlementEvent; + [Inject] internal void Inject(IMultiplayerSessionManager multiplayerSessionManager) { @@ -41,23 +44,30 @@ public override void OnDestroy() base.OnDestroy(); } - public override void HandleGetIsEntitledToLevel(string userId, string levelId) + public override async void HandleGetIsEntitledToLevel(string userId, string levelId) { - base.HandleGetIsEntitledToLevel(userId, levelId); + EntitlementsStatus entitlementStatus = await this.GetEntitlementStatus(levelId); + this._rpcManager.SetIsEntitledToLevel(levelId, entitlementStatus); } public void HandleSetIsEntitledToLevel(string userId, string levelId, EntitlementsStatus entitlement) { + Plugin.Log?.Info($"Entitlement from '{userId}' for '{levelId}' is {entitlement.ToString()}"); + + if (!_entitlementsDictionary.ContainsKey(userId)) + _entitlementsDictionary[userId] = new Dictionary(); _entitlementsDictionary[userId][levelId] = entitlement; - if (_tcsDictionary.TryGetValue(userId, out Dictionary> userDictionary)) - if (userDictionary.TryGetValue(levelId, out TaskCompletionSource entitlementTcs)) + if (_tcsDictionary.TryGetValue(userId, out Dictionary> userTcsDictionary)) + if (userTcsDictionary.TryGetValue(levelId, out TaskCompletionSource entitlementTcs) && !entitlementTcs.Task.IsCompleted) entitlementTcs.SetResult(entitlement); + + receivedEntitlementEvent?.Invoke(userId, levelId, entitlement); } public override Task GetEntitlementStatus(string levelId) { - Plugin.Log?.Debug($"Checking level entitlement for '{levelId}'"); + Plugin.Log?.Info($"Checking level entitlement for '{levelId}'"); string? hash = Utilities.Utils.LevelIdToHash(levelId); if (hash == null) @@ -76,6 +86,9 @@ public override Task GetEntitlementStatus(string levelId) public Task GetUserEntitlementStatus(string userId, string levelId) { + if (Utilities.Utils.LevelIdToHash(levelId) != null && !_sessionManager.GetPlayerByUserId(userId).HasState("modded")) + return Task.FromResult(EntitlementsStatus.NotOwned); + if (userId == _sessionManager.localPlayer.userId) return GetEntitlementStatus(levelId); @@ -83,9 +96,23 @@ public Task GetUserEntitlementStatus(string userId, string l if (userDictionary.TryGetValue(levelId, out EntitlementsStatus entitlement)) return Task.FromResult(entitlement); + if (!_tcsDictionary.ContainsKey(userId)) + _tcsDictionary[userId] = new Dictionary>(); _tcsDictionary[userId][levelId] = new TaskCompletionSource(); _rpcManager.GetIsEntitledToLevel(levelId); return _tcsDictionary[userId][levelId].Task; } + + public Task GetUserEntitlementStatusWithoutRequest(string userId, string levelId) + { + if (userId == _sessionManager.localPlayer.userId) + return GetEntitlementStatus(levelId); + + if (_entitlementsDictionary.TryGetValue(userId, out Dictionary userDictionary)) + if (userDictionary.TryGetValue(levelId, out EntitlementsStatus entitlement)) + return Task.FromResult(entitlement); + + return Task.FromResult(EntitlementsStatus.NotDownloaded); + } } } diff --git a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs index 52b5fd3..bc66572 100644 --- a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs +++ b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs @@ -1,8 +1,150 @@ using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; namespace MultiplayerExtensions.Extensions { - class ExtendedGameStateController : LobbyGameStateController, ILobbyGameStateController, IDisposable - { - } + class ExtendedGameStateController : LobbyGameStateController, ILobbyGameStateController, IDisposable + { + protected readonly ExtendedSessionManager _sessionManager; + protected readonly ExtendedEntitlementChecker _entitlementChecker; + + private static readonly SemVer.Version _minVersionStart = new SemVer.Version("0.6.0"); + + internal ExtendedGameStateController(IMultiplayerSessionManager sessionManager, NetworkPlayerEntitlementChecker entitlementChecker) + { + _sessionManager = (sessionManager as ExtendedSessionManager)!; + _entitlementChecker = (entitlementChecker as ExtendedEntitlementChecker)!; + } + + public override void Activate() + { + this._lobbyGameStateModel.gameStateDidChangeEvent += this.HandleGameStateChanged; + this._entitlementChecker.receivedEntitlementEvent += this.HandleEntitlement; + base.Activate(); + + (this as ILobbyGameStateController).lobbyStateChangedEvent += this.HandleLobbyStateChanged; + } + + public override void Deactivate() + { + this._lobbyGameStateModel.gameStateDidChangeEvent -= this.HandleGameStateChanged; + this._entitlementChecker.receivedEntitlementEvent -= this.HandleEntitlement; + + this._menuRpcManager.startedLevelEvent -= this.HandleMenuRpcManagerStartedLevel; + this._menuRpcManager.startedLevelEvent += base.HandleMenuRpcManagerStartedLevel; + base.Deactivate(); + + (this as ILobbyGameStateController).lobbyStateChangedEvent -= this.HandleLobbyStateChanged; + } + + public override void Dispose() + { + this.Deactivate(); + } + + + + private void HandleGameStateChanged(MultiplayerGameState newGameState) + { + MPState.CurrentGameState = newGameState; + } + + private void HandleLobbyStateChanged(MultiplayerLobbyState newLobbyState) + { + MPState.CurrentLobbyState = newLobbyState; + } + + + + public override void StartListeningToGameStart() + { + base.StartListeningToGameStart(); + this._menuRpcManager.startedLevelEvent -= base.HandleMenuRpcManagerStartedLevel; + this._menuRpcManager.startedLevelEvent += this.HandleMenuRpcManagerStartedLevel; + } + + public override void StopListeningToGameStart() + { + this._menuRpcManager.startedLevelEvent -= this.HandleMenuRpcManagerStartedLevel; + this._menuRpcManager.startedLevelEvent += base.HandleMenuRpcManagerStartedLevel; + base.StopListeningToGameStart(); + } + + + + private IPreviewBeatmapLevel? _previewBeatmapLevel; + private BeatmapDifficulty _beatmapDifficulty; + private BeatmapCharacteristicSO? _beatmapCharacteristic; + private IDifficultyBeatmap? _difficultyBeatmap; + private GameplayModifiers? _gameplayModifiers; + + public override void HandleMenuRpcManagerStartedLevel(string userId, BeatmapIdentifierNetSerializable beatmapId, GameplayModifiers gameplayModifiers, float startTime) + { + if (_sessionManager.partyOwner != null) + { + ILobbyPlayerData partyOwnerData = _lobbyPlayersDataModel.GetLobbyPlayerDataModel(_sessionManager.partyOwner.userId); + beatmapId = new BeatmapIdentifierNetSerializable(partyOwnerData.beatmapLevel.levelID, partyOwnerData.beatmapCharacteristic.serializedName, partyOwnerData.beatmapDifficulty); + + if (_sessionManager.partyOwner.HasState("freemod")) + gameplayModifiers = _lobbyPlayersDataModel.GetPlayerGameplayModifiers(_lobbyPlayersDataModel.localUserId); + } + + base.HandleMenuRpcManagerStartedLevel(userId, beatmapId, gameplayModifiers, startTime); + _multiplayerLevelLoader.countdownFinishedEvent -= base.HandleMultiplayerLevelLoaderCountdownFinished; + _multiplayerLevelLoader.countdownFinishedEvent += this.HandleMultiplayerLevelLoaderCountdownFinished; + } + + public override void StopLoading() + { + _multiplayerLevelLoader.countdownFinishedEvent += base.HandleMultiplayerLevelLoaderCountdownFinished; + _multiplayerLevelLoader.countdownFinishedEvent -= this.HandleMultiplayerLevelLoaderCountdownFinished; + base.StopLoading(); + } + + public override void HandleMultiplayerLevelLoaderCountdownFinished(IPreviewBeatmapLevel previewBeatmapLevel, BeatmapDifficulty beatmapDifficulty, BeatmapCharacteristicSO beatmapCharacteristic, IDifficultyBeatmap difficultyBeatmap, GameplayModifiers gameplayModifiers) + { + Plugin.Log?.Debug("Map finished loading, waiting for other players..."); + + this._previewBeatmapLevel = previewBeatmapLevel; + this._beatmapDifficulty = beatmapDifficulty; + this._beatmapCharacteristic = beatmapCharacteristic; + this._difficultyBeatmap = difficultyBeatmap; + this._gameplayModifiers = gameplayModifiers; + + _menuRpcManager.SetIsEntitledToLevel(previewBeatmapLevel.levelID, EntitlementsStatus.Ok); + HandleEntitlement(_lobbyPlayersDataModel.localUserId, startedBeatmapId.levelID, EntitlementsStatus.Ok); + } + + + + private async Task IsPlayerReady(IConnectedPlayer player) + { + if (!player.HasState("modded")) return true; // player is not modded: always assume ready + if (await _entitlementChecker.GetUserEntitlementStatusWithoutRequest(player.userId, startedBeatmapId.levelID) == EntitlementsStatus.Ok) return true; + + ExtendedPlayer? extendedPlayer = _sessionManager.GetExtendedPlayer(player); + + // did not recieve mpexVersion from player or the version is too old: assume the player is ready + if (extendedPlayer == null) return true; + if (extendedPlayer.mpexVersion == null || extendedPlayer.mpexVersion < _minVersionStart) return true; + + return false; + } + + private async void HandleEntitlement(string userId, string levelId, EntitlementsStatus entitlement) + { + if (state == MultiplayerLobbyState.GameStarting) + { + IEnumerable> readyTasks = _sessionManager.connectedPlayers.Select(IsPlayerReady); + bool[] readyStates = await Task.WhenAll(readyTasks); + if (readyStates.All(x => x) && await _entitlementChecker.GetEntitlementStatus(startedBeatmapId.levelID) == EntitlementsStatus.Ok) + { + Plugin.Log.Debug("All players ready, starting game."); + base.HandleMultiplayerLevelLoaderCountdownFinished(_previewBeatmapLevel, _beatmapDifficulty, _beatmapCharacteristic, _difficultyBeatmap, _gameplayModifiers); + } + } + } + } } diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayerTableCell.cs b/MultiplayerExtensions/Extensions/ExtendedPlayerTableCell.cs index 0dffce6..9e4c3db 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayerTableCell.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayerTableCell.cs @@ -8,11 +8,11 @@ using UnityEngine.UI; using Zenject; -namespace MultiplayerExtensions.OverrideClasses +namespace MultiplayerExtensions.Extensions { class ExtendedPlayerTableCell : GameServerPlayerTableCell { - protected NetworkPlayerEntitlementChecker _entitlementChecker = null!; + protected ExtendedEntitlementChecker _entitlementChecker = null!; protected ILobbyPlayersDataModel _playersDataModel = null!; protected IMenuRpcManager _menuRpcManager = null!; @@ -30,7 +30,7 @@ class ExtendedPlayerTableCell : GameServerPlayerTableCell [Inject] internal void Inject(NetworkPlayerEntitlementChecker entitlementChecker, ILobbyPlayersDataModel playersDataModel, IMenuRpcManager menuRpcManager) { - _entitlementChecker = entitlementChecker; + _entitlementChecker = (entitlementChecker as ExtendedEntitlementChecker)!; _playersDataModel = playersDataModel; _menuRpcManager = menuRpcManager; } @@ -75,6 +75,7 @@ public override void SetData(IConnectedPlayer connectedPlayer, ILobbyPlayerData if (getLevelEntitlementTask != null) getLevelEntitlementTask = getLevelEntitlementTask.ContinueWith(r => AdditionalContentModel.EntitlementStatus.Owned); base.SetData(connectedPlayer, playerData, hasKickPermissions, allowSelection, getLevelEntitlementTask); + _localPlayerBackgroundImage.enabled = true; GetLevelEntitlement(connectedPlayer); lastPlayer = connectedPlayer; } @@ -91,13 +92,8 @@ private async void GetLevelEntitlement(IConnectedPlayer player) lastLevelId = levelId; - bool needsRpc = false; - Task entitlement = player.isMe ? - _entitlementChecker.GetEntitlementStatus(levelId) : - Task.FromResult(EntitlementsStatus.Ok); - if (needsRpc) - _menuRpcManager.GetIsEntitledToLevel(levelId); - SetLevelEntitlement(player, await entitlement); + EntitlementsStatus entitlement = await _entitlementChecker.GetUserEntitlementStatus(player.userId, levelId); + SetLevelEntitlement(player, entitlement); } private void SetLevelEntitlement(IConnectedPlayer player, EntitlementsStatus status) diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs index 7070c0f..ad0e7c0 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs @@ -1,8 +1,8 @@ using BeatSaverSharp; using MultiplayerExtensions.Beatmaps; using MultiplayerExtensions.Packets; -using MultiplayerExtensions.Extensions; using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -13,50 +13,52 @@ class ExtendedPlayersDataModel : LobbyPlayersDataModel, ILobbyPlayersDataModel, protected readonly PacketManager _packetManager; protected readonly ExtendedSessionManager _sessionManager; + private static readonly string PlaceholderSongID = "100Bills"; + internal ExtendedPlayersDataModel(PacketManager packetManager, IMultiplayerSessionManager sessionManager) { _packetManager = packetManager; _sessionManager = (sessionManager as ExtendedSessionManager)!; } - public new void Activate() + public override void Activate() { - MPEvents.CustomSongsChanged += HandleCustomSongsChanged; - MPEvents.FreeModChanged += HandleFreeModChanged; - _packetManager.RegisterCallback(HandlePreviewBeatmapPacket); + MPEvents.CustomSongsChanged += this.HandleCustomSongsChanged; + MPEvents.FreeModChanged += this.HandleFreeModChanged; + this._packetManager.RegisterCallback(this.HandlePreviewBeatmapPacket); base.Activate(); _menuRpcManager.recommendBeatmapEvent -= base.HandleMenuRpcManagerRecommendBeatmap; - _menuRpcManager.recommendBeatmapEvent += HandleMenuRpcManagerRecommendBeatmap; + _menuRpcManager.recommendBeatmapEvent += this.HandleMenuRpcManagerRecommendBeatmap; _menuRpcManager.getRecommendedBeatmapEvent -= base.HandleMenuRpcManagerGetRecommendedBeatmap; - _menuRpcManager.getRecommendedBeatmapEvent += HandleMenuRpcManagerGetRecommendedBeatmap; + _menuRpcManager.getRecommendedBeatmapEvent += this.HandleMenuRpcManagerGetRecommendedBeatmap; _menuRpcManager.clearRecommendedBeatmapEvent -= base.HandleMenuRpcManagerClearBeatmap; - _menuRpcManager.clearRecommendedBeatmapEvent += HandleMenuRpcManagerClearBeatmap; + _menuRpcManager.clearRecommendedBeatmapEvent += this.HandleMenuRpcManagerClearBeatmap; _menuRpcManager.recommendGameplayModifiersEvent -= base.HandleMenuRpcManagerRecommendGameplayModifiers; - _menuRpcManager.recommendGameplayModifiersEvent += HandleMenuRpcManagerRecommendGameplayModifiers; + _menuRpcManager.recommendGameplayModifiersEvent += this.HandleMenuRpcManagerRecommendGameplayModifiers; _menuRpcManager.clearRecommendedGameplayModifiersEvent -= base.HandleMenuRpcManagerClearRecommendedGameplayModifiers; - _menuRpcManager.clearRecommendedGameplayModifiersEvent += HandleMenuRpcManagerClearRecommendedGameplayModifiers; + _menuRpcManager.clearRecommendedGameplayModifiersEvent += this.HandleMenuRpcManagerClearRecommendedGameplayModifiers; _menuRpcManager.setPlayersPermissionConfigurationEvent -= base.HandleMenuRpcManagerSetPlayersPermissionConfiguration; - _menuRpcManager.setPlayersPermissionConfigurationEvent += HandleMenuRpcManagerSetPlayersPermissionConfiguration; + _menuRpcManager.setPlayersPermissionConfigurationEvent += this.HandleMenuRpcManagerSetPlayersPermissionConfiguration; } - public new void Deactivate() + public override void Deactivate() { MPEvents.CustomSongsChanged -= HandleCustomSongsChanged; MPEvents.FreeModChanged -= HandleFreeModChanged; - _packetManager.UnregisterCallback(); + this._packetManager.UnregisterCallback(); - _menuRpcManager.recommendBeatmapEvent -= HandleMenuRpcManagerRecommendBeatmap; + _menuRpcManager.recommendBeatmapEvent -= this.HandleMenuRpcManagerRecommendBeatmap; _menuRpcManager.recommendBeatmapEvent += base.HandleMenuRpcManagerRecommendBeatmap; - _menuRpcManager.getRecommendedBeatmapEvent -= HandleMenuRpcManagerGetRecommendedBeatmap; + _menuRpcManager.getRecommendedBeatmapEvent -= this.HandleMenuRpcManagerGetRecommendedBeatmap; _menuRpcManager.getRecommendedBeatmapEvent += base.HandleMenuRpcManagerGetRecommendedBeatmap; - _menuRpcManager.clearRecommendedBeatmapEvent -= HandleMenuRpcManagerClearBeatmap; + _menuRpcManager.clearRecommendedBeatmapEvent -= this.HandleMenuRpcManagerClearBeatmap; _menuRpcManager.clearRecommendedBeatmapEvent += base.HandleMenuRpcManagerClearBeatmap; - _menuRpcManager.recommendGameplayModifiersEvent -= HandleMenuRpcManagerRecommendGameplayModifiers; + _menuRpcManager.recommendGameplayModifiersEvent -= this.HandleMenuRpcManagerRecommendGameplayModifiers; _menuRpcManager.recommendGameplayModifiersEvent += base.HandleMenuRpcManagerRecommendGameplayModifiers; - _menuRpcManager.clearRecommendedGameplayModifiersEvent -= HandleMenuRpcManagerClearRecommendedGameplayModifiers; + _menuRpcManager.clearRecommendedGameplayModifiersEvent -= this.HandleMenuRpcManagerClearRecommendedGameplayModifiers; _menuRpcManager.clearRecommendedGameplayModifiersEvent += base.HandleMenuRpcManagerClearRecommendedGameplayModifiers; - _menuRpcManager.setPlayersPermissionConfigurationEvent -= HandleMenuRpcManagerSetPlayersPermissionConfiguration; + _menuRpcManager.setPlayersPermissionConfigurationEvent -= this.HandleMenuRpcManagerSetPlayersPermissionConfiguration; _menuRpcManager.setPlayersPermissionConfigurationEvent += base.HandleMenuRpcManagerSetPlayersPermissionConfiguration; base.Deactivate(); @@ -64,7 +66,24 @@ internal ExtendedPlayersDataModel(PacketManager packetManager, IMultiplayerSessi public new void Dispose() { - Deactivate(); + this.Deactivate(); + } + + public override void SetLocalPlayerIsReady(bool isReady, bool notifyChange) + { + if (!Plugin.Config.HostPick && this.localUserId == this.partyOwnerId) + { + ILobbyPlayerData localPlayerDataModel = this.GetLobbyPlayerDataModel(localUserId); + IEnumerable validDataModels = this.playersData.Values.Where(data => data.beatmapLevel != null); + ILobbyPlayerData chosenPlayerDataModel = validDataModels.ElementAt(new Random().Next(0, validDataModels.Count())); + localPlayerDataModel.beatmapLevel = chosenPlayerDataModel.beatmapLevel; + localPlayerDataModel.beatmapDifficulty = chosenPlayerDataModel.beatmapDifficulty; + localPlayerDataModel.beatmapCharacteristic = chosenPlayerDataModel.beatmapCharacteristic; + localPlayerDataModel.gameplayModifiers = chosenPlayerDataModel.gameplayModifiers; + this._menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(chosenPlayerDataModel.beatmapLevel.levelID, chosenPlayerDataModel.beatmapCharacteristic.serializedName, chosenPlayerDataModel.beatmapDifficulty)); + this._menuRpcManager.RecommendGameplayModifiers(chosenPlayerDataModel.gameplayModifiers); + this.NotifyModelChange(this.localUserId); + } } private void HandleCustomSongsChanged(object sender, bool value) @@ -118,11 +137,18 @@ public override void HandleMenuRpcManagerClearBeatmap(string userId) public override void HandleMenuRpcManagerGetRecommendedBeatmap(string userId) { ILobbyPlayerData lobbyPlayerDataModel = this.GetLobbyPlayerDataModel(this.localUserId); - IConnectedPlayer user = _multiplayerSessionManager.GetPlayerByUserId(userId); - if (lobbyPlayerDataModel != null && user != null && user.HasState("modded") && lobbyPlayerDataModel?.beatmapLevel != null && lobbyPlayerDataModel?.beatmapLevel is PreviewBeatmapStub preview) - _packetManager.Send(new PreviewBeatmapPacket(preview, lobbyPlayerDataModel.beatmapCharacteristic.serializedName, lobbyPlayerDataModel.beatmapDifficulty)); - else if (lobbyPlayerDataModel != null && lobbyPlayerDataModel.beatmapLevel != null) - this._menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(lobbyPlayerDataModel.beatmapLevel.levelID, lobbyPlayerDataModel.beatmapCharacteristic.serializedName, lobbyPlayerDataModel.beatmapDifficulty)); + if (lobbyPlayerDataModel != null && lobbyPlayerDataModel.beatmapLevel != null) + { + if (lobbyPlayerDataModel.beatmapLevel is PreviewBeatmapStub preview) + _packetManager.Send(new PreviewBeatmapPacket(preview, lobbyPlayerDataModel.beatmapCharacteristic.serializedName, lobbyPlayerDataModel.beatmapDifficulty)); + else + { + if (_sessionManager.connectionOwner.HasState("modded")) + this._menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(lobbyPlayerDataModel.beatmapLevel.levelID, lobbyPlayerDataModel.beatmapCharacteristic.serializedName, lobbyPlayerDataModel.beatmapDifficulty)); + else + this._menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(PlaceholderSongID, lobbyPlayerDataModel.beatmapCharacteristic.serializedName, lobbyPlayerDataModel.beatmapDifficulty)); + } + } } /// @@ -132,9 +158,9 @@ public async override void HandleMenuRpcManagerRecommendBeatmap(string userId, B { OnSelectedBeatmap(userId, beatmapId); string? hash = Utilities.Utils.LevelIdToHash(beatmapId.levelID); - Plugin.Log?.Debug($"'{userId}' selected song '{hash ?? beatmapId.levelID}'."); if (hash != null) { + Plugin.Log?.Debug($"'{userId}' selected song '{hash ?? beatmapId.levelID}'."); BeatmapCharacteristicSO characteristic = _beatmapCharacteristicCollection.GetBeatmapCharacteristicBySerializedName(beatmapId.beatmapCharacteristicSerializedName); if (_playersData.Values.Any(playerData => playerData.beatmapLevel?.levelID == beatmapId.levelID)) { @@ -182,8 +208,8 @@ public async override void HandleMenuRpcManagerRecommendBeatmap(string userId, B HMMainThreadDispatcher.instance.Enqueue(() => base.SetPlayerBeatmapLevel(base.localUserId, preview, beatmapDifficulty, characteristic)); _packetManager.Send(new PreviewBeatmapPacket(preview!, characteristic.serializedName, beatmapDifficulty)); - if (!_multiplayerSessionManager.connectedPlayers.All(x => x.HasState("modded"))) - _menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(levelId, characteristic.serializedName, beatmapDifficulty)); + if (!_sessionManager.connectionOwner.HasState("modded")) + _menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(PlaceholderSongID, characteristic.serializedName, beatmapDifficulty)); } }else base.SetLocalPlayerBeatmapLevel(levelId, beatmapDifficulty, characteristic); @@ -221,7 +247,7 @@ public override void HandleMenuRpcManagerSetPlayersPermissionConfiguration(strin { foreach (PlayerLobbyPermissionConfigurationNetSerializable playerLobbyPermissionConfigurationNetSerializable in playersLobbyPermissionConfiguration.playersPermission) { - ExtendedPlayer? player = _sessionManager.GetExtendedPlayer(userId); + ExtendedPlayer? player = _sessionManager.GetExtendedPlayer(playerLobbyPermissionConfigurationNetSerializable.userId); if (player != null) { player.isPartyOwner = playerLobbyPermissionConfigurationNetSerializable.isServerOwner; @@ -231,6 +257,9 @@ public override void HandleMenuRpcManagerSetPlayersPermissionConfiguration(strin } this.SetPlayerIsPartyOwner(playerLobbyPermissionConfigurationNetSerializable.userId, playerLobbyPermissionConfigurationNetSerializable.isServerOwner, true); } + + MPState.LocalPlayerIsHost = localUserId == partyOwnerId; + _sessionManager.partyOwner = _sessionManager.GetPlayerByUserId(partyOwnerId); } /// diff --git a/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs b/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs index b92efd6..4075847 100644 --- a/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs +++ b/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs @@ -42,7 +42,6 @@ internal void Inject([InjectOptional] PacketManager packetManager, [InjectOption SetLocalPlayerState("freemod", Plugin.Config.FreeMod); SetLocalPlayerState("hostpick", Plugin.Config.HostPick); - connectedEvent += HandleConnected; playerStateChangedEvent += HandlePlayerStateChanged; playerConnectedEvent += HandlePlayerConnected; @@ -66,7 +65,6 @@ internal void Inject([InjectOptional] PacketManager packetManager, [InjectOption public new void EndSession() { - connectedEvent -= HandleConnected; playerStateChangedEvent -= HandlePlayerStateChanged; playerConnectedEvent -= HandlePlayerConnected; @@ -76,15 +74,6 @@ internal void Inject([InjectOptional] PacketManager packetManager, [InjectOption base.EndSession(); } - private void HandleConnected() - { - MPState.LocalPlayerIsHost = localPlayer.isConnectionOwner; - if (Plugin.Config.Statistics) - { - _ = Statistics.UseMaster(localExtendedPlayer.platformID, (int)localExtendedPlayer.platform, MPState.CurrentMasterServer.hostname, MPState.LocalPlayerIsHost); - } - } - private void HandlePlayerConnected(IConnectedPlayer player) { Plugin.Log?.Info($"Player '{player.userId}' joined"); diff --git a/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs b/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs index e3782a1..95e5f85 100644 --- a/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs @@ -9,19 +9,43 @@ /// namespace MultiplayerExtensions.HarmonyPatches { + [HarmonyPatch(typeof(MultiplayerLobbyConnectionController), nameof(MultiplayerLobbyConnectionController.CreateParty), MethodType.Normal)] + internal class CreatePartyPatch + { + /// + /// Modifies the data used to create a party game + /// + static void Prefix(CreateServerFormData data) + { + data.songPacks = SongPackMask.all | new SongPackMask("custom_levelpack_CustomLevels"); + } + } + [HarmonyPatch(typeof(MultiplayerLevelSelectionFlowCoordinator), "enableCustomLevels", MethodType.Getter)] internal class EnableCustomLevelsPatch { /// /// Overrides getter for /// - static bool Prefix(ref bool __result) + static bool Prefix(ref bool __result, SongPackMask ____songPackMask) { - __result = MPState.CustomSongsEnabled; + __result = ____songPackMask.Contains(new SongPackMask("custom_levelpack_CustomLevels")); return false; } } + [HarmonyPatch(typeof(GameServerLobbyFlowCoordinator), "DidActivate", MethodType.Normal)] + internal class GameServerDidActivatePatch + { + /// + /// Does stuff as soon as the lobby is loaded. + /// + static void Postfix(IUnifiedNetworkPlayerModel ____unifiedNetworkPlayerModel) + { + MPState.CustomSongsEnabled = ____unifiedNetworkPlayerModel.selectionMask.songPacks.Contains(new SongPackMask("custom_levelpack_CustomLevels")); + } + } + [HarmonyPatch(typeof(LobbySetupViewController), nameof(LobbySetupViewController.SetPlayersMissingLevelText), MethodType.Normal)] internal class MissingLevelStartPatch { diff --git a/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs b/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs index 094224f..9f4258c 100644 --- a/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs @@ -149,7 +149,7 @@ internal static void Prefix(ref GameplayCoreInstaller __instance, ref IConnected ExtendedSessionManager sessionManager = (Container.Resolve() as ExtendedSessionManager)!; ExtendedPlayer? exPlayer = sessionManager.GetExtendedPlayer(____connectedPlayer); - ExtendedPlayer? hostPlayer = sessionManager.GetExtendedPlayer(sessionManager.connectionOwner); + ExtendedPlayer? hostPlayer = sessionManager.GetExtendedPlayer(sessionManager.partyOwner); GameplayModifiers? newModifiers; if (____connectedPlayer.HasState("modded") && MPState.FreeModEnabled && exPlayer?.mpexVersion >= _minVersionFreeMod) diff --git a/MultiplayerExtensions/HarmonyPatches/MaxPlayerPatches.cs b/MultiplayerExtensions/HarmonyPatches/MaxPlayerPatches.cs index 4498888..d74cbc5 100644 --- a/MultiplayerExtensions/HarmonyPatches/MaxPlayerPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/MaxPlayerPatches.cs @@ -78,9 +78,11 @@ internal static IEnumerable Transpiler(IEnumerable (float)x).ToArray(); ____maxPlayersList.values = playerValues; } diff --git a/MultiplayerExtensions/Installers/MPCoreInstaller.cs b/MultiplayerExtensions/Installers/MPCoreInstaller.cs index cd4216d..6008696 100644 --- a/MultiplayerExtensions/Installers/MPCoreInstaller.cs +++ b/MultiplayerExtensions/Installers/MPCoreInstaller.cs @@ -1,6 +1,7 @@ using MultiplayerExtensions.Extensions; using MultiplayerExtensions.HarmonyPatches; using MultiplayerExtensions.Packets; +using MultiplayerExtensions.Utilities; using Zenject; namespace MultiplayerExtensions.Installers diff --git a/MultiplayerExtensions/Installers/MPMenuInstaller.cs b/MultiplayerExtensions/Installers/MPMenuInstaller.cs index d1b54fc..27a9349 100644 --- a/MultiplayerExtensions/Installers/MPMenuInstaller.cs +++ b/MultiplayerExtensions/Installers/MPMenuInstaller.cs @@ -1,6 +1,6 @@ using IPA.Utilities; using MultiplayerExtensions.Environments; -using MultiplayerExtensions.OverrideClasses; +using MultiplayerExtensions.Extensions; using MultiplayerExtensions.UI; using UnityEngine; using Zenject; diff --git a/MultiplayerExtensions/MPState.cs b/MultiplayerExtensions/MPState.cs index d1fc45d..655cc15 100644 --- a/MultiplayerExtensions/MPState.cs +++ b/MultiplayerExtensions/MPState.cs @@ -50,6 +50,22 @@ internal set } } + private static MultiplayerLobbyState? _currentLobbyState = MultiplayerLobbyState.None; + /// + /// The current multiplayer game state. + /// + public static MultiplayerLobbyState? CurrentLobbyState + { + get => _currentLobbyState; + internal set + { + if (_currentLobbyState == value) + return; + _currentLobbyState = value; + Plugin.Log?.Debug($"Updated game state to '{value}'"); + } + } + private static bool _lobbyIsModded; /// /// Whether the current lobby is custom (true) or official (false). diff --git a/MultiplayerExtensions/Plugin.cs b/MultiplayerExtensions/Plugin.cs index 542236f..dd379ef 100644 --- a/MultiplayerExtensions/Plugin.cs +++ b/MultiplayerExtensions/Plugin.cs @@ -23,7 +23,7 @@ namespace MultiplayerExtensions [Plugin(RuntimeOptions.SingleStartInit)] public class Plugin { - public static readonly string HarmonyId = "com.github.Zingabopp.MultiplayerExtensions"; + public static readonly string HarmonyId = "com.github.Goobwabber.MultiplayerExtensions"; internal static Plugin Instance { get; private set; } = null!; internal static PluginMetadata PluginMetadata = null!; @@ -114,7 +114,7 @@ public async Task CheckVersion() { try { - GithubVersion latest = await VersionCheck.GetLatestVersionAsync("Zingabopp", "MultiplayerExtensions"); + GithubVersion latest = await VersionCheck.GetLatestVersionAsync("Goobwabber", "MultiplayerExtensions"); Log?.Debug($"Latest version is {latest}, released on {latest.ReleaseDate.ToShortDateString()}"); if (PluginMetadata != null) { diff --git a/MultiplayerExtensions/UI/LobbySetupPanel.cs b/MultiplayerExtensions/UI/LobbySetupPanel.cs index f65604b..a5aecba 100644 --- a/MultiplayerExtensions/UI/LobbySetupPanel.cs +++ b/MultiplayerExtensions/UI/LobbySetupPanel.cs @@ -3,9 +3,7 @@ using BeatSaberMarkupLanguage.Components.Settings; using BeatSaberMarkupLanguage.ViewControllers; using HMUI; -using MultiplayerExtensions.OverrideClasses; using Polyglot; -using System.Collections.Generic; using System.Linq; using UnityEngine; using Zenject; diff --git a/MultiplayerExtensions/HarmonyPatches/HarmonyManager.cs b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs similarity index 96% rename from MultiplayerExtensions/HarmonyPatches/HarmonyManager.cs rename to MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs index 00e96c1..ee53628 100644 --- a/MultiplayerExtensions/HarmonyPatches/HarmonyManager.cs +++ b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs @@ -1,22 +1,17 @@ using HarmonyLib; +using MultiplayerExtensions.HarmonyPatches; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; -namespace MultiplayerExtensions.HarmonyPatches +namespace MultiplayerExtensions.Utilities { public static class HarmonyManager { - public static readonly string HarmonyId = "com.github.Zingabopp.MultiplayerExtensions"; - private static Harmony? _harmony; - internal static Harmony Harmony - { - get - { - return _harmony ??= new Harmony(HarmonyId); - } - } + internal static string HarmonyId => Plugin.HarmonyId; + internal static Harmony Harmony => Plugin.Harmony; + internal static readonly BindingFlags allBindingFlags = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; internal static readonly BindingFlags allInstanceBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; internal static readonly BindingFlags allStaticBindingFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; @@ -27,6 +22,7 @@ internal static Harmony Harmony static HarmonyManager() { AddDefaultPatch(); + AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); diff --git a/MultiplayerExtensions/HarmonyPatches/HarmonyPatchInfo.cs b/MultiplayerExtensions/Utilities/Harmony/HarmonyPatchInfo.cs similarity index 97% rename from MultiplayerExtensions/HarmonyPatches/HarmonyPatchInfo.cs rename to MultiplayerExtensions/Utilities/Harmony/HarmonyPatchInfo.cs index f9df348..ef0088e 100644 --- a/MultiplayerExtensions/HarmonyPatches/HarmonyPatchInfo.cs +++ b/MultiplayerExtensions/Utilities/Harmony/HarmonyPatchInfo.cs @@ -2,7 +2,7 @@ using System; using System.Reflection; -namespace MultiplayerExtensions.HarmonyPatches +namespace MultiplayerExtensions.Utilities { public class HarmonyPatchInfo { @@ -67,7 +67,7 @@ public bool ApplyPatch(Harmony? harmony = null) patchTypeName = PostfixMethod.method.DeclaringType?.Name; else if (TranspilerMethod != null) patchTypeName = TranspilerMethod.method.DeclaringType?.Name; - Plugin.Log?.Debug($"Harmony patching '{OriginalMethod.Name}' with '{patchTypeName}'"); + //Plugin.Log?.Debug($"Harmony patching '{OriginalMethod.Name}' with '{patchTypeName}'"); harmony.Patch(OriginalMethod, PrefixMethod, PostfixMethod, TranspilerMethod); IsApplied = true; HarmonyManager.AppliedPatches.Add(this); diff --git a/MultiplayerExtensions/Utilities/VersionCheck.cs b/MultiplayerExtensions/Utilities/Version/VersionCheck.cs similarity index 100% rename from MultiplayerExtensions/Utilities/VersionCheck.cs rename to MultiplayerExtensions/Utilities/Version/VersionCheck.cs diff --git a/MultiplayerExtensions/Utilities/VersionInfo.cs b/MultiplayerExtensions/Utilities/Version/VersionInfo.cs similarity index 96% rename from MultiplayerExtensions/Utilities/VersionInfo.cs rename to MultiplayerExtensions/Utilities/Version/VersionInfo.cs index b20a8b7..0798e61 100644 --- a/MultiplayerExtensions/Utilities/VersionInfo.cs +++ b/MultiplayerExtensions/Utilities/Version/VersionInfo.cs @@ -1,7 +1,7 @@ using System.Linq; using System.Reflection; -namespace MultiplayerExtensions +namespace MultiplayerExtensions.Utilities { internal static class VersionInfo { From 2561f28b505643cb76231a0e66ab42ca6c39bbfb Mon Sep 17 00:00:00 2001 From: MT Date: Fri, 23 Jul 2021 16:30:35 -0400 Subject: [PATCH 06/41] placeholder for ui stuff --- MultiplayerExtensions/UI/LobbySetupPanel.cs | 40 +++++++++++++++------ 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/MultiplayerExtensions/UI/LobbySetupPanel.cs b/MultiplayerExtensions/UI/LobbySetupPanel.cs index a5aecba..77f8258 100644 --- a/MultiplayerExtensions/UI/LobbySetupPanel.cs +++ b/MultiplayerExtensions/UI/LobbySetupPanel.cs @@ -3,6 +3,7 @@ using BeatSaberMarkupLanguage.Components.Settings; using BeatSaberMarkupLanguage.ViewControllers; using HMUI; +using MultiplayerExtensions.Extensions; using Polyglot; using System.Linq; using UnityEngine; @@ -13,17 +14,21 @@ namespace MultiplayerExtensions.UI class LobbySetupPanel : BSMLResourceViewController { public override string ResourceName => "MultiplayerExtensions.UI.LobbySetupPanel.bsml"; - private IMultiplayerSessionManager sessionManager; + + private ExtendedSessionManager _sessionManager = null!; + private LobbyPlayerPermissionsModel _permissionsModel = null!; CurvedTextMeshPro? modifierText; [Inject] - internal void Inject(IMultiplayerSessionManager sessionManager, LobbySetupViewController hostViewController, MultiplayerLevelLoader levelLoader) + internal void Inject(IMultiplayerSessionManager sessionManager, LobbyPlayerPermissionsModel permissionsModel, LobbySetupViewController lobbyViewController) { - this.sessionManager = sessionManager; + this._sessionManager = (sessionManager as ExtendedSessionManager)!; + this._permissionsModel = permissionsModel; base.DidActivate(true, false, true); - hostViewController.didActivateEvent += OnActivate; + lobbyViewController.didActivateEvent += OnActivate; + _sessionManager.playerStateChangedEvent += HandlePlayerStateChanged; } #region UIComponents @@ -59,9 +64,10 @@ internal void Inject(IMultiplayerSessionManager sessionManager, LobbySetupViewCo [UIValue("FreeMod")] public bool FreeMod { - get => Plugin.Config.FreeMod; - set { - Plugin.Config.FreeMod = value; + get => _permissionsModel.isPartyOwner ? Plugin.Config.FreeMod : MPState.FreeModEnabled; + set { + if (_permissionsModel.isPartyOwner) + Plugin.Config.FreeMod = value; if (MPState.FreeModEnabled != value) { MPState.FreeModEnabled = value; @@ -76,7 +82,8 @@ public bool HostPick get => Plugin.Config.HostPick; set { - Plugin.Config.HostPick = value; + if (_permissionsModel.isPartyOwner) + Plugin.Config.HostPick = value; if (MPState.HostPickEnabled != value) { MPState.HostPickEnabled = value; @@ -192,6 +199,9 @@ public void SetMissLighting(bool value) private void OnActivate(bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling) { + freeModToggle.interactable = _permissionsModel.isPartyOwner; + hostPickToggle.interactable = _permissionsModel.isPartyOwner; + if (firstActivation) { Transform spectatorText = transform.Find("Wrapper").Find("SpectatorModeWarningText"); @@ -199,10 +209,20 @@ private void OnActivate(bool firstActivation, bool addedToHierarchy, bool screen } } + private void HandlePlayerStateChanged(IConnectedPlayer player) + { + ExtendedPlayer? exPlayer = _sessionManager.GetExtendedPlayer(player); + if (exPlayer != null && exPlayer.isPartyOwner) + { + FreeMod = exPlayer.HasState("freemod"); + HostPick = exPlayer.HasState("hostpick"); + } + } + private void UpdateStates() { - sessionManager?.SetLocalPlayerState("freemod", FreeMod); - sessionManager?.SetLocalPlayerState("hostpick", HostPick); + _sessionManager?.SetLocalPlayerState("freemod", FreeMod); + _sessionManager?.SetLocalPlayerState("hostpick", HostPick); } private void SetModifierText() From 06429f2f9ebe5252e2feed7940ab1fc3a2026a48 Mon Sep 17 00:00:00 2001 From: MT Date: Fri, 23 Jul 2021 17:43:35 -0400 Subject: [PATCH 07/41] quick changes --- MultiplayerExtensions/Beatmaps/PreviewBeatmapStub.cs | 4 ++-- MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/MultiplayerExtensions/Beatmaps/PreviewBeatmapStub.cs b/MultiplayerExtensions/Beatmaps/PreviewBeatmapStub.cs index 0e380bf..8122c5c 100644 --- a/MultiplayerExtensions/Beatmaps/PreviewBeatmapStub.cs +++ b/MultiplayerExtensions/Beatmaps/PreviewBeatmapStub.cs @@ -122,8 +122,8 @@ public async Task GetCoverImageAsync(CancellationToken cancellationToken Plugin.Log?.Warn($"Failed to fetch beatmap cover: {ex.Message}"); } } - - return null!; + + return Sprite.Create(Texture2D.blackTexture, new Rect(0, 0, 2, 2), new Vector2(0, 0), 100.0f); } public Task? GetPreviewAudioClipAsync(CancellationToken cancellationToken) => _preview?.GetPreviewAudioClipAsync(cancellationToken); diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs index ad0e7c0..6456b51 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs @@ -208,7 +208,9 @@ public async override void HandleMenuRpcManagerRecommendBeatmap(string userId, B HMMainThreadDispatcher.instance.Enqueue(() => base.SetPlayerBeatmapLevel(base.localUserId, preview, beatmapDifficulty, characteristic)); _packetManager.Send(new PreviewBeatmapPacket(preview!, characteristic.serializedName, beatmapDifficulty)); - if (!_sessionManager.connectionOwner.HasState("modded")) + if (_sessionManager.connectionOwner.HasState("modded")) + _menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(levelId, characteristic.serializedName, beatmapDifficulty)); + else _menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(PlaceholderSongID, characteristic.serializedName, beatmapDifficulty)); } }else From 18b000cdeb71b31e2cef6a193b27e52a3ddbaf79 Mon Sep 17 00:00:00 2001 From: MT Date: Thu, 29 Jul 2021 22:16:42 -0400 Subject: [PATCH 08/41] nice nice --- MultiplayerExtensions/Extensions/ExtendedPlayerTableCell.cs | 5 ++++- MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs | 4 ++-- MultiplayerExtensions/MultiplayerExtensions.csproj | 4 ++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayerTableCell.cs b/MultiplayerExtensions/Extensions/ExtendedPlayerTableCell.cs index 9e4c3db..cdd49c1 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayerTableCell.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayerTableCell.cs @@ -87,8 +87,11 @@ private async void GetLevelEntitlement(IConnectedPlayer player) entitlementCts = new CancellationTokenSource(); string? levelId = _playersDataModel.GetPlayerBeatmapLevel(_playersDataModel.partyOwnerId)?.levelID; - if (levelId == null) + if (levelId == null) + { + SetLevelEntitlement(player, EntitlementsStatus.Unknown); return; + } lastLevelId = levelId; diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs index 6456b51..495bad0 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs @@ -160,7 +160,7 @@ public async override void HandleMenuRpcManagerRecommendBeatmap(string userId, B string? hash = Utilities.Utils.LevelIdToHash(beatmapId.levelID); if (hash != null) { - Plugin.Log?.Debug($"'{userId}' selected song '{hash ?? beatmapId.levelID}'."); + Plugin.Log?.Debug($"'{userId}' selected song '{beatmapId.levelID}'."); BeatmapCharacteristicSO characteristic = _beatmapCharacteristicCollection.GetBeatmapCharacteristicBySerializedName(beatmapId.beatmapCharacteristicSerializedName); if (_playersData.Values.Any(playerData => playerData.beatmapLevel?.levelID == beatmapId.levelID)) { @@ -179,7 +179,7 @@ public async override void HandleMenuRpcManagerRecommendBeatmap(string userId, B } } else - base.HandleMenuRpcManagerRecommendBeatmap(userId, beatmapId); + return; //base.HandleMenuRpcManagerRecommendBeatmap(userId, beatmapId); } /// diff --git a/MultiplayerExtensions/MultiplayerExtensions.csproj b/MultiplayerExtensions/MultiplayerExtensions.csproj index 76d83f0..0ca2fb8 100644 --- a/MultiplayerExtensions/MultiplayerExtensions.csproj +++ b/MultiplayerExtensions/MultiplayerExtensions.csproj @@ -59,6 +59,10 @@ False False + + $(BeatSaberDir)\Libs\Hive.Versioning.dll + False + $(BeatSaberDir)\Beat Saber_Data\Managed\HMRendering.dll False From 2967c6cc96697f9b9ff1b8bae32991b0c8fdb9a7 Mon Sep 17 00:00:00 2001 From: MT Date: Fri, 30 Jul 2021 02:07:30 -0400 Subject: [PATCH 09/41] fixed hud C: --- .../Environments/MultiplayerActivePlayer.cs | 6 +- .../Environments/MultiplayerGameplayHud.cs | 81 +++++++++++++++++++ .../HarmonyPatches/EnvironmentPatches.cs | 55 ------------- MultiplayerExtensions/UI/LobbySetupPanel.bsml | 1 - MultiplayerExtensions/UI/LobbySetupPanel.cs | 24 +----- MultiplayerExtensions/Utilities/Config.cs | 1 - .../Utilities/Harmony/HarmonyManager.cs | 1 - 7 files changed, 88 insertions(+), 81 deletions(-) create mode 100644 MultiplayerExtensions/Environments/MultiplayerGameplayHud.cs diff --git a/MultiplayerExtensions/Environments/MultiplayerActivePlayer.cs b/MultiplayerExtensions/Environments/MultiplayerActivePlayer.cs index d2597c8..f803e84 100644 --- a/MultiplayerExtensions/Environments/MultiplayerActivePlayer.cs +++ b/MultiplayerExtensions/Environments/MultiplayerActivePlayer.cs @@ -24,12 +24,16 @@ internal void Inject(IConnectedPlayer connectedPlayer, MultiplayerController mul protected void Awake() { + MultiplayerGameplayAnimator gameplayAnimator = transform.GetComponentInChildren(); + if (Plugin.Config.MissLighting) { - MultiplayerGameplayAnimator gameplayAnimator = transform.GetComponentInChildren(); MultiplayerGameplayLighting gameplayLighting = gameplayAnimator.gameObject.AddComponent(); gameplayLighting.Construct(_connectedPlayer, _multiplayerController, _scoreProvider, _leadPlayerProvider, gameplayAnimator, _sessionManager); } + + MultiplayerGameplayHud gameplayHud = gameplayAnimator.gameObject.AddComponent(); + gameplayHud.Construct(_connectedPlayer, gameplayAnimator); } } } diff --git a/MultiplayerExtensions/Environments/MultiplayerGameplayHud.cs b/MultiplayerExtensions/Environments/MultiplayerGameplayHud.cs new file mode 100644 index 0000000..dcd1a71 --- /dev/null +++ b/MultiplayerExtensions/Environments/MultiplayerGameplayHud.cs @@ -0,0 +1,81 @@ +using HMUI; +using IPA.Utilities; +using UnityEngine; + +namespace MultiplayerExtensions.Environments +{ + class MultiplayerGameplayHud : MonoBehaviour + { + protected IConnectedPlayer _connectedPlayer = null!; + protected MultiplayerGameplayAnimator _gameplayAnimator = null!; + + protected CoreGameHUDController _coreGameHUDController = null!; + protected GameObject _songProgressPanelGO = null!; + protected GameObject _energyPanelGO = null!; + + internal void Construct(IConnectedPlayer connectedPlayer, MultiplayerGameplayAnimator gameplayAnimator) + { + _connectedPlayer = connectedPlayer; + _gameplayAnimator = gameplayAnimator; + + if (gameplayAnimator is MultiplayerLocalActivePlayerGameplayAnimator localGameplayAnimator) + { + _coreGameHUDController = localGameplayAnimator.GetField("_coreGameHUDController"); + + _songProgressPanelGO = _coreGameHUDController.GetField("_songProgressPanelGO"); + _energyPanelGO = _coreGameHUDController.GetField("_energyPanelGO"); + } + } + + internal void Start() + { + if (Plugin.Config.SingleplayerHUD && _coreGameHUDController != null) + { + Plugin.Log?.Debug("Setting up multiplayer HUD"); + + _coreGameHUDController.transform.position = new Vector3(0f, 0f, 10f); + _coreGameHUDController.transform.eulerAngles = new Vector3(270f, 0f, 0f); + + _energyPanelGO.transform.localPosition = new Vector3(0f, 4f, 0f); + _energyPanelGO.transform.localEulerAngles = new Vector3(90f, 0f, 0f); + + if (!_coreGameHUDController.transform.Find("LeftPanel")) + { + Transform comboPanel = _coreGameHUDController.transform.Find("ComboPanel"); + Transform scoreCanvas = _coreGameHUDController.transform.Find("ScoreCanvas"); + Transform multiplierCanvas = _coreGameHUDController.transform.Find("MultiplierCanvas"); + + GameObject leftPanel = new GameObject(); + GameObject rightPanel = new GameObject(); + leftPanel.name = "LeftPanel"; + rightPanel.name = "RightPanel"; + leftPanel.transform.parent = _coreGameHUDController.transform; + rightPanel.transform.parent = _coreGameHUDController.transform; + leftPanel.transform.localPosition = new Vector3(-2.5f, 0f, 1f); + rightPanel.transform.localPosition = new Vector3(2.5f, 0f, 1f); + + _songProgressPanelGO.transform.SetParent(rightPanel.transform, true); + _songProgressPanelGO.transform.localPosition = new Vector3(0f, -1.1f, 0f); + _songProgressPanelGO.transform.SetParent(_coreGameHUDController.transform, true); + + multiplierCanvas.transform.SetParent(rightPanel.transform, true); + multiplierCanvas.transform.localPosition = new Vector3(0f, 0f, 0f); + multiplierCanvas.transform.SetParent(_coreGameHUDController.transform, true); + + comboPanel.transform.SetParent(leftPanel.transform, true); + comboPanel.transform.localPosition = new Vector3(0f, 0f, 0f); + comboPanel.transform.SetParent(_coreGameHUDController.transform, true); + + scoreCanvas.transform.SetParent(leftPanel.transform, true); + scoreCanvas.transform.localPosition = new Vector3(0f, -1.1f, 0f); + scoreCanvas.transform.SetParent(_coreGameHUDController.transform, true); + + foreach (CurvedTextMeshPro panel in scoreCanvas.GetComponentsInChildren()) + { + panel.enabled = true; + } + } + } + } + } +} diff --git a/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs b/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs index 689b333..3793f30 100644 --- a/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs @@ -130,61 +130,6 @@ static void Prefix(ref GameObject[] rings) } } - [HarmonyPatch(typeof(CoreGameHUDController), nameof(CoreGameHUDController.Start), MethodType.Normal)] - internal class CoreGameHUDController_Start - { - static void Postfix(CoreGameHUDController __instance, ref GameObject ____songProgressPanelGO, ref GameObject ____energyPanelGO) - { - if (Plugin.Config.VerticalHUD) - { - Plugin.Log?.Debug("Setting up multiplayer HUD"); - - __instance.transform.position = new Vector3(0f, 0f, 10f); - __instance.transform.eulerAngles = new Vector3(270f, 0f, 0f); - - ____energyPanelGO.transform.localPosition = new Vector3(0f, 4f, 0f); - ____energyPanelGO.transform.localEulerAngles = new Vector3(90f, 0f, 0f); - - if (Plugin.Config.SingleplayerHUD && !__instance.transform.Find("LeftPanel")) - { - Transform comboPanel = __instance.transform.Find("ComboPanel"); - Transform scoreCanvas = __instance.transform.Find("ScoreCanvas"); - Transform multiplierCanvas = __instance.transform.Find("MultiplierCanvas"); - - GameObject leftPanel = new GameObject(); - GameObject rightPanel = new GameObject(); - leftPanel.name = "LeftPanel"; - rightPanel.name = "RightPanel"; - leftPanel.transform.parent = __instance.transform; - rightPanel.transform.parent = __instance.transform; - leftPanel.transform.localPosition = new Vector3(-2.5f, 0f, 1f); - rightPanel.transform.localPosition = new Vector3(2.5f, 0f, 1f); - - ____songProgressPanelGO.transform.SetParent(rightPanel.transform, true); - ____songProgressPanelGO.transform.localPosition = new Vector3(0f, -1.1f, 0f); - ____songProgressPanelGO.transform.SetParent(__instance.transform, true); - - multiplierCanvas.transform.SetParent(rightPanel.transform, true); - multiplierCanvas.transform.localPosition = new Vector3(0f, 0f, 0f); - multiplierCanvas.transform.SetParent(__instance.transform, true); - - comboPanel.transform.SetParent(leftPanel.transform, true); - comboPanel.transform.localPosition = new Vector3(0f, 0f, 0f); - comboPanel.transform.SetParent(__instance.transform, true); - - scoreCanvas.transform.SetParent(leftPanel.transform, true); - scoreCanvas.transform.localPosition = new Vector3(0f, -1.1f, 0f); - scoreCanvas.transform.SetParent(__instance.transform, true); - - foreach (CurvedTextMeshPro panel in scoreCanvas.GetComponentsInChildren()) - { - panel.enabled = true; - } - } - } - } - } - [HarmonyPatch(typeof(MultiplayerLobbyAvatarManager), nameof(MultiplayerLobbyAvatarManager.AddPlayer), MethodType.Normal)] internal class MultiplayerLobbyAvatarAddedPatch { diff --git a/MultiplayerExtensions/UI/LobbySetupPanel.bsml b/MultiplayerExtensions/UI/LobbySetupPanel.bsml index 0a549f4..497803d 100644 --- a/MultiplayerExtensions/UI/LobbySetupPanel.bsml +++ b/MultiplayerExtensions/UI/LobbySetupPanel.bsml @@ -6,7 +6,6 @@ - diff --git a/MultiplayerExtensions/UI/LobbySetupPanel.cs b/MultiplayerExtensions/UI/LobbySetupPanel.cs index 77f8258..d7f63ab 100644 --- a/MultiplayerExtensions/UI/LobbySetupPanel.cs +++ b/MultiplayerExtensions/UI/LobbySetupPanel.cs @@ -41,9 +41,6 @@ internal void Inject(IMultiplayerSessionManager sessionManager, LobbyPlayerPermi [UIComponent("HostPickToggle")] public ToggleSetting hostPickToggle = null!; - [UIComponent("VerticalHUDToggle")] - public ToggleSetting verticalHUDToggle = null!; - [UIComponent("DefaultHUDToggle")] public ToggleSetting defaultHUDToggle = null!; @@ -92,13 +89,6 @@ public bool HostPick } } - [UIValue("VerticalHUD")] - public bool VerticalHUD - { - get => Plugin.Config.VerticalHUD; - set { Plugin.Config.VerticalHUD = value; } - } - [UIValue("DefaultHUD")] public bool DefaultHUD { @@ -155,24 +145,14 @@ public void SetHostPick(bool value) UpdateStates(); } - [UIAction("SetVerticalHUD")] - public void SetVerticalHUD(bool value) - { - VerticalHUD = value; - verticalHUDToggle.Value = value; - - DefaultHUD = !(!DefaultHUD || !value); - defaultHUDToggle.Value = !(!DefaultHUD || !value); - } - [UIAction("SetDefaultHUD")] public void SetDefaultHUD(bool value) { DefaultHUD = value; defaultHUDToggle.Value = value; - VerticalHUD = VerticalHUD || value; - verticalHUDToggle.Value = VerticalHUD || value; + //VerticalHUD = VerticalHUD || value; + //verticalHUDToggle.Value = VerticalHUD || value; } [UIAction("SetHologram")] diff --git a/MultiplayerExtensions/Utilities/Config.cs b/MultiplayerExtensions/Utilities/Config.cs index c387053..b5717b5 100644 --- a/MultiplayerExtensions/Utilities/Config.cs +++ b/MultiplayerExtensions/Utilities/Config.cs @@ -4,7 +4,6 @@ namespace MultiplayerExtensions { public class PluginConfig { - public virtual bool VerticalHUD { get; set; } = false; public virtual bool SingleplayerHUD { get; set; } = false; public virtual bool Hologram { get; set; } = true; public virtual bool FreeMod { get; set; } = false; diff --git a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs index ee53628..3f116dd 100644 --- a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs +++ b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs @@ -24,7 +24,6 @@ static HarmonyManager() AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); - AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); From 6001d24f4ab69b73808500c8ad5cb07cf438fc85 Mon Sep 17 00:00:00 2001 From: MT Date: Fri, 30 Jul 2021 02:48:17 -0400 Subject: [PATCH 10/41] i have discovered pain --- .../HarmonyPatches/EnvironmentPatches.cs | 36 +++++++++++++++++++ .../Utilities/Harmony/HarmonyManager.cs | 1 + 2 files changed, 37 insertions(+) diff --git a/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs b/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs index 3793f30..ce724c6 100644 --- a/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs @@ -7,6 +7,9 @@ using UnityEngine; using UnityEngine.Timeline; using UnityEngine.Playables; +using System.Reflection.Emit; +using UnityEngine.UI; +using System.Reflection; namespace MultiplayerExtensions.HarmonyPatches { @@ -138,4 +141,37 @@ static void Postfix(IConnectedPlayer connectedPlayer, MultiplayerLobbyAvatarMana MPEvents.RaiseLobbyAvatarCreated(__instance, connectedPlayer); } } + + [HarmonyPatch(typeof(LobbySetupViewController), nameof(LobbySetupViewController.SetLobbyState), MethodType.Normal)] + internal class EnableCancelButtonPatch + { + private static readonly MethodInfo _rootMethod = typeof(Selectable).GetProperty(nameof(Selectable.interactable)).GetSetMethod(); + private static readonly FieldInfo _cancelGameUnreadyButtonPrefab = typeof(LobbySetupViewController).GetField("_cancelGameUnreadyButton", BindingFlags.NonPublic | BindingFlags.Instance); +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. + private static readonly MethodInfo _setInteractableAttacher = SymbolExtensions.GetMethodInfo(() => SetInteractableAttacher(null, false)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. + + static IEnumerable Transpiler(IEnumerable instructions) + { + var codes = instructions.ToList(); + for (int i = 0; i < codes.Count; i++) + { + if (codes[i].opcode == OpCodes.Ldfld && codes[i].OperandIs(_cancelGameUnreadyButtonPrefab)) + { + if (codes[i + 4].opcode == OpCodes.Callvirt && codes[i + 4].Calls(_rootMethod)) + { + CodeInstruction newCode = new CodeInstruction(OpCodes.Callvirt, _setInteractableAttacher); + codes[i + 4] = newCode; + } + } + } + + return codes.AsEnumerable(); + } + + private static void SetInteractableAttacher(Selectable contract, bool value) + { + contract.interactable = true; + } + } } diff --git a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs index 3f116dd..2f66529 100644 --- a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs +++ b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs @@ -47,6 +47,7 @@ static HarmonyManager() //AddDefaultPatch(); (doesn't support generics) AddDefaultPatch(); AddDefaultPatch(); + //AddDefaultPatch(); (buggy asf) } private static void AddDefaultPatch() where T : class From 957012615d41bf446e11757b742172838683bce3 Mon Sep 17 00:00:00 2001 From: MT Date: Fri, 30 Jul 2021 18:45:30 -0400 Subject: [PATCH 11/41] made black magic happen --- .../Extensions/ExtendedGameStateController.cs | 35 ++++++++++++- .../Extensions/ExtendedPlayerReady.cs | 27 ++++++++++ .../Extensions/ExtendedPlayersDataModel.cs | 49 ++++++++++++------- .../Utilities/Harmony/HarmonyManager.cs | 2 +- 4 files changed, 93 insertions(+), 20 deletions(-) create mode 100644 MultiplayerExtensions/Extensions/ExtendedPlayerReady.cs diff --git a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs index bc66572..aa33896 100644 --- a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs +++ b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs @@ -25,6 +25,7 @@ public override void Activate() base.Activate(); (this as ILobbyGameStateController).lobbyStateChangedEvent += this.HandleLobbyStateChanged; + _lobbyPlayersDataModel.didChangeEvent += this.HandleDataModelChanged; } public override void Deactivate() @@ -37,6 +38,7 @@ public override void Deactivate() base.Deactivate(); (this as ILobbyGameStateController).lobbyStateChangedEvent -= this.HandleLobbyStateChanged; + _lobbyPlayersDataModel.didChangeEvent -= this.HandleDataModelChanged; } public override void Dispose() @@ -74,6 +76,24 @@ public override void StopListeningToGameStart() + private void HandleDataModelChanged(string userId) + { + if (state == MultiplayerLobbyState.GameStarting) + { + ILobbyPlayerData partyOwnerData = _lobbyPlayersDataModel.GetLobbyPlayerDataModel(_lobbyPlayersDataModel.partyOwnerId); + if (partyOwnerData.isReady) + { + PredictCountdownEndTime(); + HandleMenuRpcManagerStartedLevel(_lobbyPlayersDataModel.partyOwnerId, new BeatmapIdentifierNetSerializable(partyOwnerData.beatmapLevel.levelID, partyOwnerData.beatmapCharacteristic.serializedName, partyOwnerData.beatmapDifficulty), partyOwnerData.gameplayModifiers, _predictedStartTime); + } else + { + HandleMenuRpcManagerCancelledLevelStart(_lobbyPlayersDataModel.partyOwnerId); + } + } + } + + + private IPreviewBeatmapLevel? _previewBeatmapLevel; private BeatmapDifficulty _beatmapDifficulty; private BeatmapCharacteristicSO? _beatmapCharacteristic; @@ -82,7 +102,17 @@ public override void StopListeningToGameStart() public override void HandleMenuRpcManagerStartedLevel(string userId, BeatmapIdentifierNetSerializable beatmapId, GameplayModifiers gameplayModifiers, float startTime) { - if (_sessionManager.partyOwner != null) + if (this.levelStartInitiated) + { + if (userId == _sessionManager.connectionOwner.userId) + { + Plugin.Log?.Debug("Server map start initiated"); + base.HandleMultiplayerLevelLoaderCountdownFinished(_previewBeatmapLevel, _beatmapDifficulty, _beatmapCharacteristic, _difficultyBeatmap, _gameplayModifiers); + } + return; + } + + if (_sessionManager.partyOwner != null && state == MultiplayerLobbyState.GameStarting) { ILobbyPlayerData partyOwnerData = _lobbyPlayersDataModel.GetLobbyPlayerDataModel(_sessionManager.partyOwner.userId); beatmapId = new BeatmapIdentifierNetSerializable(partyOwnerData.beatmapLevel.levelID, partyOwnerData.beatmapCharacteristic.serializedName, partyOwnerData.beatmapDifficulty); @@ -142,7 +172,8 @@ private async void HandleEntitlement(string userId, string levelId, Entitlements if (readyStates.All(x => x) && await _entitlementChecker.GetEntitlementStatus(startedBeatmapId.levelID) == EntitlementsStatus.Ok) { Plugin.Log.Debug("All players ready, starting game."); - base.HandleMultiplayerLevelLoaderCountdownFinished(_previewBeatmapLevel, _beatmapDifficulty, _beatmapCharacteristic, _difficultyBeatmap, _gameplayModifiers); + _menuRpcManager.SetIsReady(true); + //base.HandleMultiplayerLevelLoaderCountdownFinished(_previewBeatmapLevel, _beatmapDifficulty, _beatmapCharacteristic, _difficultyBeatmap, _gameplayModifiers); } } } diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayerReady.cs b/MultiplayerExtensions/Extensions/ExtendedPlayerReady.cs new file mode 100644 index 0000000..e26a94e --- /dev/null +++ b/MultiplayerExtensions/Extensions/ExtendedPlayerReady.cs @@ -0,0 +1,27 @@ +using LiteNetLib.Utils; + +namespace MultiplayerExtensions.Extensions +{ + class ExtendedPlayerReadyPacket : INetSerializable, IPoolablePacket + { + public void Release() => ThreadStaticPacketPool.pool.Release(this); + + public void Serialize(NetDataWriter writer) + { + writer.Put(ready); + } + + public void Deserialize(NetDataReader reader) + { + this.ready = reader.GetBool(); + } + + public ExtendedPlayerReadyPacket Init(bool ready) + { + this.ready = ready; + return this; + } + + public bool ready; + } +} diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs index 495bad0..3372922 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs @@ -26,6 +26,7 @@ public override void Activate() MPEvents.CustomSongsChanged += this.HandleCustomSongsChanged; MPEvents.FreeModChanged += this.HandleFreeModChanged; this._packetManager.RegisterCallback(this.HandlePreviewBeatmapPacket); + this._packetManager.RegisterCallback(this.HandlePlayerReadyPacket); base.Activate(); _menuRpcManager.recommendBeatmapEvent -= base.HandleMenuRpcManagerRecommendBeatmap; @@ -47,6 +48,7 @@ public override void Deactivate() MPEvents.CustomSongsChanged -= HandleCustomSongsChanged; MPEvents.FreeModChanged -= HandleFreeModChanged; this._packetManager.UnregisterCallback(); + this._packetManager.UnregisterCallback(); _menuRpcManager.recommendBeatmapEvent -= this.HandleMenuRpcManagerRecommendBeatmap; _menuRpcManager.recommendBeatmapEvent += base.HandleMenuRpcManagerRecommendBeatmap; @@ -69,23 +71,6 @@ public override void Deactivate() this.Deactivate(); } - public override void SetLocalPlayerIsReady(bool isReady, bool notifyChange) - { - if (!Plugin.Config.HostPick && this.localUserId == this.partyOwnerId) - { - ILobbyPlayerData localPlayerDataModel = this.GetLobbyPlayerDataModel(localUserId); - IEnumerable validDataModels = this.playersData.Values.Where(data => data.beatmapLevel != null); - ILobbyPlayerData chosenPlayerDataModel = validDataModels.ElementAt(new Random().Next(0, validDataModels.Count())); - localPlayerDataModel.beatmapLevel = chosenPlayerDataModel.beatmapLevel; - localPlayerDataModel.beatmapDifficulty = chosenPlayerDataModel.beatmapDifficulty; - localPlayerDataModel.beatmapCharacteristic = chosenPlayerDataModel.beatmapCharacteristic; - localPlayerDataModel.gameplayModifiers = chosenPlayerDataModel.gameplayModifiers; - this._menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(chosenPlayerDataModel.beatmapLevel.levelID, chosenPlayerDataModel.beatmapCharacteristic.serializedName, chosenPlayerDataModel.beatmapDifficulty)); - this._menuRpcManager.RecommendGameplayModifiers(chosenPlayerDataModel.gameplayModifiers); - this.NotifyModelChange(this.localUserId); - } - } - private void HandleCustomSongsChanged(object sender, bool value) { if (!value && GetPlayerBeatmapLevel(localUserId) is PreviewBeatmapStub) @@ -264,6 +249,36 @@ public override void HandleMenuRpcManagerSetPlayersPermissionConfiguration(strin _sessionManager.partyOwner = _sessionManager.GetPlayerByUserId(partyOwnerId); } + private void HandlePlayerReadyPacket(ExtendedPlayerReadyPacket packet, IConnectedPlayer player) + { + base.SetPlayerIsReady(player.userId, packet.ready, true); + } + + public override void SetLocalPlayerIsReady(bool isReady) + { + this.SetLocalPlayerIsReady(isReady, true); + } + + public override void SetLocalPlayerIsReady(bool isReady, bool notifyChange) + { + if (!Plugin.Config.HostPick && this.localUserId == this.partyOwnerId) + { + ILobbyPlayerData localPlayerDataModel = this.GetLobbyPlayerDataModel(localUserId); + IEnumerable validDataModels = this.playersData.Values.Where(data => data.beatmapLevel != null); + ILobbyPlayerData chosenPlayerDataModel = validDataModels.ElementAt(new Random().Next(0, validDataModels.Count())); + localPlayerDataModel.beatmapLevel = chosenPlayerDataModel.beatmapLevel; + localPlayerDataModel.beatmapDifficulty = chosenPlayerDataModel.beatmapDifficulty; + localPlayerDataModel.beatmapCharacteristic = chosenPlayerDataModel.beatmapCharacteristic; + localPlayerDataModel.gameplayModifiers = chosenPlayerDataModel.gameplayModifiers; + this._menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(chosenPlayerDataModel.beatmapLevel.levelID, chosenPlayerDataModel.beatmapCharacteristic.serializedName, chosenPlayerDataModel.beatmapDifficulty)); + this._menuRpcManager.RecommendGameplayModifiers(chosenPlayerDataModel.gameplayModifiers); + this.NotifyModelChange(this.localUserId); + } + + _packetManager.Send(new ExtendedPlayerReadyPacket().Init(isReady)); + base.SetPlayerIsReady(this.localUserId, isReady, notifyChange); + } + /// /// Used to raise the event. /// diff --git a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs index 2f66529..281bbde 100644 --- a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs +++ b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs @@ -47,7 +47,7 @@ static HarmonyManager() //AddDefaultPatch(); (doesn't support generics) AddDefaultPatch(); AddDefaultPatch(); - //AddDefaultPatch(); (buggy asf) + AddDefaultPatch(); } private static void AddDefaultPatch() where T : class From 8cd288f890fc0c26f97ec5d4b2b002e4d1cea224 Mon Sep 17 00:00:00 2001 From: MT Date: Mon, 23 Aug 2021 15:27:07 -0400 Subject: [PATCH 12/41] update beatsaversharp --- .../Beatmaps/PreviewBeatmapStub.cs | 10 +++++----- MultiplayerExtensions/Downloader.cs | 19 +++++-------------- .../Extensions/ExtendedEntitlementChecker.cs | 4 ++-- .../Extensions/ExtendedPlayersDataModel.cs | 6 +++--- MultiplayerExtensions/Plugin.cs | 2 +- MultiplayerExtensions/Utilities/Sprites.cs | 2 +- 6 files changed, 17 insertions(+), 26 deletions(-) diff --git a/MultiplayerExtensions/Beatmaps/PreviewBeatmapStub.cs b/MultiplayerExtensions/Beatmaps/PreviewBeatmapStub.cs index 8122c5c..2a0e1b0 100644 --- a/MultiplayerExtensions/Beatmaps/PreviewBeatmapStub.cs +++ b/MultiplayerExtensions/Beatmaps/PreviewBeatmapStub.cs @@ -1,4 +1,4 @@ -using BeatSaverSharp; +using BeatSaverSharp.Models; using System; using System.Threading; using System.Threading.Tasks; @@ -23,7 +23,7 @@ public Task isDownloadable if (_downloadableTask == null) { - _downloadableTask = Plugin.BeatSaver.Hash(levelHash).ContinueWith(r => r.Exception == null && r.Result is Beatmap); + _downloadableTask = Plugin.BeatSaver.BeatmapByHash(levelHash).ContinueWith(r => r.Exception == null && r.Result is Beatmap); _downloadableTask.ContinueWith(r => _downloadable = r.Result ? DownloadableState.True : DownloadableState.False); } @@ -85,14 +85,14 @@ public PreviewBeatmapStub(PreviewBeatmapPacket packet) this.songDuration = packet.songDuration; } - public PreviewBeatmapStub(string levelID, Beatmap bm) + public PreviewBeatmapStub(string levelID, string hash, Beatmap bm) { this._beatmap = bm; this._downloadable = DownloadableState.True; this.isDownloaded = false; this.levelID = levelID; - this.levelHash = bm.Hash; + this.levelHash = hash; this.songName = bm.Metadata.SongName; this.songSubName = bm.Metadata.SongSubName; @@ -113,7 +113,7 @@ public async Task GetCoverImageAsync(CancellationToken cancellationToken { try { - Sprite? cover = Utilities.Sprites.GetSprite(await _beatmap.CoverImageBytes()); + Sprite? cover = Utilities.Sprites.GetSprite(await _beatmap.Versions[0].DownloadCoverImage()); if (cover != null) return cover; } diff --git a/MultiplayerExtensions/Downloader.cs b/MultiplayerExtensions/Downloader.cs index 347f826..5385aae 100644 --- a/MultiplayerExtensions/Downloader.cs +++ b/MultiplayerExtensions/Downloader.cs @@ -4,8 +4,8 @@ using System.Threading.Tasks; using MultiplayerExtensions.Utilities; using System.Collections.Concurrent; -using BeatSaverSharp; using System.Diagnostics; +using BeatSaverSharp.Models; #nullable enable namespace MultiplayerExtensions @@ -25,14 +25,14 @@ public static bool TryGetDownload(string levelId, out Task DownloadSong(string hash, CancellationToken cancellationToken) { - Beatmap? bm = await Plugin.BeatSaver.Hash(hash); + Beatmap? bm = await Plugin.BeatSaver.BeatmapByHash(hash); if (bm == null) { Plugin.Log?.Warn($"Could not find song '{hash}' on Beat Saver."); return null; } - Plugin.Log.Info($"Attempting to download song '({bm.Key}) {bm.Name ?? hash}'"); + Plugin.Log.Info($"Attempting to download song '({bm.ID}) {bm.Name ?? hash}'"); #if DEBUG if((Plugin.Config.DebugConfig?.FailDownloads ?? false)) { @@ -43,16 +43,7 @@ public static bool TryGetDownload(string levelId, out Task(d => - { -#if DEBUG - Plugin.Log.Debug($"Downloading '{hash}': {d}"); -#endif - DownloadProgressChanged?.Invoke(hash, d); - }) - }); + byte[]? beatmapBytes = await bm.LatestVersion.DownloadZIP(); #if DEBUG TimeSpan delay = TimeSpan.FromSeconds(Plugin.Config.DebugConfig?.MinDownloadTime ?? 0) - TimeSpan.FromMilliseconds(sw.ElapsedMilliseconds); if (delay > TimeSpan.Zero) @@ -62,7 +53,7 @@ public static bool TryGetDownload(string levelId, out Task GetEntitlementStatus(string levelId) if (SongCore.Collections.songWithHashPresent(hash)) return Task.FromResult(EntitlementsStatus.Ok); - return Plugin.BeatSaver.Hash(hash).ContinueWith(r => + return Plugin.BeatSaver.BeatmapByHash(hash).ContinueWith(r => { Beatmap? beatmap = r.Result; if (beatmap == null) diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs index 3372922..00991dd 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs @@ -1,4 +1,4 @@ -using BeatSaverSharp; +using BeatSaverSharp.Models; using MultiplayerExtensions.Beatmaps; using MultiplayerExtensions.Packets; using System; @@ -328,9 +328,9 @@ private void OnSelectedBeatmap(string userId, BeatmapIdentifierNetSerializable? { try { - Beatmap? bm = await Plugin.BeatSaver.Hash(hash); + Beatmap? bm = await Plugin.BeatSaver.BeatmapByHash(hash); if (bm != null) - return new PreviewBeatmapStub(levelID, bm); + return new PreviewBeatmapStub(levelID, hash, bm); return null; } catch(Exception ex) diff --git a/MultiplayerExtensions/Plugin.cs b/MultiplayerExtensions/Plugin.cs index dd379ef..d582276 100644 --- a/MultiplayerExtensions/Plugin.cs +++ b/MultiplayerExtensions/Plugin.cs @@ -66,7 +66,7 @@ public Plugin(IPALogger logger, Config conf, Zenjector zenjector, PluginMetadata zenjector.OnMenu(); zenjector.OnGame().OnlyForMultiplayer(); - HttpOptions options = new HttpOptions("MultiplayerExtensions", new Version(pluginMetadata.Version.ToString())); + BeatSaverOptions options = new BeatSaverOptions("MultiplayerExtensions", new Version(pluginMetadata.Version.ToString())); BeatSaver = new BeatSaver(options); HttpClient = new HttpClient(); HttpClient.DefaultRequestHeaders.Add("User-Agent", Plugin.UserAgent); diff --git a/MultiplayerExtensions/Utilities/Sprites.cs b/MultiplayerExtensions/Utilities/Sprites.cs index 28a3026..506f86a 100644 --- a/MultiplayerExtensions/Utilities/Sprites.cs +++ b/MultiplayerExtensions/Utilities/Sprites.cs @@ -13,7 +13,7 @@ class Sprites /// /// /// - public static Sprite? GetSprite(byte[] data, float pixelsPerUnit = 100.0f, bool returnDefaultOnFail = true) + public static Sprite? GetSprite(byte[]? data, float pixelsPerUnit = 100.0f, bool returnDefaultOnFail = true) { Sprite? ReturnDefault(bool useDefault) { From 782443051264892037a967cdb67a2309ada7c2ed Mon Sep 17 00:00:00 2001 From: MT Date: Mon, 23 Aug 2021 15:33:12 -0400 Subject: [PATCH 13/41] yeeted old stuff --- .../Extensions/ExtendedGameStateController.cs | 35 ++----------------- .../Extensions/ExtendedPlayerReady.cs | 27 -------------- .../Extensions/ExtendedPlayersDataModel.cs | 25 ++----------- 3 files changed, 5 insertions(+), 82 deletions(-) delete mode 100644 MultiplayerExtensions/Extensions/ExtendedPlayerReady.cs diff --git a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs index aa33896..bc66572 100644 --- a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs +++ b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs @@ -25,7 +25,6 @@ public override void Activate() base.Activate(); (this as ILobbyGameStateController).lobbyStateChangedEvent += this.HandleLobbyStateChanged; - _lobbyPlayersDataModel.didChangeEvent += this.HandleDataModelChanged; } public override void Deactivate() @@ -38,7 +37,6 @@ public override void Deactivate() base.Deactivate(); (this as ILobbyGameStateController).lobbyStateChangedEvent -= this.HandleLobbyStateChanged; - _lobbyPlayersDataModel.didChangeEvent -= this.HandleDataModelChanged; } public override void Dispose() @@ -76,24 +74,6 @@ public override void StopListeningToGameStart() - private void HandleDataModelChanged(string userId) - { - if (state == MultiplayerLobbyState.GameStarting) - { - ILobbyPlayerData partyOwnerData = _lobbyPlayersDataModel.GetLobbyPlayerDataModel(_lobbyPlayersDataModel.partyOwnerId); - if (partyOwnerData.isReady) - { - PredictCountdownEndTime(); - HandleMenuRpcManagerStartedLevel(_lobbyPlayersDataModel.partyOwnerId, new BeatmapIdentifierNetSerializable(partyOwnerData.beatmapLevel.levelID, partyOwnerData.beatmapCharacteristic.serializedName, partyOwnerData.beatmapDifficulty), partyOwnerData.gameplayModifiers, _predictedStartTime); - } else - { - HandleMenuRpcManagerCancelledLevelStart(_lobbyPlayersDataModel.partyOwnerId); - } - } - } - - - private IPreviewBeatmapLevel? _previewBeatmapLevel; private BeatmapDifficulty _beatmapDifficulty; private BeatmapCharacteristicSO? _beatmapCharacteristic; @@ -102,17 +82,7 @@ private void HandleDataModelChanged(string userId) public override void HandleMenuRpcManagerStartedLevel(string userId, BeatmapIdentifierNetSerializable beatmapId, GameplayModifiers gameplayModifiers, float startTime) { - if (this.levelStartInitiated) - { - if (userId == _sessionManager.connectionOwner.userId) - { - Plugin.Log?.Debug("Server map start initiated"); - base.HandleMultiplayerLevelLoaderCountdownFinished(_previewBeatmapLevel, _beatmapDifficulty, _beatmapCharacteristic, _difficultyBeatmap, _gameplayModifiers); - } - return; - } - - if (_sessionManager.partyOwner != null && state == MultiplayerLobbyState.GameStarting) + if (_sessionManager.partyOwner != null) { ILobbyPlayerData partyOwnerData = _lobbyPlayersDataModel.GetLobbyPlayerDataModel(_sessionManager.partyOwner.userId); beatmapId = new BeatmapIdentifierNetSerializable(partyOwnerData.beatmapLevel.levelID, partyOwnerData.beatmapCharacteristic.serializedName, partyOwnerData.beatmapDifficulty); @@ -172,8 +142,7 @@ private async void HandleEntitlement(string userId, string levelId, Entitlements if (readyStates.All(x => x) && await _entitlementChecker.GetEntitlementStatus(startedBeatmapId.levelID) == EntitlementsStatus.Ok) { Plugin.Log.Debug("All players ready, starting game."); - _menuRpcManager.SetIsReady(true); - //base.HandleMultiplayerLevelLoaderCountdownFinished(_previewBeatmapLevel, _beatmapDifficulty, _beatmapCharacteristic, _difficultyBeatmap, _gameplayModifiers); + base.HandleMultiplayerLevelLoaderCountdownFinished(_previewBeatmapLevel, _beatmapDifficulty, _beatmapCharacteristic, _difficultyBeatmap, _gameplayModifiers); } } } diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayerReady.cs b/MultiplayerExtensions/Extensions/ExtendedPlayerReady.cs deleted file mode 100644 index e26a94e..0000000 --- a/MultiplayerExtensions/Extensions/ExtendedPlayerReady.cs +++ /dev/null @@ -1,27 +0,0 @@ -using LiteNetLib.Utils; - -namespace MultiplayerExtensions.Extensions -{ - class ExtendedPlayerReadyPacket : INetSerializable, IPoolablePacket - { - public void Release() => ThreadStaticPacketPool.pool.Release(this); - - public void Serialize(NetDataWriter writer) - { - writer.Put(ready); - } - - public void Deserialize(NetDataReader reader) - { - this.ready = reader.GetBool(); - } - - public ExtendedPlayerReadyPacket Init(bool ready) - { - this.ready = ready; - return this; - } - - public bool ready; - } -} diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs index 00991dd..afcedb6 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs @@ -13,8 +13,6 @@ class ExtendedPlayersDataModel : LobbyPlayersDataModel, ILobbyPlayersDataModel, protected readonly PacketManager _packetManager; protected readonly ExtendedSessionManager _sessionManager; - private static readonly string PlaceholderSongID = "100Bills"; - internal ExtendedPlayersDataModel(PacketManager packetManager, IMultiplayerSessionManager sessionManager) { _packetManager = packetManager; @@ -26,7 +24,6 @@ public override void Activate() MPEvents.CustomSongsChanged += this.HandleCustomSongsChanged; MPEvents.FreeModChanged += this.HandleFreeModChanged; this._packetManager.RegisterCallback(this.HandlePreviewBeatmapPacket); - this._packetManager.RegisterCallback(this.HandlePlayerReadyPacket); base.Activate(); _menuRpcManager.recommendBeatmapEvent -= base.HandleMenuRpcManagerRecommendBeatmap; @@ -48,7 +45,6 @@ public override void Deactivate() MPEvents.CustomSongsChanged -= HandleCustomSongsChanged; MPEvents.FreeModChanged -= HandleFreeModChanged; this._packetManager.UnregisterCallback(); - this._packetManager.UnregisterCallback(); _menuRpcManager.recommendBeatmapEvent -= this.HandleMenuRpcManagerRecommendBeatmap; _menuRpcManager.recommendBeatmapEvent += base.HandleMenuRpcManagerRecommendBeatmap; @@ -126,13 +122,7 @@ public override void HandleMenuRpcManagerGetRecommendedBeatmap(string userId) { if (lobbyPlayerDataModel.beatmapLevel is PreviewBeatmapStub preview) _packetManager.Send(new PreviewBeatmapPacket(preview, lobbyPlayerDataModel.beatmapCharacteristic.serializedName, lobbyPlayerDataModel.beatmapDifficulty)); - else - { - if (_sessionManager.connectionOwner.HasState("modded")) - this._menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(lobbyPlayerDataModel.beatmapLevel.levelID, lobbyPlayerDataModel.beatmapCharacteristic.serializedName, lobbyPlayerDataModel.beatmapDifficulty)); - else - this._menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(PlaceholderSongID, lobbyPlayerDataModel.beatmapCharacteristic.serializedName, lobbyPlayerDataModel.beatmapDifficulty)); - } + this._menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(lobbyPlayerDataModel.beatmapLevel.levelID, lobbyPlayerDataModel.beatmapCharacteristic.serializedName, lobbyPlayerDataModel.beatmapDifficulty)); } } @@ -193,10 +183,7 @@ public async override void HandleMenuRpcManagerRecommendBeatmap(string userId, B HMMainThreadDispatcher.instance.Enqueue(() => base.SetPlayerBeatmapLevel(base.localUserId, preview, beatmapDifficulty, characteristic)); _packetManager.Send(new PreviewBeatmapPacket(preview!, characteristic.serializedName, beatmapDifficulty)); - if (_sessionManager.connectionOwner.HasState("modded")) - _menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(levelId, characteristic.serializedName, beatmapDifficulty)); - else - _menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(PlaceholderSongID, characteristic.serializedName, beatmapDifficulty)); + _menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(levelId, characteristic.serializedName, beatmapDifficulty)); } }else base.SetLocalPlayerBeatmapLevel(levelId, beatmapDifficulty, characteristic); @@ -249,11 +236,6 @@ public override void HandleMenuRpcManagerSetPlayersPermissionConfiguration(strin _sessionManager.partyOwner = _sessionManager.GetPlayerByUserId(partyOwnerId); } - private void HandlePlayerReadyPacket(ExtendedPlayerReadyPacket packet, IConnectedPlayer player) - { - base.SetPlayerIsReady(player.userId, packet.ready, true); - } - public override void SetLocalPlayerIsReady(bool isReady) { this.SetLocalPlayerIsReady(isReady, true); @@ -275,8 +257,7 @@ public override void SetLocalPlayerIsReady(bool isReady, bool notifyChange) this.NotifyModelChange(this.localUserId); } - _packetManager.Send(new ExtendedPlayerReadyPacket().Init(isReady)); - base.SetPlayerIsReady(this.localUserId, isReady, notifyChange); + base.SetLocalPlayerIsReady(isReady, notifyChange); } /// From a74d00aaa960665b07ff72adc92a097136eb9262 Mon Sep 17 00:00:00 2001 From: MT Date: Mon, 23 Aug 2021 15:42:34 -0400 Subject: [PATCH 14/41] disable custom songs --- MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs index 281bbde..23c50a0 100644 --- a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs +++ b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs @@ -22,7 +22,7 @@ public static class HarmonyManager static HarmonyManager() { AddDefaultPatch(); - AddDefaultPatch(); + //AddDefaultPatch(); (disabled for official) AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); From facfad64c11e2632d74ba238a526ff156b03e113 Mon Sep 17 00:00:00 2001 From: MT Date: Wed, 25 Aug 2021 10:00:28 -0400 Subject: [PATCH 15/41] beatsaver and entitlement fix --- MultiplayerExtensions/Downloader.cs | 3 ++- MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/MultiplayerExtensions/Downloader.cs b/MultiplayerExtensions/Downloader.cs index 5385aae..d74baac 100644 --- a/MultiplayerExtensions/Downloader.cs +++ b/MultiplayerExtensions/Downloader.cs @@ -6,6 +6,7 @@ using System.Collections.Concurrent; using System.Diagnostics; using BeatSaverSharp.Models; +using System.Linq; #nullable enable namespace MultiplayerExtensions @@ -43,7 +44,7 @@ public static bool TryGetDownload(string levelId, out Task version.Hash == hash).DownloadZIP(); #if DEBUG TimeSpan delay = TimeSpan.FromSeconds(Plugin.Config.DebugConfig?.MinDownloadTime ?? 0) - TimeSpan.FromMilliseconds(sw.ElapsedMilliseconds); if (delay > TimeSpan.Zero) diff --git a/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs b/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs index fac3edf..98ca5ce 100644 --- a/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs +++ b/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs @@ -98,7 +98,8 @@ public Task GetUserEntitlementStatus(string userId, string l if (!_tcsDictionary.ContainsKey(userId)) _tcsDictionary[userId] = new Dictionary>(); - _tcsDictionary[userId][levelId] = new TaskCompletionSource(); + if (!_tcsDictionary[userId].ContainsKey(levelId)) + _tcsDictionary[userId][levelId] = new TaskCompletionSource(); _rpcManager.GetIsEntitledToLevel(levelId); return _tcsDictionary[userId][levelId].Task; } From eb8fb3eaff0f51f2e7de35f51963390f2f6929bb Mon Sep 17 00:00:00 2001 From: MT Date: Wed, 25 Aug 2021 10:05:56 -0400 Subject: [PATCH 16/41] update manifest --- MultiplayerExtensions/manifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MultiplayerExtensions/manifest.json b/MultiplayerExtensions/manifest.json index d0000a5..7670ebb 100644 --- a/MultiplayerExtensions/manifest.json +++ b/MultiplayerExtensions/manifest.json @@ -5,11 +5,11 @@ "author": "Zingabopp and Goobwabber", "version": "0.6.0", "description": "Expands the functionality of Beat Saber Multiplayer.", - "gameVersion": "1.16.3", + "gameVersion": "1.16.4", "dependsOn": { "BSIPA": "^4.1.4", "SongCore": "^3.2.0", - "BeatSaverSharp": "^2.0.1", + "BeatSaverSharp": "^3.0.1", "BeatSaberMarkupLanguage": "^1.5.1", "SiraUtil": "^2.5.2" }, From 30858d11971ff2953751bc37e4679cbabdc43410 Mon Sep 17 00:00:00 2001 From: MT Date: Fri, 10 Sep 2021 19:15:20 -0400 Subject: [PATCH 17/41] 1.17.1 build --- .../Extensions/ExtendedPlayersDataModel.cs | 2 +- MultiplayerExtensions/Extensions/ExtendedSessionManager.cs | 7 +++++++ MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs | 3 ++- MultiplayerExtensions/MultiplayerExtensions.csproj | 2 +- MultiplayerExtensions/manifest.json | 4 ++-- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs index afcedb6..f20d6f3 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs @@ -154,7 +154,7 @@ public async override void HandleMenuRpcManagerRecommendBeatmap(string userId, B } } else - return; //base.HandleMenuRpcManagerRecommendBeatmap(userId, beatmapId); + base.HandleMenuRpcManagerRecommendBeatmap(userId, beatmapId); } /// diff --git a/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs b/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs index 4075847..a001a6f 100644 --- a/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs +++ b/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs @@ -42,6 +42,8 @@ internal void Inject([InjectOptional] PacketManager packetManager, [InjectOption SetLocalPlayerState("freemod", Plugin.Config.FreeMod); SetLocalPlayerState("hostpick", Plugin.Config.HostPick); + connectedEvent += HandleConnected; + playerStateChangedEvent += HandlePlayerStateChanged; playerConnectedEvent += HandlePlayerConnected; @@ -74,6 +76,11 @@ internal void Inject([InjectOptional] PacketManager packetManager, [InjectOption base.EndSession(); } + private void HandleConnected() + { + Plugin.Log?.Info($"Connected to lobby."); + } + private void HandlePlayerConnected(IConnectedPlayer player) { Plugin.Log?.Info($"Player '{player.userId}' joined"); diff --git a/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs b/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs index 95e5f85..e357a29 100644 --- a/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs @@ -17,7 +17,8 @@ internal class CreatePartyPatch /// static void Prefix(CreateServerFormData data) { - data.songPacks = SongPackMask.all | new SongPackMask("custom_levelpack_CustomLevels"); + if (!MPState.CurrentMasterServer.isOfficial) + data.songPacks = SongPackMask.all | new SongPackMask("custom_levelpack_CustomLevels"); } } diff --git a/MultiplayerExtensions/MultiplayerExtensions.csproj b/MultiplayerExtensions/MultiplayerExtensions.csproj index 0ca2fb8..b2d4385 100644 --- a/MultiplayerExtensions/MultiplayerExtensions.csproj +++ b/MultiplayerExtensions/MultiplayerExtensions.csproj @@ -4,7 +4,7 @@ Library Properties MultiplayerExtensions - 0.6.0 + 0.6.1 net472 true portable diff --git a/MultiplayerExtensions/manifest.json b/MultiplayerExtensions/manifest.json index 7670ebb..af15bce 100644 --- a/MultiplayerExtensions/manifest.json +++ b/MultiplayerExtensions/manifest.json @@ -3,9 +3,9 @@ "id": "MultiplayerExtensions", "name": "MultiplayerExtensions", "author": "Zingabopp and Goobwabber", - "version": "0.6.0", + "version": "0.6.1", "description": "Expands the functionality of Beat Saber Multiplayer.", - "gameVersion": "1.16.4", + "gameVersion": "1.17.1", "dependsOn": { "BSIPA": "^4.1.4", "SongCore": "^3.2.0", From 76dbf6bf8a6cd889ba1cce1ce689779ba0635e6c Mon Sep 17 00:00:00 2001 From: MT Date: Sat, 11 Sep 2021 22:38:51 -0400 Subject: [PATCH 18/41] fix lobby host crap --- MultiplayerExtensions/Extensions/ExtendedSessionManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs b/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs index a001a6f..f902922 100644 --- a/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs +++ b/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs @@ -150,6 +150,8 @@ private void HandlePlayerStateChanged(IConnectedPlayer player) public ExtendedPlayer? GetExtendedPlayer(string userId) { + if (localExtendedPlayer.userId == userId) + return localExtendedPlayer; if (_extendedPlayers.TryGetValue(userId, out ExtendedPlayer extendedPlayer)) return extendedPlayer; return null; From 8fd3f1d7f194325f0968e3ece1aaab7f87b1320f Mon Sep 17 00:00:00 2001 From: MT Date: Sun, 12 Sep 2021 16:25:18 -0400 Subject: [PATCH 19/41] fix some stuff --- .../Extensions/ExtendedGameStateController.cs | 16 +++++----- .../Extensions/ExtendedPlayersDataModel.cs | 30 +++++++++++++------ 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs index bc66572..c29bfa7 100644 --- a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs +++ b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs @@ -82,14 +82,8 @@ public override void StopListeningToGameStart() public override void HandleMenuRpcManagerStartedLevel(string userId, BeatmapIdentifierNetSerializable beatmapId, GameplayModifiers gameplayModifiers, float startTime) { - if (_sessionManager.partyOwner != null) - { - ILobbyPlayerData partyOwnerData = _lobbyPlayersDataModel.GetLobbyPlayerDataModel(_sessionManager.partyOwner.userId); - beatmapId = new BeatmapIdentifierNetSerializable(partyOwnerData.beatmapLevel.levelID, partyOwnerData.beatmapCharacteristic.serializedName, partyOwnerData.beatmapDifficulty); - - if (_sessionManager.partyOwner.HasState("freemod")) - gameplayModifiers = _lobbyPlayersDataModel.GetPlayerGameplayModifiers(_lobbyPlayersDataModel.localUserId); - } + if (_sessionManager.partyOwner != null && _sessionManager.partyOwner.HasState("freemod")) + gameplayModifiers = _lobbyPlayersDataModel.GetPlayerGameplayModifiers(_lobbyPlayersDataModel.localUserId); base.HandleMenuRpcManagerStartedLevel(userId, beatmapId, gameplayModifiers, startTime); _multiplayerLevelLoader.countdownFinishedEvent -= base.HandleMultiplayerLevelLoaderCountdownFinished; @@ -137,6 +131,12 @@ private async void HandleEntitlement(string userId, string levelId, Entitlements { if (state == MultiplayerLobbyState.GameStarting) { + if (_levelStartedOnTime == false) + { + Plugin.Log.Debug("Loaded level late, starting game."); + base.HandleMultiplayerLevelLoaderCountdownFinished(_previewBeatmapLevel, _beatmapDifficulty, _beatmapCharacteristic, _difficultyBeatmap, _gameplayModifiers); + } + IEnumerable> readyTasks = _sessionManager.connectedPlayers.Select(IsPlayerReady); bool[] readyStates = await Task.WhenAll(readyTasks); if (readyStates.All(x => x) && await _entitlementChecker.GetEntitlementStatus(startedBeatmapId.levelID) == EntitlementsStatus.Ok) diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs index f20d6f3..adfbcd1 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs @@ -1,4 +1,4 @@ -using BeatSaverSharp.Models; +using BeatSaverSharp.Models; using MultiplayerExtensions.Beatmaps; using MultiplayerExtensions.Packets; using System; @@ -217,19 +217,31 @@ public override void HandleMenuRpcManagerClearRecommendedGameplayModifiers(strin } } - public override void HandleMenuRpcManagerSetPlayersPermissionConfiguration(string userId, PlayersLobbyPermissionConfigurationNetSerializable playersLobbyPermissionConfiguration) + public override void HandleMenuRpcManagerSetPlayersPermissionConfiguration(string userId, PlayersLobbyPermissionConfigurationNetSerializable permissionConfiguration) { - foreach (PlayerLobbyPermissionConfigurationNetSerializable playerLobbyPermissionConfigurationNetSerializable in playersLobbyPermissionConfiguration.playersPermission) + foreach (PlayerLobbyPermissionConfigurationNetSerializable playerPermission in permissionConfiguration.playersPermission) { - ExtendedPlayer? player = _sessionManager.GetExtendedPlayer(playerLobbyPermissionConfigurationNetSerializable.userId); + Plugin.Log?.Info($"Processing PermissionConfiguration for '{playerPermission.userId}'"); + + ExtendedPlayer? player = _sessionManager.GetExtendedPlayer(playerPermission.userId); if (player != null) { - player.isPartyOwner = playerLobbyPermissionConfigurationNetSerializable.isServerOwner; - player.hasRecommendBeatmapPermission = playerLobbyPermissionConfigurationNetSerializable.hasRecommendBeatmapsPermission; - player.hasRecommendModifiersPermission = playerLobbyPermissionConfigurationNetSerializable.hasRecommendGameplayModifiersPermission; - player.hasKickVotePermission = playerLobbyPermissionConfigurationNetSerializable.hasKickVotePermission; + player.isPartyOwner = playerPermission.isServerOwner; + player.hasRecommendBeatmapPermission = playerPermission.hasRecommendBeatmapsPermission; + player.hasRecommendModifiersPermission = playerPermission.hasRecommendGameplayModifiersPermission; + player.hasKickVotePermission = playerPermission.hasKickVotePermission; } - this.SetPlayerIsPartyOwner(playerLobbyPermissionConfigurationNetSerializable.userId, playerLobbyPermissionConfigurationNetSerializable.isServerOwner, true); + + // Base game is bugged and this method is fucked + // this.SetPlayerIsPartyOwner(playerPermission.userId, playerPermission.isServerOwner, true); + ILobbyPlayerData lobbyPlayerData = this.GetOrCreateLobbyPlayerDataModel(playerPermission.userId, out bool alreadyExists); + if (playerPermission.isServerOwner) + this.SetPlayerIsPartyOwner(playerPermission.userId, playerPermission.isServerOwner, true); + else if (lobbyPlayerData.isPartyOwner != playerPermission.isServerOwner) + { + lobbyPlayerData.isPartyOwner = playerPermission.isServerOwner; + this.NotifyModelChange(playerPermission.userId); + } } MPState.LocalPlayerIsHost = localUserId == partyOwnerId; From b2c505dfaebbc7b101aaad178787f11761f5487f Mon Sep 17 00:00:00 2001 From: MT Date: Sun, 12 Sep 2021 17:03:54 -0400 Subject: [PATCH 20/41] fix downloader issue --- MultiplayerExtensions/Downloader.cs | 7 ++++++- .../Extensions/ExtendedPlayersDataModel.cs | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/MultiplayerExtensions/Downloader.cs b/MultiplayerExtensions/Downloader.cs index d74baac..9d713aa 100644 --- a/MultiplayerExtensions/Downloader.cs +++ b/MultiplayerExtensions/Downloader.cs @@ -44,7 +44,12 @@ public static bool TryGetDownload(string levelId, out Task version.Hash == hash).DownloadZIP(); + + Plugin.Log?.Info($"Target hash: '{hash}'"); + byte[]? beatmapBytes = await bm.Versions.ToList().Find(version => { + Plugin.Log?.Info($"Version: '{version.Key}' '{version.Hash}'"); + return version.Hash.ToUpper() == hash; + }).DownloadZIP(); #if DEBUG TimeSpan delay = TimeSpan.FromSeconds(Plugin.Config.DebugConfig?.MinDownloadTime ?? 0) - TimeSpan.FromMilliseconds(sw.ElapsedMilliseconds); if (delay > TimeSpan.Zero) diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs index adfbcd1..a15fee0 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs @@ -182,8 +182,8 @@ public async override void HandleMenuRpcManagerRecommendBeatmap(string userId, B preview = await FetchBeatSaverPreview(levelId, hash); HMMainThreadDispatcher.instance.Enqueue(() => base.SetPlayerBeatmapLevel(base.localUserId, preview, beatmapDifficulty, characteristic)); - _packetManager.Send(new PreviewBeatmapPacket(preview!, characteristic.serializedName, beatmapDifficulty)); _menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(levelId, characteristic.serializedName, beatmapDifficulty)); + _packetManager.Send(new PreviewBeatmapPacket(preview!, characteristic.serializedName, beatmapDifficulty)); } }else base.SetLocalPlayerBeatmapLevel(levelId, beatmapDifficulty, characteristic); From 67c818b4c8975c34bafdf456b5fbded2a467e9d0 Mon Sep 17 00:00:00 2001 From: MT Date: Mon, 13 Sep 2021 14:56:20 -0400 Subject: [PATCH 21/41] Yeeted old stuff - Deleted Custom Songs State - Deleted Free Mod - Deleted Host Pick - Deleted Statistics --- .../Extensions/ExtendedPlayer.cs | 2 - .../Extensions/ExtendedPlayersDataModel.cs | 75 ---------------- .../Extensions/ExtendedSessionManager.cs | 32 ------- .../HarmonyPatches/CustomSongsPatches.cs | 38 +-------- .../HarmonyPatches/EnvironmentPatches.cs | 2 +- .../HarmonyPatches/InstallerPatches.cs | 20 +---- .../{LoggingPatch.cs => LoggingPatches.cs} | 4 +- MultiplayerExtensions/MPEvents.cs | 21 ----- MultiplayerExtensions/MPState.cs | 47 ---------- MultiplayerExtensions/Plugin.cs | 1 - MultiplayerExtensions/UI/LobbySetupPanel.bsml | 3 +- MultiplayerExtensions/UI/LobbySetupPanel.cs | 85 ------------------- MultiplayerExtensions/UI/MPSettings.cs | 10 --- MultiplayerExtensions/Utilities/Config.cs | 4 - .../Utilities/Harmony/HarmonyManager.cs | 4 +- MultiplayerExtensions/Utilities/Statistics.cs | 81 ------------------ 16 files changed, 7 insertions(+), 422 deletions(-) rename MultiplayerExtensions/HarmonyPatches/{LoggingPatch.cs => LoggingPatches.cs} (97%) delete mode 100644 MultiplayerExtensions/Utilities/Statistics.cs diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayer.cs b/MultiplayerExtensions/Extensions/ExtendedPlayer.cs index 7460dab..7c2e6c1 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayer.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayer.cs @@ -29,8 +29,6 @@ public class ExtendedPlayer : IConnectedPlayer /// public Color playerColor; - internal GameplayModifiers? lastModifiers; - public bool isPartyOwner { get; internal set; } public bool hasRecommendBeatmapPermission { get; internal set; } public bool hasRecommendModifiersPermission { get; internal set; } diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs index a15fee0..41a409e 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs @@ -21,8 +21,6 @@ internal ExtendedPlayersDataModel(PacketManager packetManager, IMultiplayerSessi public override void Activate() { - MPEvents.CustomSongsChanged += this.HandleCustomSongsChanged; - MPEvents.FreeModChanged += this.HandleFreeModChanged; this._packetManager.RegisterCallback(this.HandlePreviewBeatmapPacket); base.Activate(); @@ -42,8 +40,6 @@ public override void Activate() public override void Deactivate() { - MPEvents.CustomSongsChanged -= HandleCustomSongsChanged; - MPEvents.FreeModChanged -= HandleFreeModChanged; this._packetManager.UnregisterCallback(); _menuRpcManager.recommendBeatmapEvent -= this.HandleMenuRpcManagerRecommendBeatmap; @@ -67,25 +63,6 @@ public override void Deactivate() this.Deactivate(); } - private void HandleCustomSongsChanged(object sender, bool value) - { - if (!value && GetPlayerBeatmapLevel(localUserId) is PreviewBeatmapStub) - { - base.ClearLocalPlayerBeatmapLevel(); - } - } - - private void HandleFreeModChanged(object sender, bool value) - { - if (value && localUserId != partyOwnerId) - { - GameplayModifiers localModifiers = GetPlayerGameplayModifiers(localUserId); - GameplayModifiers hostModifiers = GetPlayerGameplayModifiers(partyOwnerId); - if (localModifiers.songSpeed != hostModifiers.songSpeed) - base.SetLocalPlayerGameplayModifiers(localModifiers.CopyWith(songSpeed: hostModifiers.songSpeed)); - } - } - /// /// Handles a used to transmit data about a custom song. /// @@ -189,34 +166,6 @@ public async override void HandleMenuRpcManagerRecommendBeatmap(string userId, B base.SetLocalPlayerBeatmapLevel(levelId, beatmapDifficulty, characteristic); } - public override void HandleMenuRpcManagerRecommendGameplayModifiers(string userId, GameplayModifiers gameplayModifiers) - { - ExtendedPlayer? player = _sessionManager.GetExtendedPlayer(userId); - if (player != null) - player.lastModifiers = gameplayModifiers; - base.HandleMenuRpcManagerRecommendGameplayModifiers(userId, gameplayModifiers); - if (userId == partyOwnerId && MPState.FreeModEnabled) - { - GameplayModifiers localModifiers = GetPlayerGameplayModifiers(localUserId); - if (localModifiers.songSpeed != gameplayModifiers.songSpeed) - base.SetLocalPlayerGameplayModifiers(localModifiers.CopyWith(songSpeed: gameplayModifiers.songSpeed)); - } - } - - public override void HandleMenuRpcManagerClearRecommendedGameplayModifiers(string userId) - { - ExtendedPlayer? player = _sessionManager.GetExtendedPlayer(userId); - if (player != null) - player.lastModifiers = null; - base.HandleMenuRpcManagerClearRecommendedGameplayModifiers(userId); - if (userId == partyOwnerId && MPState.FreeModEnabled) - { - GameplayModifiers localModifiers = GetPlayerGameplayModifiers(localUserId); - if (localModifiers.songSpeed != GameplayModifiers.SongSpeed.Normal) - base.SetLocalPlayerGameplayModifiers(localModifiers.CopyWith(songSpeed: GameplayModifiers.SongSpeed.Normal)); - } - } - public override void HandleMenuRpcManagerSetPlayersPermissionConfiguration(string userId, PlayersLobbyPermissionConfigurationNetSerializable permissionConfiguration) { foreach (PlayerLobbyPermissionConfigurationNetSerializable playerPermission in permissionConfiguration.playersPermission) @@ -248,30 +197,6 @@ public override void HandleMenuRpcManagerSetPlayersPermissionConfiguration(strin _sessionManager.partyOwner = _sessionManager.GetPlayerByUserId(partyOwnerId); } - public override void SetLocalPlayerIsReady(bool isReady) - { - this.SetLocalPlayerIsReady(isReady, true); - } - - public override void SetLocalPlayerIsReady(bool isReady, bool notifyChange) - { - if (!Plugin.Config.HostPick && this.localUserId == this.partyOwnerId) - { - ILobbyPlayerData localPlayerDataModel = this.GetLobbyPlayerDataModel(localUserId); - IEnumerable validDataModels = this.playersData.Values.Where(data => data.beatmapLevel != null); - ILobbyPlayerData chosenPlayerDataModel = validDataModels.ElementAt(new Random().Next(0, validDataModels.Count())); - localPlayerDataModel.beatmapLevel = chosenPlayerDataModel.beatmapLevel; - localPlayerDataModel.beatmapDifficulty = chosenPlayerDataModel.beatmapDifficulty; - localPlayerDataModel.beatmapCharacteristic = chosenPlayerDataModel.beatmapCharacteristic; - localPlayerDataModel.gameplayModifiers = chosenPlayerDataModel.gameplayModifiers; - this._menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(chosenPlayerDataModel.beatmapLevel.levelID, chosenPlayerDataModel.beatmapCharacteristic.serializedName, chosenPlayerDataModel.beatmapDifficulty)); - this._menuRpcManager.RecommendGameplayModifiers(chosenPlayerDataModel.gameplayModifiers); - this.NotifyModelChange(this.localUserId); - } - - base.SetLocalPlayerIsReady(isReady, notifyChange); - } - /// /// Used to raise the event. /// diff --git a/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs b/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs index f902922..8249d4b 100644 --- a/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs +++ b/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs @@ -35,17 +35,10 @@ internal void Inject([InjectOptional] PacketManager packetManager, [InjectOption localExtendedPlayer = new ExtendedPlayer(localPlayer); - MPState.FreeModEnabled = Plugin.Config.FreeMod; - MPState.HostPickEnabled = Plugin.Config.HostPick; - SetLocalPlayerState("modded", true); - SetLocalPlayerState("freemod", Plugin.Config.FreeMod); - SetLocalPlayerState("hostpick", Plugin.Config.HostPick); connectedEvent += HandleConnected; - playerStateChangedEvent += HandlePlayerStateChanged; - playerConnectedEvent += HandlePlayerConnected; playerDisconnectedEvent += HandlePlayerDisconnected; _packetManager.RegisterCallback(HandleExtendedPlayerPacket); @@ -57,18 +50,11 @@ internal void Inject([InjectOptional] PacketManager packetManager, [InjectOption { localExtendedPlayer.platformID = r.Result.platformUserId; localExtendedPlayer.platform = r.Result.platform.ToPlatform(); - - if (Plugin.Config.Statistics) - { - _ = Statistics.AddUser(localExtendedPlayer.platformID, (int)localExtendedPlayer.platform); - } }); } public new void EndSession() { - playerStateChangedEvent -= HandlePlayerStateChanged; - playerConnectedEvent -= HandlePlayerConnected; playerDisconnectedEvent -= HandlePlayerDisconnected; _packetManager.UnregisterCallback(); @@ -127,24 +113,6 @@ private void HandleExtendedPlayerPacket(ExtendedPlayerPacket packet, IConnectedP } } - private void HandlePlayerStateChanged(IConnectedPlayer player) - { - if (player.isConnectionOwner) - { - if (MPState.CustomSongsEnabled != player.HasState("customsongs")) - { - MPState.CustomSongsEnabled = player.HasState("customsongs"); - MPEvents.RaiseCustomSongsChanged(this, player.HasState("customsongs")); - } - - if (MPState.FreeModEnabled != player.HasState("freemod")) - { - MPState.FreeModEnabled = player.HasState("freemod"); - MPEvents.RaiseCustomSongsChanged(this, player.HasState("freemod")); - } - } - } - public ExtendedPlayer? GetExtendedPlayer(IConnectedPlayer player) => GetExtendedPlayer(player.userId); diff --git a/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs b/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs index e357a29..2329c3b 100644 --- a/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs @@ -39,7 +39,7 @@ static bool Prefix(ref bool __result, SongPackMask ____songPackMask) internal class GameServerDidActivatePatch { /// - /// Does stuff as soon as the lobby is loaded. + /// Check if lobby supports custom songs. /// static void Postfix(IUnifiedNetworkPlayerModel ____unifiedNetworkPlayerModel) { @@ -56,41 +56,7 @@ internal class MissingLevelStartPatch static void Prefix(LobbySetupViewController __instance, string playersMissingLevelText, ref Button ____startGameReadyButton) { if (____startGameReadyButton.interactable) - __instance.SetStartGameEnabled(CannotStartGameReason.None); - } - } - - [HarmonyPatch(typeof(CenterStageScreenController), nameof(CenterStageScreenController.HandleLobbyPlayersDataModelDidChange), MethodType.Normal)] - internal class CenterStageGameDataPatch - { - /// - /// Replaces selected gameplay modifiers if freemod is enabled. - /// - static void Postfix(string userId, ref ILobbyPlayersDataModel ____lobbyPlayersDataModel, ref ModifiersSelectionView ____modifiersSelectionView) - { - if (userId == ____lobbyPlayersDataModel.localUserId && MPState.FreeModEnabled) - { - GameplayModifiers gameplayModifiers = ____lobbyPlayersDataModel.GetPlayerGameplayModifiers(userId); - if (gameplayModifiers != null) - ____modifiersSelectionView.SetGameplayModifiers(gameplayModifiers); - } - } - } - - [HarmonyPatch(typeof(GameplayModifiersPanelController), nameof(GameplayModifiersPanelController.RefreshTotalMultiplierAndRankUI), MethodType.Normal)] - internal class DisableSpeedModifiersPatch - { - static void Postfix(ref GameplayModifierToggle[] ____gameplayModifierToggles) - { - //foreach(GameplayModifierToggle toggle in ____gameplayModifierToggles) - //{ - // Plugin.Log.Warn(toggle.gameplayModifier.modifierNameLocalizationKey); - //} - - bool speedModsEnabled = !MPState.FreeModEnabled || MPState.LocalPlayerIsHost; - ____gameplayModifierToggles.ToList().Find(toggle => toggle.gameplayModifier.modifierNameLocalizationKey == "MODIFIER_SUPER_FAST_SONG").toggle.interactable = speedModsEnabled; - ____gameplayModifierToggles.ToList().Find(toggle => toggle.gameplayModifier.modifierNameLocalizationKey == "MODIFIER_FASTER_SONG").toggle.interactable = speedModsEnabled; - ____gameplayModifierToggles.ToList().Find(toggle => toggle.gameplayModifier.modifierNameLocalizationKey == "MODIFIER_SLOWER_SONG").toggle.interactable = speedModsEnabled; + __instance.SetStartGameEnabled(CannotStartGameReason.DoNotOwnSong); } } diff --git a/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs b/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs index ce724c6..b278bb9 100644 --- a/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs @@ -171,7 +171,7 @@ static IEnumerable Transpiler(IEnumerable inst private static void SetInteractableAttacher(Selectable contract, bool value) { - contract.interactable = true; + contract.interactable = !MPState.CurrentMasterServer.isOfficial ? true : value; } } } diff --git a/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs b/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs index 9f4258c..41a0b30 100644 --- a/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs @@ -140,30 +140,12 @@ private static FromBinderNonGeneric LevelLoaderAttacher(DiContainer contract) [HarmonyPatch(typeof(MultiplayerConnectedPlayerInstaller), nameof(MultiplayerConnectedPlayerInstaller.InstallBindings))] internal class ConnectedPlayerInstallerPatch { - private static readonly SemVer.Version _minVersionFreeMod = new SemVer.Version("0.4.6"); - internal static void Prefix(ref GameplayCoreInstaller __instance, ref IConnectedPlayer ____connectedPlayer, ref GameplayCoreSceneSetupData ____sceneSetupData) { - var mib = __instance as MonoInstallerBase; - var Container = SiraUtil.Accessors.GetDiContainer(ref mib); - - ExtendedSessionManager sessionManager = (Container.Resolve() as ExtendedSessionManager)!; - ExtendedPlayer? exPlayer = sessionManager.GetExtendedPlayer(____connectedPlayer); - ExtendedPlayer? hostPlayer = sessionManager.GetExtendedPlayer(sessionManager.partyOwner); - - GameplayModifiers? newModifiers; - if (____connectedPlayer.HasState("modded") && MPState.FreeModEnabled && exPlayer?.mpexVersion >= _minVersionFreeMod) - newModifiers = exPlayer.lastModifiers; - else - newModifiers = hostPlayer?.lastModifiers; - - if (newModifiers == null) - newModifiers = ____sceneSetupData.gameplayModifiers; - ____sceneSetupData = new GameplayCoreSceneSetupData( ____sceneSetupData.difficultyBeatmap, ____sceneSetupData.previewBeatmapLevel, - newModifiers.CopyWith(zenMode: Plugin.Config.LagReducer), + ____sceneSetupData.gameplayModifiers.CopyWith(zenMode: Plugin.Config.LagReducer), ____sceneSetupData.playerSpecificSettings, ____sceneSetupData.practiceSettings, ____sceneSetupData.useTestNoteCutSoundEffects, diff --git a/MultiplayerExtensions/HarmonyPatches/LoggingPatch.cs b/MultiplayerExtensions/HarmonyPatches/LoggingPatches.cs similarity index 97% rename from MultiplayerExtensions/HarmonyPatches/LoggingPatch.cs rename to MultiplayerExtensions/HarmonyPatches/LoggingPatches.cs index d4543f7..1f79462 100644 --- a/MultiplayerExtensions/HarmonyPatches/LoggingPatch.cs +++ b/MultiplayerExtensions/HarmonyPatches/LoggingPatches.cs @@ -12,7 +12,7 @@ namespace MultiplayerExtensions.HarmonyPatches { [HarmonyPatch(typeof(ConnectedPlayerManager), "OnNetworkReceive", new Type[] { typeof(IConnection), typeof(NetDataReader), typeof(DeliveryMethod) })] - class LoggingPatch + class PacketErrorLoggingPatch { private static readonly MethodInfo _exceptionLogger = SymbolExtensions.GetMethodInfo(() => ExceptionLogger((IConnectedPlayer)null!, (Exception)null!)); private static ConcurrentDictionary PlayerExceptions = new ConcurrentDictionary(); @@ -20,8 +20,6 @@ static IEnumerable Transpiler(IEnumerable inst { if (_exceptionLogger == null) Plugin.Log?.Error($"Couldn't find _exceptionLogger"); - else - Plugin.Log?.Warn($"Applying transpiler."); LocalBuilder? localException = gen.DeclareLocal(typeof(Exception)); localException.SetLocalSymInfo("ex"); foreach (CodeInstruction? code in instructions) diff --git a/MultiplayerExtensions/MPEvents.cs b/MultiplayerExtensions/MPEvents.cs index e01a1c9..fc15c2a 100644 --- a/MultiplayerExtensions/MPEvents.cs +++ b/MultiplayerExtensions/MPEvents.cs @@ -36,21 +36,6 @@ public static class MPEvents /// public static event EventHandler? GameStateChanged; - /// - /// Raised when the host toggles custom songs. - /// - public static event EventHandler? CustomSongsChanged; - - /// - /// Raised when the host toggles free mod. - /// - public static event EventHandler? FreeModChanged; - - /// - /// Raised when the host toggles host pick. - /// - public static event EventHandler? HostPickChanged; - internal static void RaiseMasterServerChanged(object sender, MasterServerInfo info) => MasterServerChanged?.RaiseEventSafe(sender, info, nameof(MasterServerChanged)); internal static void RaiseRoomCodeChanged(object sender, string code) @@ -63,12 +48,6 @@ internal static void RaiseLobbyAvatarCreated(object sender, IConnectedPlayer sta => LobbyAvatarCreated.RaiseEventSafe(sender, state, nameof(LobbyAvatarCreated)); internal static void RaiseGameStateChanged(object sender, MultiplayerGameState state) => GameStateChanged.RaiseEventSafe(sender, state, nameof(GameStateChanged)); - internal static void RaiseCustomSongsChanged(object sender, bool state) - => CustomSongsChanged.RaiseEventSafe(sender, state, nameof(CustomSongsChanged)); - internal static void RaiseFreeModChanged(object sender, bool state) - => FreeModChanged.RaiseEventSafe(sender, state, nameof(FreeModChanged)); - internal static void RaiseHostPickChanged(object sender, bool state) - => HostPickChanged.RaiseEventSafe(sender, state, nameof(HostPickChanged)); } public class SelectedBeatmapEventArgs : EventArgs diff --git a/MultiplayerExtensions/MPState.cs b/MultiplayerExtensions/MPState.cs index 655cc15..6604ce0 100644 --- a/MultiplayerExtensions/MPState.cs +++ b/MultiplayerExtensions/MPState.cs @@ -66,21 +66,6 @@ internal set } } - private static bool _lobbyIsModded; - /// - /// Whether the current lobby is custom (true) or official (false). - /// - public static bool LobbyIsModded - { - get => _lobbyIsModded; - internal set - { - if (_lobbyIsModded == value) - return; - _lobbyIsModded = value; - } - } - private static bool _customSongsEnabled; /// /// Whether custom songs are enabled in the current lobby. @@ -97,38 +82,6 @@ internal set } } - private static bool _freeModEnabled; - /// - /// Whether free mod is enabled in the current lobby. - /// - public static bool FreeModEnabled - { - get => _freeModEnabled; - internal set - { - if (_freeModEnabled == value) - return; - _freeModEnabled = value; - Plugin.Log?.Debug($"Updated free mod to '{value}'"); - } - } - - private static bool _hostPickEnabled; - /// - /// Whether host pick is enabled in the current lobby. - /// - public static bool HostPickEnabled - { - get => _hostPickEnabled; - internal set - { - if (_hostPickEnabled == value) - return; - _hostPickEnabled = value; - Plugin.Log?.Debug($"Updated host pick to '{value}'"); - } - } - private static bool _easterEggsEnabled = true; /// /// Whether easter eggs in multiplayer are enabled. diff --git a/MultiplayerExtensions/Plugin.cs b/MultiplayerExtensions/Plugin.cs index d582276..388c55b 100644 --- a/MultiplayerExtensions/Plugin.cs +++ b/MultiplayerExtensions/Plugin.cs @@ -79,7 +79,6 @@ public void OnApplicationStart() BSMLSettings.instance.AddSettingsMenu("Multiplayer", "MultiplayerExtensions.UI.settings.bsml", MPSettings.instance); Plugin.Config.MaxPlayers = Math.Max(Math.Min(Config.MaxPlayers, MaxPlayers), MinPlayers); - MPState.FreeModEnabled = false; HarmonyManager.ApplyDefaultPatches(); Task versionTask = CheckVersion(); diff --git a/MultiplayerExtensions/UI/LobbySetupPanel.bsml b/MultiplayerExtensions/UI/LobbySetupPanel.bsml index 497803d..dc628ec 100644 --- a/MultiplayerExtensions/UI/LobbySetupPanel.bsml +++ b/MultiplayerExtensions/UI/LobbySetupPanel.bsml @@ -1,8 +1,7 @@ - - + diff --git a/MultiplayerExtensions/UI/LobbySetupPanel.cs b/MultiplayerExtensions/UI/LobbySetupPanel.cs index d7f63ab..8a20b0c 100644 --- a/MultiplayerExtensions/UI/LobbySetupPanel.cs +++ b/MultiplayerExtensions/UI/LobbySetupPanel.cs @@ -28,15 +28,9 @@ internal void Inject(IMultiplayerSessionManager sessionManager, LobbyPlayerPermi base.DidActivate(true, false, true); lobbyViewController.didActivateEvent += OnActivate; - _sessionManager.playerStateChangedEvent += HandlePlayerStateChanged; } #region UIComponents - [UIComponent("CustomSongsToggle")] - public ToggleSetting customSongsToggle = null!; - - [UIComponent("FreeModToggle")] - public ToggleSetting freeModToggle = null!; [UIComponent("HostPickToggle")] public ToggleSetting hostPickToggle = null!; @@ -58,36 +52,6 @@ internal void Inject(IMultiplayerSessionManager sessionManager, LobbyPlayerPermi #endregion #region UIValues - [UIValue("FreeMod")] - public bool FreeMod - { - get => _permissionsModel.isPartyOwner ? Plugin.Config.FreeMod : MPState.FreeModEnabled; - set { - if (_permissionsModel.isPartyOwner) - Plugin.Config.FreeMod = value; - if (MPState.FreeModEnabled != value) - { - MPState.FreeModEnabled = value; - MPEvents.RaiseFreeModChanged(this, value); - } - } - } - - [UIValue("HostPick")] - public bool HostPick - { - get => Plugin.Config.HostPick; - set - { - if (_permissionsModel.isPartyOwner) - Plugin.Config.HostPick = value; - if (MPState.HostPickEnabled != value) - { - MPState.HostPickEnabled = value; - MPEvents.RaiseHostPickChanged(this, value); - } - } - } [UIValue("DefaultHUD")] public bool DefaultHUD @@ -126,24 +90,6 @@ public string DownloadProgress #endregion #region UIActions - [UIAction("SetFreeMod")] - public void SetFreeMod(bool value) - { - FreeMod = value; - freeModToggle.Value = value; - - UpdateStates(); - SetModifierText(); - } - - [UIAction("SetHostPick")] - public void SetHostPick(bool value) - { - HostPick = value; - hostPickToggle.Value = value; - - UpdateStates(); - } [UIAction("SetDefaultHUD")] public void SetDefaultHUD(bool value) @@ -179,42 +125,11 @@ public void SetMissLighting(bool value) private void OnActivate(bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling) { - freeModToggle.interactable = _permissionsModel.isPartyOwner; - hostPickToggle.interactable = _permissionsModel.isPartyOwner; - if (firstActivation) { Transform spectatorText = transform.Find("Wrapper").Find("SpectatorModeWarningText"); spectatorText.position = new Vector3(spectatorText.position.x, 0.25f, spectatorText.position.z); } } - - private void HandlePlayerStateChanged(IConnectedPlayer player) - { - ExtendedPlayer? exPlayer = _sessionManager.GetExtendedPlayer(player); - if (exPlayer != null && exPlayer.isPartyOwner) - { - FreeMod = exPlayer.HasState("freemod"); - HostPick = exPlayer.HasState("hostpick"); - } - } - - private void UpdateStates() - { - _sessionManager?.SetLocalPlayerState("freemod", FreeMod); - _sessionManager?.SetLocalPlayerState("hostpick", HostPick); - } - - private void SetModifierText() - { - if (modifierText == null) - { - modifierText = Resources.FindObjectsOfTypeAll().ToList().Find(text => text.gameObject.name == "SuggestedModifiers"); - Destroy(modifierText.gameObject.GetComponent()); - } - - if (modifierText != null) - modifierText.text = MPState.FreeModEnabled ? "Selected Modifiers" : Localization.Get("SUGGESTED_MODIFIERS"); - } } } diff --git a/MultiplayerExtensions/UI/MPSettings.cs b/MultiplayerExtensions/UI/MPSettings.cs index c1a3cf2..db0fd76 100644 --- a/MultiplayerExtensions/UI/MPSettings.cs +++ b/MultiplayerExtensions/UI/MPSettings.cs @@ -13,15 +13,5 @@ public bool EasterEggsEnabled MPState.EasterEggsEnabled = value; } } - - [UIValue("statistics")] - public bool StatisticsEnabled - { - get => Plugin.Config.Statistics; - set - { - Plugin.Config.Statistics = value; - } - } } } diff --git a/MultiplayerExtensions/Utilities/Config.cs b/MultiplayerExtensions/Utilities/Config.cs index b5717b5..6a460e4 100644 --- a/MultiplayerExtensions/Utilities/Config.cs +++ b/MultiplayerExtensions/Utilities/Config.cs @@ -6,14 +6,10 @@ public class PluginConfig { public virtual bool SingleplayerHUD { get; set; } = false; public virtual bool Hologram { get; set; } = true; - public virtual bool FreeMod { get; set; } = false; public virtual bool LagReducer { get; set; } = false; public virtual bool MissLighting { get; set; } = true; - public virtual bool HostPick { get; set; } = true; public virtual string Color { get; set; } = "#08C0FF"; public virtual int MaxPlayers { get; set; } = 10; - public virtual bool ReportMasterServer { get; set; } = true; - public virtual bool Statistics { get; set; } = true; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public virtual DebugConfig? DebugConfig { get; set; } diff --git a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs index 23c50a0..0b6e046 100644 --- a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs +++ b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs @@ -24,7 +24,6 @@ static HarmonyManager() AddDefaultPatch(); //AddDefaultPatch(); (disabled for official) AddDefaultPatch(); - AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); @@ -36,8 +35,6 @@ static HarmonyManager() AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); - AddDefaultPatch(); - AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); @@ -48,6 +45,7 @@ static HarmonyManager() AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); + AddDefaultPatch(); } private static void AddDefaultPatch() where T : class diff --git a/MultiplayerExtensions/Utilities/Statistics.cs b/MultiplayerExtensions/Utilities/Statistics.cs deleted file mode 100644 index 6199def..0000000 --- a/MultiplayerExtensions/Utilities/Statistics.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; - -namespace MultiplayerExtensions.Utilities -{ - public static class Statistics - { - private const string BASE_URL = "https://mpex.goobwabber.com/api/v1"; - - // From com.github.roydejong.BeatSaberServerBrowser - private static async Task PerformWebRequest(string method, string endpoint, string json = null!) - { - var targetUrl = BASE_URL + endpoint; - Plugin.Log?.Debug($"{method} {targetUrl} {json}"); - - try - { - HttpResponseMessage response; - - switch (method) - { - case "GET": - response = await Plugin.HttpClient.GetAsync(targetUrl).ConfigureAwait(false); - break; - case "POST": - if (String.IsNullOrEmpty(json)) - { - response = await Plugin.HttpClient.PostAsync(targetUrl, null).ConfigureAwait(false); - } - else - { - var content = new StringContent(json, Encoding.UTF8, "application/json"); - response = await Plugin.HttpClient.PostAsync(targetUrl, content).ConfigureAwait(false); - } - break; - default: - throw new ArgumentException($"Invalid request method for the Master Server API: {method}"); - } - - if (response.StatusCode != HttpStatusCode.OK) - { - throw new Exception($"Expected HTTP 200 OK, got HTTP {response.StatusCode}"); - } - - Plugin.Log?.Debug($"✔ 200 OK: {method} {targetUrl}"); - return response; - } - catch (TaskCanceledException) - { - return null; - } - catch (Exception ex) - { - Plugin.Log?.Error($"⚠ Request error: {method} {targetUrl} → {ex}"); - return null; - } - } - - public static async Task AddUser(string userId, int platform) - { - return await PerformWebRequest("POST", $"/adduser?userId={userId}&platform={platform}") != null; - } - - public static async Task PlayMap(string? userId, int platform, string hostname, string hash, string difficulty, string characteristic, int timePlayed, bool pass, int cutNotes, int missedNotes, int score, double accuracy) - { - if (userId != null) - return await PerformWebRequest("POST", $"/playmap?userId={userId}&platform={platform}&hostname={hostname}&hash={hash}&difficulty={difficulty}&characteristic={characteristic}&timePlayed={timePlayed}&pass={pass}&cutNotes={cutNotes}&missedNotes={missedNotes}&score={score}&accuracy={accuracy}") != null; - return true; - } - - public static async Task UseMaster(string? userId, int platform, string hostname, bool host = false) - { - if (userId != null) - return await PerformWebRequest("POST", $"/usemaster?userId={userId}&hostname={hostname}&platform={platform}&host={host}&disableNewMaster={!Plugin.Config.ReportMasterServer}") != null; - return true; - } - } -} From 2ebaa90a862366dd03ba1d089617f09c082a2465 Mon Sep 17 00:00:00 2001 From: MT Date: Mon, 13 Sep 2021 15:56:55 -0400 Subject: [PATCH 22/41] Move UI --- MultiplayerExtensions/UI/LobbySetupPanel.bsml | 7 +++---- MultiplayerExtensions/UI/LobbySetupPanel.cs | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/MultiplayerExtensions/UI/LobbySetupPanel.bsml b/MultiplayerExtensions/UI/LobbySetupPanel.bsml index dc628ec..a5bce50 100644 --- a/MultiplayerExtensions/UI/LobbySetupPanel.bsml +++ b/MultiplayerExtensions/UI/LobbySetupPanel.bsml @@ -1,8 +1,7 @@ - - - - + + + diff --git a/MultiplayerExtensions/UI/LobbySetupPanel.cs b/MultiplayerExtensions/UI/LobbySetupPanel.cs index 8a20b0c..9007900 100644 --- a/MultiplayerExtensions/UI/LobbySetupPanel.cs +++ b/MultiplayerExtensions/UI/LobbySetupPanel.cs @@ -127,8 +127,8 @@ private void OnActivate(bool firstActivation, bool addedToHierarchy, bool screen { if (firstActivation) { - Transform spectatorText = transform.Find("Wrapper").Find("SpectatorModeWarningText"); - spectatorText.position = new Vector3(spectatorText.position.x, 0.25f, spectatorText.position.z); + //Transform spectatorText = transform.Find("Wrapper").Find("SpectatorModeWarningText"); + //spectatorText.position = new Vector3(spectatorText.position.x, 0.25f, spectatorText.position.z); } } } From dbb74d288c4c572b00daaebd9c24a2da16baba6a Mon Sep 17 00:00:00 2001 From: MT Date: Mon, 13 Sep 2021 18:38:42 -0400 Subject: [PATCH 23/41] matchmaking patches --- .../HarmonyPatches/CustomSongsPatches.cs | 13 +++++++++++++ .../Utilities/Harmony/HarmonyManager.cs | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs b/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs index 2329c3b..b85d09f 100644 --- a/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs @@ -22,6 +22,19 @@ static void Prefix(CreateServerFormData data) } } + [HarmonyPatch(typeof(MultiplayerLobbyConnectionController), nameof(MultiplayerLobbyConnectionController.ConnectToMatchmaking), MethodType.Normal)] + internal class ConnectToMatchmakingPatch + { + /// + /// Modifies the data used to matchmake + /// + static void Prefix(SongPackMask ____songPackMask) + { + if (!MPState.CurrentMasterServer.isOfficial) + ____songPackMask |= new SongPackMask("custom_levelpack_CustomLevels"); + } + } + [HarmonyPatch(typeof(MultiplayerLevelSelectionFlowCoordinator), "enableCustomLevels", MethodType.Getter)] internal class EnableCustomLevelsPatch { diff --git a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs index 0b6e046..b5c7d4f 100644 --- a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs +++ b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs @@ -22,7 +22,8 @@ public static class HarmonyManager static HarmonyManager() { AddDefaultPatch(); - //AddDefaultPatch(); (disabled for official) + AddDefaultPatch(); + AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); From f767dfc11cabde3633e53585719ca1f517d5c8b0 Mon Sep 17 00:00:00 2001 From: MT Date: Mon, 13 Sep 2021 21:31:21 -0400 Subject: [PATCH 24/41] update frequency / removed dead code / fixed quickplay matchmake --- .../Extensions/ExtendedGameStateController.cs | 3 --- MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs | 4 ++-- MultiplayerExtensions/HarmonyPatches/NetworkingPatches.cs | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs index c29bfa7..ad2ee2d 100644 --- a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs +++ b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs @@ -82,9 +82,6 @@ public override void StopListeningToGameStart() public override void HandleMenuRpcManagerStartedLevel(string userId, BeatmapIdentifierNetSerializable beatmapId, GameplayModifiers gameplayModifiers, float startTime) { - if (_sessionManager.partyOwner != null && _sessionManager.partyOwner.HasState("freemod")) - gameplayModifiers = _lobbyPlayersDataModel.GetPlayerGameplayModifiers(_lobbyPlayersDataModel.localUserId); - base.HandleMenuRpcManagerStartedLevel(userId, beatmapId, gameplayModifiers, startTime); _multiplayerLevelLoader.countdownFinishedEvent -= base.HandleMultiplayerLevelLoaderCountdownFinished; _multiplayerLevelLoader.countdownFinishedEvent += this.HandleMultiplayerLevelLoaderCountdownFinished; diff --git a/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs b/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs index b85d09f..d8b4f55 100644 --- a/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs @@ -28,10 +28,10 @@ internal class ConnectToMatchmakingPatch /// /// Modifies the data used to matchmake /// - static void Prefix(SongPackMask ____songPackMask) + static void Prefix(ref SongPackMask songPackMask) { if (!MPState.CurrentMasterServer.isOfficial) - ____songPackMask |= new SongPackMask("custom_levelpack_CustomLevels"); + songPackMask |= new SongPackMask("custom_levelpack_CustomLevels"); } } diff --git a/MultiplayerExtensions/HarmonyPatches/NetworkingPatches.cs b/MultiplayerExtensions/HarmonyPatches/NetworkingPatches.cs index 07ebd7d..8529d27 100644 --- a/MultiplayerExtensions/HarmonyPatches/NetworkingPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/NetworkingPatches.cs @@ -46,7 +46,7 @@ internal static void Postfix(MultiplayerSettingsPanelController __instance, stri internal class UpdateReliableFrequencyPatch { private static float nextTime = 0f; - private static float frequency = 0.1f; + private static float frequency = 0.02f; internal static bool Prefix() { From 98cbd777d55c26d31cb3db0fcb2fbb1082975934 Mon Sep 17 00:00:00 2001 From: MT Date: Tue, 14 Sep 2021 12:54:09 -0400 Subject: [PATCH 25/41] player ready --- .../Extensions/ExtendedGameStateController.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs index ad2ee2d..82aa79f 100644 --- a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs +++ b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs @@ -10,8 +10,6 @@ class ExtendedGameStateController : LobbyGameStateController, ILobbyGameStateCon protected readonly ExtendedSessionManager _sessionManager; protected readonly ExtendedEntitlementChecker _entitlementChecker; - private static readonly SemVer.Version _minVersionStart = new SemVer.Version("0.6.0"); - internal ExtendedGameStateController(IMultiplayerSessionManager sessionManager, NetworkPlayerEntitlementChecker entitlementChecker) { _sessionManager = (sessionManager as ExtendedSessionManager)!; @@ -112,15 +110,7 @@ public override void HandleMultiplayerLevelLoaderCountdownFinished(IPreviewBeatm private async Task IsPlayerReady(IConnectedPlayer player) { - if (!player.HasState("modded")) return true; // player is not modded: always assume ready if (await _entitlementChecker.GetUserEntitlementStatusWithoutRequest(player.userId, startedBeatmapId.levelID) == EntitlementsStatus.Ok) return true; - - ExtendedPlayer? extendedPlayer = _sessionManager.GetExtendedPlayer(player); - - // did not recieve mpexVersion from player or the version is too old: assume the player is ready - if (extendedPlayer == null) return true; - if (extendedPlayer.mpexVersion == null || extendedPlayer.mpexVersion < _minVersionStart) return true; - return false; } From aa16e8e719c7224d98eb3e50294335099bc1b9e4 Mon Sep 17 00:00:00 2001 From: MT Date: Wed, 15 Sep 2021 09:02:46 -0400 Subject: [PATCH 26/41] fix red circle --- MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs b/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs index d8b4f55..abd2846 100644 --- a/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs @@ -68,7 +68,7 @@ internal class MissingLevelStartPatch /// static void Prefix(LobbySetupViewController __instance, string playersMissingLevelText, ref Button ____startGameReadyButton) { - if (____startGameReadyButton.interactable) + if (string.IsNullOrEmpty(playersMissingLevelText) && ____startGameReadyButton.interactable) __instance.SetStartGameEnabled(CannotStartGameReason.DoNotOwnSong); } } From d3976c07a5d1c6c4ae6977313bfa467e7a2a724e Mon Sep 17 00:00:00 2001 From: MT Date: Wed, 15 Sep 2021 16:37:46 -0400 Subject: [PATCH 27/41] no prediction garbage --- .../HarmonyPatches/EnvironmentPatches.cs | 28 +++++++++++++++++++ .../Utilities/Harmony/HarmonyManager.cs | 1 + 2 files changed, 29 insertions(+) diff --git a/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs b/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs index b278bb9..ae19e7e 100644 --- a/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs @@ -174,4 +174,32 @@ private static void SetInteractableAttacher(Selectable contract, bool value) contract.interactable = !MPState.CurrentMasterServer.isOfficial ? true : value; } } + + [HarmonyPatch(typeof(GameServerLobbyFlowCoordinator), nameof(GameServerLobbyFlowCoordinator.HandleLobbySetupViewControllerStartGameOrReady), MethodType.Normal)] + internal class YeetPredictionsPatch + { + private static readonly MethodInfo _rootMethod = typeof(LobbyPlayerPermissionsModel).GetProperty(nameof(LobbyPlayerPermissionsModel.isPartyOwner)).GetGetMethod(); +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. + private static readonly MethodInfo _getIsPartyOwnerAttacher = SymbolExtensions.GetMethodInfo(() => GetIsPartyOwnerAttacher(null)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. + + static IEnumerable Transpiler(IEnumerable instructions) + { + var codes = instructions.ToList(); + for (int i = 0; i < codes.Count; i++) + { + if (codes[i].opcode == OpCodes.Callvirt && codes[i].OperandIs(_rootMethod)) + { + codes[i] = new CodeInstruction(OpCodes.Callvirt, _getIsPartyOwnerAttacher); + } + } + + return codes.AsEnumerable(); + } + + private static bool GetIsPartyOwnerAttacher(LobbyPlayerPermissionsModel contract) + { + return false; + } + } } diff --git a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs index b5c7d4f..b749329 100644 --- a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs +++ b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs @@ -47,6 +47,7 @@ static HarmonyManager() AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); + AddDefaultPatch(); } private static void AddDefaultPatch() where T : class From de40b7cb946f4a616714258f71eee7c621b75b01 Mon Sep 17 00:00:00 2001 From: MT Date: Thu, 16 Sep 2021 15:03:32 -0400 Subject: [PATCH 28/41] beatmap packet order --- MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs index 41a409e..e6329c2 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs @@ -96,7 +96,7 @@ public override void HandleMenuRpcManagerGetRecommendedBeatmap(string userId) { ILobbyPlayerData lobbyPlayerDataModel = this.GetLobbyPlayerDataModel(this.localUserId); if (lobbyPlayerDataModel != null && lobbyPlayerDataModel.beatmapLevel != null) - { + { if (lobbyPlayerDataModel.beatmapLevel is PreviewBeatmapStub preview) _packetManager.Send(new PreviewBeatmapPacket(preview, lobbyPlayerDataModel.beatmapCharacteristic.serializedName, lobbyPlayerDataModel.beatmapDifficulty)); this._menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(lobbyPlayerDataModel.beatmapLevel.levelID, lobbyPlayerDataModel.beatmapCharacteristic.serializedName, lobbyPlayerDataModel.beatmapDifficulty)); @@ -159,8 +159,8 @@ public async override void HandleMenuRpcManagerRecommendBeatmap(string userId, B preview = await FetchBeatSaverPreview(levelId, hash); HMMainThreadDispatcher.instance.Enqueue(() => base.SetPlayerBeatmapLevel(base.localUserId, preview, beatmapDifficulty, characteristic)); - _menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(levelId, characteristic.serializedName, beatmapDifficulty)); _packetManager.Send(new PreviewBeatmapPacket(preview!, characteristic.serializedName, beatmapDifficulty)); + _menuRpcManager.RecommendBeatmap(new BeatmapIdentifierNetSerializable(levelId, characteristic.serializedName, beatmapDifficulty)); } }else base.SetLocalPlayerBeatmapLevel(levelId, beatmapDifficulty, characteristic); From f075f70b816f09f4eaec2a11b85cd358a810416e Mon Sep 17 00:00:00 2001 From: MT Date: Thu, 16 Sep 2021 20:46:55 -0400 Subject: [PATCH 29/41] predictions were actually important sadge --- MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs index b749329..1cf9444 100644 --- a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs +++ b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs @@ -47,7 +47,7 @@ static HarmonyManager() AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); - AddDefaultPatch(); + //AddDefaultPatch(); } private static void AddDefaultPatch() where T : class From 88be20b6a1b861a7f352aef59bb9d128c3c07b09 Mon Sep 17 00:00:00 2001 From: MT Date: Tue, 21 Sep 2021 07:46:01 -0400 Subject: [PATCH 30/41] disable position clamps --- .../HarmonyPatches/EnvironmentPatches.cs | 12 ++++++++++++ .../Utilities/Harmony/HarmonyManager.cs | 1 + 2 files changed, 13 insertions(+) diff --git a/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs b/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs index ae19e7e..fd358e9 100644 --- a/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/EnvironmentPatches.cs @@ -202,4 +202,16 @@ private static bool GetIsPartyOwnerAttacher(LobbyPlayerPermissionsModel contract return false; } } + + [HarmonyPatch(typeof(AvatarPoseRestrictions), nameof(AvatarPoseRestrictions.HandleAvatarPoseControllerPositionsWillBeSet), MethodType.Normal)] + internal class DisableAvatarRestrictions + { + static bool Prefix(AvatarPoseRestrictions __instance, Vector3 headPosition, Vector3 leftHandPosition, Vector3 rightHandPosition, out Vector3 newHeadPosition, out Vector3 newLeftHandPosition, out Vector3 newRightHandPosition) + { + newHeadPosition = headPosition; + newLeftHandPosition = __instance.LimitHandPositionRelativeToHead(leftHandPosition, headPosition); + newRightHandPosition = __instance.LimitHandPositionRelativeToHead(rightHandPosition, headPosition); + return false; + } + } } diff --git a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs index 1cf9444..c338774 100644 --- a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs +++ b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs @@ -48,6 +48,7 @@ static HarmonyManager() AddDefaultPatch(); AddDefaultPatch(); //AddDefaultPatch(); + AddDefaultPatch(); } private static void AddDefaultPatch() where T : class From fd5ddec98d52385f4f7aac006b7f5cab2f5218f2 Mon Sep 17 00:00:00 2001 From: MT Date: Wed, 22 Sep 2021 08:41:57 -0400 Subject: [PATCH 31/41] entitlement stuff and player table --- .../Extensions/ExtendedEntitlementChecker.cs | 9 +++---- .../Extensions/ExtendedGameStateController.cs | 5 +++- .../Extensions/ExtendedPlayerTableCell.cs | 24 ++++++++++++------- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs b/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs index 98ca5ce..0cd14c6 100644 --- a/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs +++ b/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs @@ -104,16 +104,13 @@ public Task GetUserEntitlementStatus(string userId, string l return _tcsDictionary[userId][levelId].Task; } - public Task GetUserEntitlementStatusWithoutRequest(string userId, string levelId) + public EntitlementsStatus GetUserEntitlementStatusWithoutRequest(string userId, string levelId) { - if (userId == _sessionManager.localPlayer.userId) - return GetEntitlementStatus(levelId); - if (_entitlementsDictionary.TryGetValue(userId, out Dictionary userDictionary)) if (userDictionary.TryGetValue(levelId, out EntitlementsStatus entitlement)) - return Task.FromResult(entitlement); + return entitlement; - return Task.FromResult(EntitlementsStatus.NotDownloaded); + return EntitlementsStatus.Unknown; } } } diff --git a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs index 82aa79f..e73abad 100644 --- a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs +++ b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs @@ -110,7 +110,10 @@ public override void HandleMultiplayerLevelLoaderCountdownFinished(IPreviewBeatm private async Task IsPlayerReady(IConnectedPlayer player) { - if (await _entitlementChecker.GetUserEntitlementStatusWithoutRequest(player.userId, startedBeatmapId.levelID) == EntitlementsStatus.Ok) return true; + if (player.isMe && await _entitlementChecker.GetEntitlementStatus(startedBeatmapId.levelID) == EntitlementsStatus.Ok) + return true; + if (_entitlementChecker.GetUserEntitlementStatusWithoutRequest(player.userId, startedBeatmapId.levelID) == EntitlementsStatus.Ok) + return true; return false; } diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayerTableCell.cs b/MultiplayerExtensions/Extensions/ExtendedPlayerTableCell.cs index cdd49c1..352ea54 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayerTableCell.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayerTableCell.cs @@ -17,7 +17,9 @@ class ExtendedPlayerTableCell : GameServerPlayerTableCell protected IMenuRpcManager _menuRpcManager = null!; private ButtonBinder __buttonBinder = new ButtonBinder(); - private CancellationTokenSource entitlementCts = null!; + + private static float alphaIsMe = 0.4f; + private static float alphaIsNotMe = 0.2f; private static Color green = new Color(0f, 1f, 0f, 1f); private static Color yellow = new Color(0.125f, 0.75f, 1f, 1f); @@ -57,6 +59,7 @@ internal void Construct(GameServerPlayerTableCell playerTableCell) _statusImageView = playerTableCell.GetField("_statusImageView"); _readyIcon = playerTableCell.GetField("_readyIcon"); _spectatingIcon = playerTableCell.GetField("_spectatingIcon"); + _hostIcon = playerTableCell.GetField("_hostIcon"); // Helpers _gameplayModifiers = playerTableCell.GetField("_gameplayModifiers"); // TableCellWithSeparator @@ -80,12 +83,8 @@ public override void SetData(IConnectedPlayer connectedPlayer, ILobbyPlayerData lastPlayer = connectedPlayer; } - private async void GetLevelEntitlement(IConnectedPlayer player) + private void GetLevelEntitlement(IConnectedPlayer player) { - if (entitlementCts != null) - entitlementCts.Cancel(); - entitlementCts = new CancellationTokenSource(); - string? levelId = _playersDataModel.GetPlayerBeatmapLevel(_playersDataModel.partyOwnerId)?.levelID; if (levelId == null) { @@ -95,8 +94,15 @@ private async void GetLevelEntitlement(IConnectedPlayer player) lastLevelId = levelId; - EntitlementsStatus entitlement = await _entitlementChecker.GetUserEntitlementStatus(player.userId, levelId); - SetLevelEntitlement(player, entitlement); + EntitlementsStatus entitlement = EntitlementsStatus.Unknown; + if (!player.isMe) + entitlement = _entitlementChecker.GetUserEntitlementStatusWithoutRequest(player.userId, levelId); + if (entitlement != EntitlementsStatus.Unknown) + SetLevelEntitlement(player, entitlement); + else + { + _entitlementChecker.GetUserEntitlementStatus(player.userId, levelId); + } } private void SetLevelEntitlement(IConnectedPlayer player, EntitlementsStatus status) @@ -109,7 +115,7 @@ private void SetLevelEntitlement(IConnectedPlayer player, EntitlementsStatus sta _ => normal, }; - backgroundColor.a = player.isMe ? 0.4f : 0.2f; + backgroundColor.a = player.isMe ? alphaIsMe : alphaIsNotMe; _localPlayerBackgroundImage.color = backgroundColor; } From ee9ac07b9f48cab24211a4d67d923740050928c5 Mon Sep 17 00:00:00 2001 From: MT Date: Fri, 24 Sep 2021 10:00:11 -0400 Subject: [PATCH 32/41] fixed some weird level start stuff --- .../Extensions/ExtendedEntitlementChecker.cs | 18 +++++ .../Extensions/ExtendedGameStateController.cs | 79 +++++++------------ .../Extensions/ExtendedPlayersDataModel.cs | 2 +- 3 files changed, 49 insertions(+), 50 deletions(-) diff --git a/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs b/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs index 0cd14c6..52b3255 100644 --- a/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs +++ b/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs @@ -1,6 +1,7 @@ using BeatSaverSharp.Models; using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using Zenject; @@ -112,5 +113,22 @@ public EntitlementsStatus GetUserEntitlementStatusWithoutRequest(string userId, return EntitlementsStatus.Unknown; } + + public async Task WaitForOkEntitlement(string userId, string levelId, CancellationToken cancellationToken) + { + if (!_tcsDictionary.ContainsKey(userId)) + _tcsDictionary[userId] = new Dictionary>(); + if (!_tcsDictionary[userId].ContainsKey(levelId)) + _tcsDictionary[userId][levelId] = new TaskCompletionSource(); + + cancellationToken.Register(() => _tcsDictionary[userId][levelId].TrySetCanceled()); + + EntitlementsStatus result = EntitlementsStatus.Unknown; + while (result != EntitlementsStatus.Ok && !cancellationToken.IsCancellationRequested) + { + result = await _tcsDictionary[userId][levelId].Task.ContinueWith(t => t.IsCompleted ? t.Result : EntitlementsStatus.Unknown); + _tcsDictionary[userId][levelId] = new TaskCompletionSource(); + } + } } } diff --git a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs index e73abad..97bedea 100644 --- a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs +++ b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; namespace MultiplayerExtensions.Extensions @@ -19,7 +20,6 @@ internal ExtendedGameStateController(IMultiplayerSessionManager sessionManager, public override void Activate() { this._lobbyGameStateModel.gameStateDidChangeEvent += this.HandleGameStateChanged; - this._entitlementChecker.receivedEntitlementEvent += this.HandleEntitlement; base.Activate(); (this as ILobbyGameStateController).lobbyStateChangedEvent += this.HandleLobbyStateChanged; @@ -28,7 +28,6 @@ public override void Activate() public override void Deactivate() { this._lobbyGameStateModel.gameStateDidChangeEvent -= this.HandleGameStateChanged; - this._entitlementChecker.receivedEntitlementEvent -= this.HandleEntitlement; this._menuRpcManager.startedLevelEvent -= this.HandleMenuRpcManagerStartedLevel; this._menuRpcManager.startedLevelEvent += base.HandleMenuRpcManagerStartedLevel; @@ -70,14 +69,6 @@ public override void StopListeningToGameStart() base.StopListeningToGameStart(); } - - - private IPreviewBeatmapLevel? _previewBeatmapLevel; - private BeatmapDifficulty _beatmapDifficulty; - private BeatmapCharacteristicSO? _beatmapCharacteristic; - private IDifficultyBeatmap? _difficultyBeatmap; - private GameplayModifiers? _gameplayModifiers; - public override void HandleMenuRpcManagerStartedLevel(string userId, BeatmapIdentifierNetSerializable beatmapId, GameplayModifiers gameplayModifiers, float startTime) { base.HandleMenuRpcManagerStartedLevel(userId, beatmapId, gameplayModifiers, startTime); @@ -89,52 +80,42 @@ public override void StopLoading() { _multiplayerLevelLoader.countdownFinishedEvent += base.HandleMultiplayerLevelLoaderCountdownFinished; _multiplayerLevelLoader.countdownFinishedEvent -= this.HandleMultiplayerLevelLoaderCountdownFinished; + + if (_levelLoadSyncCts != null) + _levelLoadSyncCts.Cancel(); + base.StopLoading(); } - public override void HandleMultiplayerLevelLoaderCountdownFinished(IPreviewBeatmapLevel previewBeatmapLevel, BeatmapDifficulty beatmapDifficulty, BeatmapCharacteristicSO beatmapCharacteristic, IDifficultyBeatmap difficultyBeatmap, GameplayModifiers gameplayModifiers) + private CancellationTokenSource? _levelLoadSyncCts; + + public async override void HandleMultiplayerLevelLoaderCountdownFinished(IPreviewBeatmapLevel previewBeatmapLevel, BeatmapDifficulty beatmapDifficulty, BeatmapCharacteristicSO beatmapCharacteristic, IDifficultyBeatmap difficultyBeatmap, GameplayModifiers gameplayModifiers) { Plugin.Log?.Debug("Map finished loading, waiting for other players..."); - - this._previewBeatmapLevel = previewBeatmapLevel; - this._beatmapDifficulty = beatmapDifficulty; - this._beatmapCharacteristic = beatmapCharacteristic; - this._difficultyBeatmap = difficultyBeatmap; - this._gameplayModifiers = gameplayModifiers; - _menuRpcManager.SetIsEntitledToLevel(previewBeatmapLevel.levelID, EntitlementsStatus.Ok); - HandleEntitlement(_lobbyPlayersDataModel.localUserId, startedBeatmapId.levelID, EntitlementsStatus.Ok); - } - - - private async Task IsPlayerReady(IConnectedPlayer player) - { - if (player.isMe && await _entitlementChecker.GetEntitlementStatus(startedBeatmapId.levelID) == EntitlementsStatus.Ok) - return true; - if (_entitlementChecker.GetUserEntitlementStatusWithoutRequest(player.userId, startedBeatmapId.levelID) == EntitlementsStatus.Ok) - return true; - return false; - } - - private async void HandleEntitlement(string userId, string levelId, EntitlementsStatus entitlement) - { - if (state == MultiplayerLobbyState.GameStarting) - { - if (_levelStartedOnTime == false) - { - Plugin.Log.Debug("Loaded level late, starting game."); - base.HandleMultiplayerLevelLoaderCountdownFinished(_previewBeatmapLevel, _beatmapDifficulty, _beatmapCharacteristic, _difficultyBeatmap, _gameplayModifiers); - } - - IEnumerable> readyTasks = _sessionManager.connectedPlayers.Select(IsPlayerReady); - bool[] readyStates = await Task.WhenAll(readyTasks); - if (readyStates.All(x => x) && await _entitlementChecker.GetEntitlementStatus(startedBeatmapId.levelID) == EntitlementsStatus.Ok) - { - Plugin.Log.Debug("All players ready, starting game."); - base.HandleMultiplayerLevelLoaderCountdownFinished(_previewBeatmapLevel, _beatmapDifficulty, _beatmapCharacteristic, _difficultyBeatmap, _gameplayModifiers); - } - } + if (_levelStartedOnTime == false) + { + Plugin.Log?.Debug("Loaded level late, starting game."); + base.HandleMultiplayerLevelLoaderCountdownFinished(previewBeatmapLevel, beatmapDifficulty, beatmapCharacteristic, difficultyBeatmap, gameplayModifiers); + return; + } + + _levelLoadSyncCts = new CancellationTokenSource(); + IEnumerable playerReadyTasks = _sessionManager.connectedPlayers.Select(p => p.isMe + ? Task.CompletedTask + : _entitlementChecker.WaitForOkEntitlement(p.userId, previewBeatmapLevel.levelID, _levelLoadSyncCts.Token) + ); + await Task.WhenAll(playerReadyTasks); + + if (_levelLoadSyncCts.IsCancellationRequested) { + _levelLoadSyncCts = null; + return; + } + _levelLoadSyncCts = null; + + Plugin.Log?.Debug("All players ready, starting game."); + base.HandleMultiplayerLevelLoaderCountdownFinished(previewBeatmapLevel, beatmapDifficulty, beatmapCharacteristic, difficultyBeatmap, gameplayModifiers); } } } diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs index e6329c2..fd9229f 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayersDataModel.cs @@ -74,7 +74,7 @@ private void HandlePreviewBeatmapPacket(PreviewBeatmapPacket packet, IConnectedP Plugin.Log?.Debug($"'{player.userId}' selected song '{hash}'."); BeatmapCharacteristicSO characteristic = _beatmapCharacteristicCollection.GetBeatmapCharacteristicBySerializedName(packet.characteristic); PreviewBeatmapStub preview = new PreviewBeatmapStub(packet); - HMMainThreadDispatcher.instance.Enqueue(() => base.SetPlayerBeatmapLevel(player.userId, preview, packet.difficulty, characteristic)); + base.SetPlayerBeatmapLevel(player.userId, preview, packet.difficulty, characteristic); } } From 34aa255393333262202d044dc6f7219a180c7c62 Mon Sep 17 00:00:00 2001 From: Goobwabber <47616186+Goobwabber@users.noreply.github.com> Date: Tue, 28 Sep 2021 16:06:00 -0400 Subject: [PATCH 33/41] Update PR_Build.yml --- .github/workflows/PR_Build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/PR_Build.yml b/.github/workflows/PR_Build.yml index 0333c26..fae5746 100644 --- a/.github/workflows/PR_Build.yml +++ b/.github/workflows/PR_Build.yml @@ -18,7 +18,7 @@ jobs: dotnet-version: 3.1.101 - name: GetStrippedRefs env: - FILES_URL: ${{ secrets.BSFILES_1_16_3_URL }} + FILES_URL: ${{ secrets.BSFILES_URL }} run: wget --no-check-certificate "$FILES_URL" -q -O bsfiles.zip - name: ExtractRefs run: unzip -q -n bsfiles.zip -d ./Refs From 3b6420a4f4206fabcae20282baf1b6fea73e57db Mon Sep 17 00:00:00 2001 From: MT Date: Tue, 28 Sep 2021 17:05:15 -0400 Subject: [PATCH 34/41] fix brain pepga --- .../Extensions/ExtendedEntitlementChecker.cs | 4 ++++ MultiplayerExtensions/Plugin.cs | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs b/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs index 52b3255..6072ef2 100644 --- a/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs +++ b/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs @@ -116,6 +116,10 @@ public EntitlementsStatus GetUserEntitlementStatusWithoutRequest(string userId, public async Task WaitForOkEntitlement(string userId, string levelId, CancellationToken cancellationToken) { + if (_entitlementsDictionary.TryGetValue(userId, out Dictionary userDictionary)) + if (userDictionary.TryGetValue(levelId, out EntitlementsStatus entitlement) && entitlement == EntitlementsStatus.Ok) + return; + if (!_tcsDictionary.ContainsKey(userId)) _tcsDictionary[userId] = new Dictionary>(); if (!_tcsDictionary[userId].ContainsKey(levelId)) diff --git a/MultiplayerExtensions/Plugin.cs b/MultiplayerExtensions/Plugin.cs index 388c55b..83354dc 100644 --- a/MultiplayerExtensions/Plugin.cs +++ b/MultiplayerExtensions/Plugin.cs @@ -93,9 +93,9 @@ public void MPEvents_Test() MPEvents.BeatmapSelected += (s, e) => { if (!string.IsNullOrEmpty(e.LevelId)) - Log?.Warn($"BeatmapSelected by '{e.UserId}|{e.UserType.ToString()}': {e.LevelId}|{e.BeatmapDifficulty}|{e.BeatmapCharacteristic?.name ?? ""}"); + Log?.Warn($"Beatmap Selected by '{e.UserId}|{e.UserType.ToString()}': {e.LevelId}|{e.BeatmapDifficulty}|{e.BeatmapCharacteristic?.name ?? ""}"); else - Log?.Warn($"Beatmap Cleared by '{e.UserId}|{e.UserType.ToString()}'"); + Log?.Warn($"Beatmap Selection Cleared by '{e.UserId}|{e.UserType.ToString()}'"); }; } [Conditional("DEBUG")] From 87f1fd026d2fb0b98efe843f4e3577960254d154 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Fri, 29 Oct 2021 20:30:51 +0200 Subject: [PATCH 35/41] Added Download Progress Bar, Added Warning dialog for Quickplay customs --- MultiplayerExtensions/Downloader.cs | 2 +- .../Extensions/ExtendedGameStateController.cs | 7 ++ .../HarmonyPatches/QuickplayPatches.cs | 50 ++++++++++++++ .../MultiplayerExtensions.csproj | 4 +- ...ding.bsml => CenterScreenLoading.bsml.dis} | 0 .../UI/CenterScreenLoadingPanel.cs | 65 +++++++++++++++---- .../Utilities/Harmony/HarmonyManager.cs | 1 + 7 files changed, 113 insertions(+), 16 deletions(-) create mode 100644 MultiplayerExtensions/HarmonyPatches/QuickplayPatches.cs rename MultiplayerExtensions/UI/{CenterScreenLoading.bsml => CenterScreenLoading.bsml.dis} (100%) diff --git a/MultiplayerExtensions/Downloader.cs b/MultiplayerExtensions/Downloader.cs index 9d713aa..2e3136e 100644 --- a/MultiplayerExtensions/Downloader.cs +++ b/MultiplayerExtensions/Downloader.cs @@ -49,7 +49,7 @@ public static bool TryGetDownload(string levelId, out Task { Plugin.Log?.Info($"Version: '{version.Key}' '{version.Hash}'"); return version.Hash.ToUpper() == hash; - }).DownloadZIP(); + }).DownloadZIP(progress: UI.CenterScreenLoadingPanel.self); #if DEBUG TimeSpan delay = TimeSpan.FromSeconds(Plugin.Config.DebugConfig?.MinDownloadTime ?? 0) - TimeSpan.FromMilliseconds(sw.ElapsedMilliseconds); if (delay > TimeSpan.Zero) diff --git a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs index 97bedea..7277558 100644 --- a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs +++ b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs @@ -115,6 +115,13 @@ public async override void HandleMultiplayerLevelLoaderCountdownFinished(IPrevie _levelLoadSyncCts = null; Plugin.Log?.Debug("All players ready, starting game."); + + Plugin.Log?.Debug($"Null Checking previewBeatmapLevel: '{(previewBeatmapLevel == null ? "null" : "not null")}'"); + Plugin.Log?.Debug($"Null Checking beatmapDifficulty: '{beatmapDifficulty}'"); + Plugin.Log?.Debug($"Null Checking beatmapCharacteristic: '{(beatmapCharacteristic == null ? "null" : "not null")}'"); + Plugin.Log?.Debug($"Null Checking difficultyBeatmap: '{(difficultyBeatmap == null ? "null" : "not null")}'"); + Plugin.Log?.Debug($"Null Checking gameplayModifiers: '{(gameplayModifiers == null ? "null" : "not null")}'"); + base.HandleMultiplayerLevelLoaderCountdownFinished(previewBeatmapLevel, beatmapDifficulty, beatmapCharacteristic, difficultyBeatmap, gameplayModifiers); } } diff --git a/MultiplayerExtensions/HarmonyPatches/QuickplayPatches.cs b/MultiplayerExtensions/HarmonyPatches/QuickplayPatches.cs new file mode 100644 index 0000000..8844d3b --- /dev/null +++ b/MultiplayerExtensions/HarmonyPatches/QuickplayPatches.cs @@ -0,0 +1,50 @@ +using HarmonyLib; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using IPA.Utilities; +using HMUI; + +namespace MultiplayerExtensions.HarmonyPatches +{ + [HarmonyPatch(typeof(MultiplayerModeSelectionFlowCoordinator), nameof(MultiplayerModeSelectionFlowCoordinator.HandleJoinQuickPlayViewControllerDidFinish), MethodType.Normal)] + internal class MultiplayerModeSelectionFlowCoordinatorPatch + { + static bool Prefix(MultiplayerModeSelectionFlowCoordinator __instance, bool success, JoinQuickPlayViewController ____joinQuickPlayViewController, SimpleDialogPromptViewController ____simpleDialogPromptViewController, SongPackMaskModelSO ____songPackMaskModel) + { + string levelPackName = ____joinQuickPlayViewController.multiplayerModeSettings.quickPlaySongPackMaskSerializedName; + Plugin.Log?.Debug(levelPackName); + if (success && ____songPackMaskModel.ToSongPackMask(levelPackName).Contains("custom_levelpack_CustomLevels")) + { + ____simpleDialogPromptViewController.Init( + "Custom Song Quickplay", + "This category includes songs of varying difficulty.\nIt may be more enjoyable to play in a private lobby with friends.", + "Continue", + "Cancel", + delegate (int btnId) + { + switch (btnId) + { + default: + case 0: // Continue + __instance.HandleJoinQuickPlayViewControllerDidFinish(true); + break; + case 1: // Cancel + __instance.InvokeMethod("ReplaceTopViewController", new object[] { + ____joinQuickPlayViewController, null, ViewController.AnimationType.In, ViewController.AnimationDirection.Vertical + }); + break; + } + } + ); + __instance.InvokeMethod("ReplaceTopViewController", new object[] { + ____simpleDialogPromptViewController, null, ViewController.AnimationType.In, ViewController.AnimationDirection.Vertical + }); + return false; + } + return true; + } + } +} diff --git a/MultiplayerExtensions/MultiplayerExtensions.csproj b/MultiplayerExtensions/MultiplayerExtensions.csproj index b2d4385..e157253 100644 --- a/MultiplayerExtensions/MultiplayerExtensions.csproj +++ b/MultiplayerExtensions/MultiplayerExtensions.csproj @@ -35,7 +35,7 @@ True - + @@ -204,7 +204,7 @@ - + diff --git a/MultiplayerExtensions/UI/CenterScreenLoading.bsml b/MultiplayerExtensions/UI/CenterScreenLoading.bsml.dis similarity index 100% rename from MultiplayerExtensions/UI/CenterScreenLoading.bsml rename to MultiplayerExtensions/UI/CenterScreenLoading.bsml.dis diff --git a/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs b/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs index 1c83c91..f6ea771 100644 --- a/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs +++ b/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs @@ -1,46 +1,85 @@ using BeatSaberMarkupLanguage.Attributes; using BeatSaberMarkupLanguage.ViewControllers; +using System; +using System.Linq; using UnityEngine; using UnityEngine.UI; using Zenject; namespace MultiplayerExtensions.UI { - class CenterScreenLoadingPanel : BSMLResourceViewController + class CenterScreenLoadingPanel : MonoBehaviour, IProgress { - public override string ResourceName => "MultiplayerExtensions.UI.CenterScreenLoading.bsml"; + //public override string ResourceName => "MultiplayerExtensions.UI.CenterScreenLoading.bsml"; private IMultiplayerSessionManager sessionManager; private ILobbyGameStateController gameStateController; private CenterStageScreenController screenController; + private LoadingControl? loadingControl; + private bool isDownloading; + public static CenterScreenLoadingPanel? self { get; private set; } [Inject] internal void Inject(IMultiplayerSessionManager sessionManager, ILobbyGameStateController gameStateController, CenterStageScreenController screenController) { + self = this; this.sessionManager = sessionManager; this.gameStateController = gameStateController; this.screenController = screenController; - base.DidActivate(true, false, true); - loadIndicator.color = Color.white; + BeatSaberMarkupLanguage.Tags.VerticalLayoutTag verticalTag = new BeatSaberMarkupLanguage.Tags.VerticalLayoutTag(); + GameObject vertical = verticalTag.CreateObject(transform); + (vertical.transform as RectTransform).sizeDelta = new Vector2(60, 60); + (vertical.transform as RectTransform).anchoredPosition = new Vector2(0.0f, -30.0f); + var layout = vertical.AddComponent().minWidth = 60; + + GameObject existingLoadingControl = Resources.FindObjectsOfTypeAll().First().gameObject; + GameObject loadingControlGameObject = GameObject.Instantiate(existingLoadingControl, vertical.transform); + loadingControl = loadingControlGameObject.GetComponent(); + loadingControl.Hide(); + + //base.DidActivate(true, false, true); + + //loadIndicator.color = Color.white; } - [UIComponent("LoadingDisplay")] - public RectTransform loadingDisplay; + //[UIComponent("LoadingDisplay")] + //public RectTransform loadingDisplay; - [UIComponent("LoadIndicator")] - public Image loadIndicator; + //[UIComponent("LoadIndicator")] + //public Image loadIndicator; public void Update() { - if (screenController.countdownShown && sessionManager.syncTime >= gameStateController.startTime && gameStateController.levelStartInitiated) + if (isDownloading) { - if (loadingDisplay != null) - loadingDisplay.gameObject.SetActive(true); + return; + } + else if (screenController.countdownShown && sessionManager.syncTime >= gameStateController.startTime && gameStateController.levelStartInitiated) + { + if (loadingControl != null) + loadingControl.ShowLoading("Loading..."); + //loadingDisplay.gameObject.SetActive(true); } else { - if (loadingDisplay != null) - loadingDisplay.gameObject.SetActive(false); + if (loadingControl != null) + loadingControl.Hide(); + //loadingDisplay.gameObject.SetActive(false); + } + } + + public void OnDisable() + { + if (loadingControl != null) + loadingControl.Hide(); + } + + public void Report(double value) + { + isDownloading = (value < 1.0); + if (loadingControl != null) + { + loadingControl.ShowDownloadingProgress("Downloading...", (float)value); } } } diff --git a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs index c338774..39f2d17 100644 --- a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs +++ b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs @@ -49,6 +49,7 @@ static HarmonyManager() AddDefaultPatch(); //AddDefaultPatch(); AddDefaultPatch(); + AddDefaultPatch(); } private static void AddDefaultPatch() where T : class From 39d94f1b9886f9a355590d31ebe076e119c6132c Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Fri, 29 Oct 2021 20:33:51 +0200 Subject: [PATCH 36/41] Delete unused bsml file, cleanup --- MultiplayerExtensions/MultiplayerExtensions.csproj | 2 -- .../UI/CenterScreenLoading.bsml.dis | 4 ---- MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs | 12 ------------ 3 files changed, 18 deletions(-) delete mode 100644 MultiplayerExtensions/UI/CenterScreenLoading.bsml.dis diff --git a/MultiplayerExtensions/MultiplayerExtensions.csproj b/MultiplayerExtensions/MultiplayerExtensions.csproj index e157253..403123c 100644 --- a/MultiplayerExtensions/MultiplayerExtensions.csproj +++ b/MultiplayerExtensions/MultiplayerExtensions.csproj @@ -35,7 +35,6 @@ True - @@ -204,7 +203,6 @@ - diff --git a/MultiplayerExtensions/UI/CenterScreenLoading.bsml.dis b/MultiplayerExtensions/UI/CenterScreenLoading.bsml.dis deleted file mode 100644 index 1273729..0000000 --- a/MultiplayerExtensions/UI/CenterScreenLoading.bsml.dis +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs b/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs index f6ea771..2c202ac 100644 --- a/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs +++ b/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs @@ -36,18 +36,8 @@ internal void Inject(IMultiplayerSessionManager sessionManager, ILobbyGameStateC GameObject loadingControlGameObject = GameObject.Instantiate(existingLoadingControl, vertical.transform); loadingControl = loadingControlGameObject.GetComponent(); loadingControl.Hide(); - - //base.DidActivate(true, false, true); - - //loadIndicator.color = Color.white; } - //[UIComponent("LoadingDisplay")] - //public RectTransform loadingDisplay; - - //[UIComponent("LoadIndicator")] - //public Image loadIndicator; - public void Update() { if (isDownloading) @@ -58,13 +48,11 @@ public void Update() { if (loadingControl != null) loadingControl.ShowLoading("Loading..."); - //loadingDisplay.gameObject.SetActive(true); } else { if (loadingControl != null) loadingControl.Hide(); - //loadingDisplay.gameObject.SetActive(false); } } From 80174374e0ca21b7c16031f12b410aa748a32361 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Fri, 29 Oct 2021 20:34:24 +0200 Subject: [PATCH 37/41] Delete one other unused line --- MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs b/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs index 2c202ac..efd9898 100644 --- a/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs +++ b/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs @@ -10,7 +10,6 @@ namespace MultiplayerExtensions.UI { class CenterScreenLoadingPanel : MonoBehaviour, IProgress { - //public override string ResourceName => "MultiplayerExtensions.UI.CenterScreenLoading.bsml"; private IMultiplayerSessionManager sessionManager; private ILobbyGameStateController gameStateController; private CenterStageScreenController screenController; From f639221bb92a20bf5bf7c85f7918ec73960b3984 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sat, 30 Oct 2021 23:48:28 +0200 Subject: [PATCH 38/41] Fix MultiplayerModeSelectionFlowCoordinatorPatch, remove ConnectToMatchmakingPatch --- .../HarmonyPatches/CustomSongsPatches.cs | 12 ------------ .../HarmonyPatches/QuickplayPatches.cs | 5 ++++- .../Utilities/Harmony/HarmonyManager.cs | 1 - 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs b/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs index abd2846..24ac681 100644 --- a/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs @@ -22,18 +22,6 @@ static void Prefix(CreateServerFormData data) } } - [HarmonyPatch(typeof(MultiplayerLobbyConnectionController), nameof(MultiplayerLobbyConnectionController.ConnectToMatchmaking), MethodType.Normal)] - internal class ConnectToMatchmakingPatch - { - /// - /// Modifies the data used to matchmake - /// - static void Prefix(ref SongPackMask songPackMask) - { - if (!MPState.CurrentMasterServer.isOfficial) - songPackMask |= new SongPackMask("custom_levelpack_CustomLevels"); - } - } [HarmonyPatch(typeof(MultiplayerLevelSelectionFlowCoordinator), "enableCustomLevels", MethodType.Getter)] internal class EnableCustomLevelsPatch diff --git a/MultiplayerExtensions/HarmonyPatches/QuickplayPatches.cs b/MultiplayerExtensions/HarmonyPatches/QuickplayPatches.cs index 8844d3b..05ec4c1 100644 --- a/MultiplayerExtensions/HarmonyPatches/QuickplayPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/QuickplayPatches.cs @@ -12,11 +12,12 @@ namespace MultiplayerExtensions.HarmonyPatches [HarmonyPatch(typeof(MultiplayerModeSelectionFlowCoordinator), nameof(MultiplayerModeSelectionFlowCoordinator.HandleJoinQuickPlayViewControllerDidFinish), MethodType.Normal)] internal class MultiplayerModeSelectionFlowCoordinatorPatch { + internal static bool skipCheck = false; static bool Prefix(MultiplayerModeSelectionFlowCoordinator __instance, bool success, JoinQuickPlayViewController ____joinQuickPlayViewController, SimpleDialogPromptViewController ____simpleDialogPromptViewController, SongPackMaskModelSO ____songPackMaskModel) { string levelPackName = ____joinQuickPlayViewController.multiplayerModeSettings.quickPlaySongPackMaskSerializedName; Plugin.Log?.Debug(levelPackName); - if (success && ____songPackMaskModel.ToSongPackMask(levelPackName).Contains("custom_levelpack_CustomLevels")) + if (success && ____songPackMaskModel.ToSongPackMask(levelPackName).Contains("custom_levelpack_CustomLevels") && !skipCheck) { ____simpleDialogPromptViewController.Init( "Custom Song Quickplay", @@ -29,6 +30,7 @@ static bool Prefix(MultiplayerModeSelectionFlowCoordinator __instance, bool succ { default: case 0: // Continue + skipCheck = true; __instance.HandleJoinQuickPlayViewControllerDidFinish(true); break; case 1: // Cancel @@ -44,6 +46,7 @@ static bool Prefix(MultiplayerModeSelectionFlowCoordinator __instance, bool succ }); return false; } + skipCheck = false; return true; } } diff --git a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs index 39f2d17..fa314f8 100644 --- a/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs +++ b/MultiplayerExtensions/Utilities/Harmony/HarmonyManager.cs @@ -23,7 +23,6 @@ static HarmonyManager() { AddDefaultPatch(); AddDefaultPatch(); - AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); AddDefaultPatch(); From a11ad543341b03204c7ab76684b90e105d7300a4 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Wed, 3 Nov 2021 17:16:09 +0100 Subject: [PATCH 39/41] New CenterScreenLoadingPanel, fix HandleMultiplayerLevelLoaderCountdownFinished, add ProtocolVersion --- MultiplayerExtensions/Downloader.cs | 2 +- .../Extensions/ExtendedEntitlementChecker.cs | 4 ++++ .../Extensions/ExtendedGameStateController.cs | 15 +++++++++------ .../Extensions/ExtendedPlayer.cs | 10 +++++----- .../Extensions/ExtendedSessionManager.cs | 8 ++++---- .../MultiplayerExtensions.csproj | 2 +- MultiplayerExtensions/Plugin.cs | 2 ++ .../UI/CenterScreenLoadingPanel.cs | 13 +++++++++---- MultiplayerExtensions/manifest.json | 2 +- 9 files changed, 36 insertions(+), 22 deletions(-) diff --git a/MultiplayerExtensions/Downloader.cs b/MultiplayerExtensions/Downloader.cs index 2e3136e..4845021 100644 --- a/MultiplayerExtensions/Downloader.cs +++ b/MultiplayerExtensions/Downloader.cs @@ -49,7 +49,7 @@ public static bool TryGetDownload(string levelId, out Task { Plugin.Log?.Info($"Version: '{version.Key}' '{version.Hash}'"); return version.Hash.ToUpper() == hash; - }).DownloadZIP(progress: UI.CenterScreenLoadingPanel.self); + }).DownloadZIP(progress: UI.CenterScreenLoadingPanel.Instance); #if DEBUG TimeSpan delay = TimeSpan.FromSeconds(Plugin.Config.DebugConfig?.MinDownloadTime ?? 0) - TimeSpan.FromMilliseconds(sw.ElapsedMilliseconds); if (delay > TimeSpan.Zero) diff --git a/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs b/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs index 6072ef2..5e94467 100644 --- a/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs +++ b/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs @@ -118,7 +118,10 @@ public async Task WaitForOkEntitlement(string userId, string levelId, Cancellati { if (_entitlementsDictionary.TryGetValue(userId, out Dictionary userDictionary)) if (userDictionary.TryGetValue(levelId, out EntitlementsStatus entitlement) && entitlement == EntitlementsStatus.Ok) + { + UI.CenterScreenLoadingPanel.Instance.playersReady++; return; + } if (!_tcsDictionary.ContainsKey(userId)) _tcsDictionary[userId] = new Dictionary>(); @@ -132,6 +135,7 @@ public async Task WaitForOkEntitlement(string userId, string levelId, Cancellati { result = await _tcsDictionary[userId][levelId].Task.ContinueWith(t => t.IsCompleted ? t.Result : EntitlementsStatus.Unknown); _tcsDictionary[userId][levelId] = new TaskCompletionSource(); + if (result == EntitlementsStatus.Ok) UI.CenterScreenLoadingPanel.Instance.playersReady++; } } } diff --git a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs index 7277558..5151155 100644 --- a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs +++ b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs @@ -1,4 +1,5 @@ -using System; +using IPA.Utilities; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -91,7 +92,14 @@ public override void StopLoading() public async override void HandleMultiplayerLevelLoaderCountdownFinished(IPreviewBeatmapLevel previewBeatmapLevel, BeatmapDifficulty beatmapDifficulty, BeatmapCharacteristicSO beatmapCharacteristic, IDifficultyBeatmap difficultyBeatmap, GameplayModifiers gameplayModifiers) { + if (_multiplayerLevelLoader.GetField("_loaderState") == MultiplayerLevelLoader.MultiplayerBeatmapLoaderState.NotLoading) + { + Plugin.Log?.Info("HandleMultiplayerLevelLoaderCountdownFinished already running, returning"); + return; + } + _multiplayerLevelLoader.SetField("_loaderState", MultiplayerLevelLoader.MultiplayerBeatmapLoaderState.NotLoading); Plugin.Log?.Debug("Map finished loading, waiting for other players..."); + UI.CenterScreenLoadingPanel.Instance.playersReady = 0; _menuRpcManager.SetIsEntitledToLevel(previewBeatmapLevel.levelID, EntitlementsStatus.Ok); if (_levelStartedOnTime == false) @@ -116,11 +124,6 @@ public async override void HandleMultiplayerLevelLoaderCountdownFinished(IPrevie Plugin.Log?.Debug("All players ready, starting game."); - Plugin.Log?.Debug($"Null Checking previewBeatmapLevel: '{(previewBeatmapLevel == null ? "null" : "not null")}'"); - Plugin.Log?.Debug($"Null Checking beatmapDifficulty: '{beatmapDifficulty}'"); - Plugin.Log?.Debug($"Null Checking beatmapCharacteristic: '{(beatmapCharacteristic == null ? "null" : "not null")}'"); - Plugin.Log?.Debug($"Null Checking difficultyBeatmap: '{(difficultyBeatmap == null ? "null" : "not null")}'"); - Plugin.Log?.Debug($"Null Checking gameplayModifiers: '{(gameplayModifiers == null ? "null" : "not null")}'"); base.HandleMultiplayerLevelLoaderCountdownFinished(previewBeatmapLevel, beatmapDifficulty, beatmapCharacteristic, difficultyBeatmap, gameplayModifiers); } diff --git a/MultiplayerExtensions/Extensions/ExtendedPlayer.cs b/MultiplayerExtensions/Extensions/ExtendedPlayer.cs index 7c2e6c1..0126b1a 100644 --- a/MultiplayerExtensions/Extensions/ExtendedPlayer.cs +++ b/MultiplayerExtensions/Extensions/ExtendedPlayer.cs @@ -22,7 +22,7 @@ public class ExtendedPlayer : IConnectedPlayer /// /// MultiplayerExtensions version reported by BSIPA. /// - public SemVer.Version mpexVersion; + public Hive.Versioning.Version mpexVersion; /// /// Player's color set in the plugin config. @@ -37,7 +37,7 @@ public class ExtendedPlayer : IConnectedPlayer public ExtendedPlayer(IConnectedPlayer player) { _connectedPlayer = player; - this.mpexVersion = Plugin.PluginMetadata.Version; + this.mpexVersion = Plugin.ProtocolVersion; } public ExtendedPlayer(IConnectedPlayer player, string platformID, Platform platform, Color playerColor) @@ -45,11 +45,11 @@ public ExtendedPlayer(IConnectedPlayer player, string platformID, Platform platf _connectedPlayer = player; this.platformID = platformID; this.platform = platform; - this.mpexVersion = Plugin.PluginMetadata.Version; + this.mpexVersion = Plugin.ProtocolVersion; this.playerColor = playerColor; } - public ExtendedPlayer(IConnectedPlayer player, string platformID, Platform platform, SemVer.Version mpexVersion, Color playerColor) + public ExtendedPlayer(IConnectedPlayer player, string platformID, Platform platform, Hive.Versioning.Version mpexVersion, Color playerColor) { _connectedPlayer = player; this.platformID = platformID; @@ -102,7 +102,7 @@ public void Deserialize(NetDataReader reader) public ExtendedPlayerPacket Init(string platformID, Platform platform, Color playerColor) { this.platformID = platformID; - this.mpexVersion = Plugin.PluginMetadata.Version.ToString(); + this.mpexVersion = Plugin.ProtocolVersion.ToString(); this.playerColor = playerColor; this.platform = platform; return this; diff --git a/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs b/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs index 8249d4b..e69e037 100644 --- a/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs +++ b/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs @@ -92,18 +92,18 @@ private void HandleExtendedPlayerPacket(ExtendedPlayerPacket packet, IConnectedP extendedPlayer.platformID = packet.platformID; extendedPlayer.platform = packet.platform; extendedPlayer.playerColor = packet.playerColor; - extendedPlayer.mpexVersion = new SemVer.Version(packet.mpexVersion); + extendedPlayer.mpexVersion = new Hive.Versioning.Version(packet.mpexVersion); } else { Plugin.Log?.Info($"Received 'ExtendedPlayerPacket' from '{player.userId}' with platformID: '{packet.platformID}' mpexVersion: '{packet.mpexVersion}'"); - ExtendedPlayer extendedPlayer = new ExtendedPlayer(player, packet.platformID, packet.platform, new SemVer.Version(packet.mpexVersion), packet.playerColor); + ExtendedPlayer extendedPlayer = new ExtendedPlayer(player, packet.platformID, packet.platform, new Hive.Versioning.Version(packet.mpexVersion), packet.playerColor); - if (Plugin.PluginMetadata.Version != extendedPlayer.mpexVersion) + if (Plugin.ProtocolVersion != extendedPlayer.mpexVersion) { Plugin.Log?.Warn("###################################################################"); Plugin.Log?.Warn("Different MultiplayerExtensions version detected!"); - Plugin.Log?.Warn($"The player '{player.userName}' is using MultiplayerExtensions {extendedPlayer.mpexVersion} while you are using MultiplayerExtensions {Plugin.PluginMetadata.Version}"); + Plugin.Log?.Warn($"The player '{player.userName}' is using MultiplayerExtensions {extendedPlayer.mpexVersion} while you are using MultiplayerExtensions {Plugin.ProtocolVersion}"); Plugin.Log?.Warn("For best compatibility all players should use the same version of MultiplayerExtensions."); Plugin.Log?.Warn("###################################################################"); } diff --git a/MultiplayerExtensions/MultiplayerExtensions.csproj b/MultiplayerExtensions/MultiplayerExtensions.csproj index 403123c..54e142b 100644 --- a/MultiplayerExtensions/MultiplayerExtensions.csproj +++ b/MultiplayerExtensions/MultiplayerExtensions.csproj @@ -4,7 +4,7 @@ Library Properties MultiplayerExtensions - 0.6.1 + 0.6.2 net472 true portable diff --git a/MultiplayerExtensions/Plugin.cs b/MultiplayerExtensions/Plugin.cs index 83354dc..a724b33 100644 --- a/MultiplayerExtensions/Plugin.cs +++ b/MultiplayerExtensions/Plugin.cs @@ -27,6 +27,8 @@ public class Plugin internal static Plugin Instance { get; private set; } = null!; internal static PluginMetadata PluginMetadata = null!; + + internal static Hive.Versioning.Version ProtocolVersion { get; } = new Hive.Versioning.Version("1.0.0"); internal static IPALogger Log { get; private set; } = null!; internal static PluginConfig Config = null!; diff --git a/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs b/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs index efd9898..cddb249 100644 --- a/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs +++ b/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs @@ -15,20 +15,23 @@ class CenterScreenLoadingPanel : MonoBehaviour, IProgress private CenterStageScreenController screenController; private LoadingControl? loadingControl; private bool isDownloading; - public static CenterScreenLoadingPanel? self { get; private set; } + public int playersReady; + public static CenterScreenLoadingPanel? Instance { get; private set; } [Inject] internal void Inject(IMultiplayerSessionManager sessionManager, ILobbyGameStateController gameStateController, CenterStageScreenController screenController) { - self = this; + Instance = this; this.sessionManager = sessionManager; this.gameStateController = gameStateController; this.screenController = screenController; BeatSaberMarkupLanguage.Tags.VerticalLayoutTag verticalTag = new BeatSaberMarkupLanguage.Tags.VerticalLayoutTag(); GameObject vertical = verticalTag.CreateObject(transform); +#pragma warning disable CS8602 // Dereference of a possibly null reference. (vertical.transform as RectTransform).sizeDelta = new Vector2(60, 60); (vertical.transform as RectTransform).anchoredPosition = new Vector2(0.0f, -30.0f); +#pragma warning restore CS8602 // Dereference of a possibly null reference. var layout = vertical.AddComponent().minWidth = 60; GameObject existingLoadingControl = Resources.FindObjectsOfTypeAll().First().gameObject; @@ -37,7 +40,7 @@ internal void Inject(IMultiplayerSessionManager sessionManager, ILobbyGameStateC loadingControl.Hide(); } - public void Update() + public void FixedUpdate() { if (isDownloading) { @@ -46,12 +49,13 @@ public void Update() else if (screenController.countdownShown && sessionManager.syncTime >= gameStateController.startTime && gameStateController.levelStartInitiated) { if (loadingControl != null) - loadingControl.ShowLoading("Loading..."); + loadingControl.ShowLoading($"{playersReady + 1} of {(sessionManager.connectedPlayerCount + 1)} players ready..."); } else { if (loadingControl != null) loadingControl.Hide(); + playersReady = 0; } } @@ -59,6 +63,7 @@ public void OnDisable() { if (loadingControl != null) loadingControl.Hide(); + playersReady = 0; } public void Report(double value) diff --git a/MultiplayerExtensions/manifest.json b/MultiplayerExtensions/manifest.json index af15bce..b4906b1 100644 --- a/MultiplayerExtensions/manifest.json +++ b/MultiplayerExtensions/manifest.json @@ -3,7 +3,7 @@ "id": "MultiplayerExtensions", "name": "MultiplayerExtensions", "author": "Zingabopp and Goobwabber", - "version": "0.6.1", + "version": "0.6.2", "description": "Expands the functionality of Beat Saber Multiplayer.", "gameVersion": "1.17.1", "dependsOn": { From 4f61ec7fdf5b8226c4b13f07fcf609ea73057d2c Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sat, 13 Nov 2021 16:33:02 +0100 Subject: [PATCH 40/41] Check requirements, added State for having specific mods installed (currently needed on Quest), Fix, LagReducer disabling zenMode when enabled, added percentage to download indicator --- .../Extensions/ExtendedEntitlementChecker.cs | 33 ++++++++++++++++++- .../Extensions/ExtendedSessionManager.cs | 4 +++ .../HarmonyPatches/InstallerPatches.cs | 3 +- MultiplayerExtensions/Plugin.cs | 11 ++++++- .../UI/CenterScreenLoadingPanel.cs | 2 +- 5 files changed, 49 insertions(+), 4 deletions(-) diff --git a/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs b/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs index 5e94467..d049183 100644 --- a/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs +++ b/MultiplayerExtensions/Extensions/ExtendedEntitlementChecker.cs @@ -1,6 +1,7 @@ using BeatSaverSharp.Models; using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Zenject; @@ -75,12 +76,40 @@ public override Task GetEntitlementStatus(string levelId) return base.GetEntitlementStatus(levelId); if (SongCore.Collections.songWithHashPresent(hash)) + { + // The input parameter for RetrieveExtraSongData is called levelId but it only takes the level hash + var extraSongData = SongCore.Collections.RetrieveExtraSongData(hash); + if (extraSongData != null) + { + foreach (var difficultyData in extraSongData._difficulties) + { + if (difficultyData.additionalDifficultyData != null && + ((difficultyData.additionalDifficultyData._requirements.Contains("Noodle Extensions") && !Plugin.IsNoodleInstalled) || + (difficultyData.additionalDifficultyData._requirements.Contains("Mapping Extensions") && !Plugin.IsMappingInstalled))) + return Task.FromResult(EntitlementsStatus.NotOwned); + else if (difficultyData.additionalDifficultyData != null) + { + foreach (string requirement in difficultyData.additionalDifficultyData._requirements) Plugin.Log?.Info($"Requirement found: {requirement}"); + } + else Plugin.Log?.Debug("difficultyData.additionalDifficultyData is null"); + + } + } + else Plugin.Log?.Debug("extraSongData is null"); return Task.FromResult(EntitlementsStatus.Ok); + } return Plugin.BeatSaver.BeatmapByHash(hash).ContinueWith(r => { Beatmap? beatmap = r.Result; if (beatmap == null) return EntitlementsStatus.NotOwned; + else + { + foreach (var difficulty in beatmap.Versions[0].Difficulties) + { + if ((difficulty.NoodleExtensions && !Plugin.IsNoodleInstalled) || (difficulty.MappingExtensions && !Plugin.IsMappingInstalled)) return EntitlementsStatus.NotOwned; + } + } return EntitlementsStatus.NotDownloaded; }); } @@ -120,6 +149,7 @@ public async Task WaitForOkEntitlement(string userId, string levelId, Cancellati if (userDictionary.TryGetValue(levelId, out EntitlementsStatus entitlement) && entitlement == EntitlementsStatus.Ok) { UI.CenterScreenLoadingPanel.Instance.playersReady++; + Plugin.Log?.Info($"User '{userId}' for level '{levelId}' is '{entitlement}'"); return; } @@ -135,8 +165,9 @@ public async Task WaitForOkEntitlement(string userId, string levelId, Cancellati { result = await _tcsDictionary[userId][levelId].Task.ContinueWith(t => t.IsCompleted ? t.Result : EntitlementsStatus.Unknown); _tcsDictionary[userId][levelId] = new TaskCompletionSource(); - if (result == EntitlementsStatus.Ok) UI.CenterScreenLoadingPanel.Instance.playersReady++; } + if (!cancellationToken.IsCancellationRequested) UI.CenterScreenLoadingPanel.Instance.playersReady++; + Plugin.Log?.Info($"User '{userId}' for level '{levelId}' is '{result}' was task cancelled {(cancellationToken.IsCancellationRequested ? "true" : "false")}"); } } } diff --git a/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs b/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs index e69e037..e51c1fe 100644 --- a/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs +++ b/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs @@ -37,6 +37,10 @@ internal void Inject([InjectOptional] PacketManager packetManager, [InjectOption SetLocalPlayerState("modded", true); + SetLocalPlayerState("ME_Installed", Plugin.IsMappingInstalled); + SetLocalPlayerState("NE_Installed", Plugin.IsNoodleInstalled); + SetLocalPlayerState("Chroma_Installed", Plugin.IsChromaInstalled); + connectedEvent += HandleConnected; playerConnectedEvent += HandlePlayerConnected; diff --git a/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs b/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs index 41a0b30..9a237f9 100644 --- a/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs +++ b/MultiplayerExtensions/HarmonyPatches/InstallerPatches.cs @@ -1,4 +1,5 @@ using HarmonyLib; +using IPA.Utilities; using MultiplayerExtensions.Extensions; using System; using System.Collections.Generic; @@ -145,7 +146,7 @@ internal static void Prefix(ref GameplayCoreInstaller __instance, ref IConnected ____sceneSetupData = new GameplayCoreSceneSetupData( ____sceneSetupData.difficultyBeatmap, ____sceneSetupData.previewBeatmapLevel, - ____sceneSetupData.gameplayModifiers.CopyWith(zenMode: Plugin.Config.LagReducer), + ____sceneSetupData.gameplayModifiers.CopyWith(zenMode: (____sceneSetupData.gameplayModifiers.zenMode || Plugin.Config.LagReducer)), ____sceneSetupData.playerSpecificSettings, ____sceneSetupData.practiceSettings, ____sceneSetupData.useTestNoteCutSoundEffects, diff --git a/MultiplayerExtensions/Plugin.cs b/MultiplayerExtensions/Plugin.cs index a724b33..c66d177 100644 --- a/MultiplayerExtensions/Plugin.cs +++ b/MultiplayerExtensions/Plugin.cs @@ -28,7 +28,11 @@ public class Plugin internal static Plugin Instance { get; private set; } = null!; internal static PluginMetadata PluginMetadata = null!; - internal static Hive.Versioning.Version ProtocolVersion { get; } = new Hive.Versioning.Version("1.0.0"); + internal static bool IsNoodleInstalled { get; private set; } + internal static bool IsMappingInstalled { get; private set; } + internal static bool IsChromaInstalled { get; private set; } + + internal static Hive.Versioning.Version ProtocolVersion { get; } = new Hive.Versioning.Version("0.7.1"); internal static IPALogger Log { get; private set; } = null!; internal static PluginConfig Config = null!; @@ -84,6 +88,11 @@ public void OnApplicationStart() HarmonyManager.ApplyDefaultPatches(); Task versionTask = CheckVersion(); + + IsNoodleInstalled = IPA.Loader.PluginManager.IsEnabled(IPA.Loader.PluginManager.GetPluginFromId("NoodleExtensions")); + IsMappingInstalled = IPA.Loader.PluginManager.IsEnabled(IPA.Loader.PluginManager.GetPluginFromId("MappingExtensions")); + IsChromaInstalled = IPA.Loader.PluginManager.IsEnabled(IPA.Loader.PluginManager.GetPluginFromId("Chroma")); + MPEvents_Test(); Sprites.PreloadSprites(); diff --git a/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs b/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs index cddb249..832932b 100644 --- a/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs +++ b/MultiplayerExtensions/UI/CenterScreenLoadingPanel.cs @@ -71,7 +71,7 @@ public void Report(double value) isDownloading = (value < 1.0); if (loadingControl != null) { - loadingControl.ShowDownloadingProgress("Downloading...", (float)value); + loadingControl.ShowDownloadingProgress($"Downloading ({value * 100:F2}%)...", (float)value); } } } From f1046f8124137bfbfe2e8f3dfa9fe22d5dee6547 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 14 Nov 2021 12:46:30 +0100 Subject: [PATCH 41/41] Small changes, remove unused code, allow for live color updating --- .../Extensions/ExtendedGameStateController.cs | 1 - .../Extensions/ExtendedSessionManager.cs | 7 ++++--- MultiplayerExtensions/Plugin.cs | 17 +---------------- 3 files changed, 5 insertions(+), 20 deletions(-) diff --git a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs index 5151155..010a5bf 100644 --- a/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs +++ b/MultiplayerExtensions/Extensions/ExtendedGameStateController.cs @@ -94,7 +94,6 @@ public async override void HandleMultiplayerLevelLoaderCountdownFinished(IPrevie { if (_multiplayerLevelLoader.GetField("_loaderState") == MultiplayerLevelLoader.MultiplayerBeatmapLoaderState.NotLoading) { - Plugin.Log?.Info("HandleMultiplayerLevelLoaderCountdownFinished already running, returning"); return; } _multiplayerLevelLoader.SetField("_loaderState", MultiplayerLevelLoader.MultiplayerBeatmapLoaderState.NotLoading); diff --git a/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs b/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs index e51c1fe..33d61b0 100644 --- a/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs +++ b/MultiplayerExtensions/Extensions/ExtendedSessionManager.cs @@ -97,6 +97,7 @@ private void HandleExtendedPlayerPacket(ExtendedPlayerPacket packet, IConnectedP extendedPlayer.platform = packet.platform; extendedPlayer.playerColor = packet.playerColor; extendedPlayer.mpexVersion = new Hive.Versioning.Version(packet.mpexVersion); + extendedPlayerConnectedEvent?.Invoke(extendedPlayer); } else { @@ -106,9 +107,9 @@ private void HandleExtendedPlayerPacket(ExtendedPlayerPacket packet, IConnectedP if (Plugin.ProtocolVersion != extendedPlayer.mpexVersion) { Plugin.Log?.Warn("###################################################################"); - Plugin.Log?.Warn("Different MultiplayerExtensions version detected!"); - Plugin.Log?.Warn($"The player '{player.userName}' is using MultiplayerExtensions {extendedPlayer.mpexVersion} while you are using MultiplayerExtensions {Plugin.ProtocolVersion}"); - Plugin.Log?.Warn("For best compatibility all players should use the same version of MultiplayerExtensions."); + Plugin.Log?.Warn("Different MultiplayerExtensions protocol detected!"); + Plugin.Log?.Warn($"The player '{player.userName}' is using MpEx protocol version {extendedPlayer.mpexVersion} while you are using MpEx protocol {Plugin.ProtocolVersion}"); + Plugin.Log?.Warn("For best compatibility all players should use a compatible version of MultiplayerExtensions/MultiQuestensions."); Plugin.Log?.Warn("###################################################################"); } diff --git a/MultiplayerExtensions/Plugin.cs b/MultiplayerExtensions/Plugin.cs index c66d177..f45449c 100644 --- a/MultiplayerExtensions/Plugin.cs +++ b/MultiplayerExtensions/Plugin.cs @@ -3,20 +3,16 @@ using IPA.Config; using IPA.Config.Stores; using IPA.Loader; -using MultiplayerExtensions.HarmonyPatches; using MultiplayerExtensions.Installers; using SiraUtil.Zenject; using MultiplayerExtensions.Utilities; using System; -using System.Reflection; using System.Threading.Tasks; using IPALogger = IPA.Logging.Logger; using BeatSaverSharp; using System.Diagnostics; -using Zenject; using MultiplayerExtensions.UI; using BeatSaberMarkupLanguage.Settings; -using System.Net.Http; namespace MultiplayerExtensions { @@ -36,7 +32,6 @@ public class Plugin internal static IPALogger Log { get; private set; } = null!; internal static PluginConfig Config = null!; - internal static HttpClient HttpClient { get; private set; } = null!; internal static BeatSaver BeatSaver = null!; internal static Harmony? _harmony; internal static Harmony Harmony @@ -47,15 +42,6 @@ internal static Harmony Harmony } } - public static string UserAgent - { - get - { - var modVersion = PluginMetadata.Version.ToString(); - var bsVersion = IPA.Utilities.UnityGame.GameVersion.ToString(); - return $"MultiplayerExtensions/{modVersion} (BeatSaber/{bsVersion})"; - } - } private const int MaxPlayers = 100; private const int MinPlayers = 10; @@ -73,9 +59,8 @@ public Plugin(IPALogger logger, Config conf, Zenjector zenjector, PluginMetadata zenjector.OnGame().OnlyForMultiplayer(); BeatSaverOptions options = new BeatSaverOptions("MultiplayerExtensions", new Version(pluginMetadata.Version.ToString())); + options.Timeout = TimeSpan.FromMinutes(1); BeatSaver = new BeatSaver(options); - HttpClient = new HttpClient(); - HttpClient.DefaultRequestHeaders.Add("User-Agent", Plugin.UserAgent); } [OnStart]