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