diff --git a/SSMP/Api/Client/IUiManager.cs b/SSMP/Api/Client/IUiManager.cs index e4a35c0..049c0dd 100644 --- a/SSMP/Api/Client/IUiManager.cs +++ b/SSMP/Api/Client/IUiManager.cs @@ -1,3 +1,5 @@ +using System; + namespace SSMP.Api.Client; /// @@ -8,4 +10,41 @@ public interface IUiManager { /// The message box that shows information related to SSMP. /// IChatBox ChatBox { get; } + + /// + /// Fired when the multiplayer button is pressed, before any blocking hooks run. + /// Use this for fire-and-forget reactions such as logging or showing a notification. + /// + event Action? MultiplayerButtonPressed; + + /// + /// Registers a hook that is invoked when the multiplayer button is pressed. + /// + /// + /// Hooks are executed in reverse order (last registered runs first). + /// + /// Example (informational hook): + /// + /// RegisterMultiplayerMenuHook(next => { + /// MyNonMandatoryDependencyPopup.Show( + /// "Addon X unavailable", + /// onAccept: _ => {continue; }, + /// onDecline: _ => { continue; }); + /// }); + /// + /// + /// Example (blocking hook): + /// + /// RegisterMultiplayerMenuHook(next => { + /// MyMandatoryDependencyPopup.Show( + /// "Addon X unavailable", + /// onConfirm: agreed => { if (agreed) continue; }); + /// onDecline: agreed => { if (!agreed) return; }); + /// }); + /// + /// + /// + /// The hook to register. Receives a callback to invoke when ready to proceed. + /// + void RegisterMultiplayerMenuHook(Action hook); } diff --git a/SSMP/Ui/UiManager.cs b/SSMP/Ui/UiManager.cs index a0d1219..29292a8 100644 --- a/SSMP/Ui/UiManager.cs +++ b/SSMP/Ui/UiManager.cs @@ -142,6 +142,9 @@ internal class UiManager : IUiManager { /// public event Action? RequestClientDisconnectEvent; + /// + public event Action? MultiplayerButtonPressed; + #endregion #region Fields @@ -207,6 +210,12 @@ internal class UiManager : IUiManager { /// private bool _isSlotSelectionActive; + /// + /// The head of the multiplayer menu hook chain. + /// Starts as the bare transition; each registered hook wraps it. + /// + private Action _multiplayerMenuChain; + #endregion #region Properties @@ -243,6 +252,13 @@ public IChatBox ChatBox { public UiManager(ModSettings modSettings, NetClient netClient) { _modSettings = modSettings; _netClient = netClient; + _multiplayerMenuChain = () => UM.StartCoroutine(GoToMultiplayerMenu()); + } + + /// + public void RegisterMultiplayerMenuHook(Action hook) { + var previous = _multiplayerMenuChain; + _multiplayerMenuChain = () => hook(previous); } #endregion @@ -738,7 +754,7 @@ private void ConfigureButtonTriggers(GameObject button) { if (eventTrigger == null) return; eventTrigger.triggers.Clear(); - AddButtonTriggers(eventTrigger, () => UM.StartCoroutine(GoToMultiplayerMenu())); + AddButtonTriggers(eventTrigger, OnMultiplayerMenuRequested); } /// @@ -777,6 +793,14 @@ private void SetNavigation(MenuButton button, MenuButton? selectOnUp = null, Men button.navigation = nav; } + /// + /// Handles the multiplayer menu request by firing the notification event, then invoking the hook chain. + /// + private void OnMultiplayerMenuRequested() { + MultiplayerButtonPressed?.Invoke(); + _multiplayerMenuChain.Invoke(); + } + #endregion #region Menu Navigation