diff --git a/Dalamud/Game/Network/GameNetwork.cs b/Dalamud/Game/Network/GameNetwork.cs
index 2b6630c8b..f56fd3996 100644
--- a/Dalamud/Game/Network/GameNetwork.cs
+++ b/Dalamud/Game/Network/GameNetwork.cs
@@ -1,4 +1,3 @@
-using System;
using System.Runtime.InteropServices;
using Dalamud.Configuration.Internal;
@@ -14,13 +13,9 @@ namespace Dalamud.Game.Network;
///
/// This class handles interacting with game network events.
///
-[PluginInterface]
[InterfaceVersion("1.0")]
[ServiceManager.BlockingEarlyLoadedService]
-#pragma warning disable SA1015
-[ResolveVia]
-#pragma warning restore SA1015
-public sealed class GameNetwork : IDisposable, IServiceType, IGameNetwork
+internal sealed class GameNetwork : IDisposable, IServiceType, IGameNetwork
{
private readonly GameNetworkAddressResolver address;
private readonly Hook processZonePacketDownHook;
@@ -57,14 +52,10 @@ public sealed class GameNetwork : IDisposable, IServiceType, IGameNetwork
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate byte ProcessZonePacketUpDelegate(IntPtr a1, IntPtr dataPtr, IntPtr a3, byte a4);
- ///
- /// Event that is called when a network message is sent/received.
- ///
- public event IGameNetwork.OnNetworkMessageDelegate NetworkMessage;
+ ///
+ public event IGameNetwork.OnNetworkMessageDelegate? NetworkMessage;
- ///
- /// Dispose of managed and unmanaged resources.
- ///
+ ///
void IDisposable.Dispose()
{
this.processZonePacketDownHook.Dispose();
@@ -148,3 +139,38 @@ public sealed class GameNetwork : IDisposable, IServiceType, IGameNetwork
return this.processZonePacketUpHook.Original(a1, dataPtr, a3, a4);
}
}
+
+///
+/// Plugin-scoped version of a AddonLifecycle service.
+///
+[PluginInterface]
+[InterfaceVersion("1.0")]
+[ServiceManager.ScopedService]
+#pragma warning disable SA1015
+[ResolveVia]
+#pragma warning restore SA1015
+internal class GameNetworkPluginScoped : IDisposable, IServiceType, IGameNetwork
+{
+ [ServiceManager.ServiceDependency]
+ private readonly GameNetwork gameNetworkService = Service.Get();
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ internal GameNetworkPluginScoped()
+ {
+ this.gameNetworkService.NetworkMessage += this.NetworkMessageForward;
+ }
+
+ ///
+ public event IGameNetwork.OnNetworkMessageDelegate? NetworkMessage;
+
+ ///
+ public void Dispose()
+ {
+ this.gameNetworkService.NetworkMessage -= this.NetworkMessageForward;
+ }
+
+ private void NetworkMessageForward(nint dataPtr, ushort opCode, uint sourceActorId, uint targetActorId, NetworkMessageDirection direction)
+ => this.NetworkMessage?.Invoke(dataPtr, opCode, sourceActorId, targetActorId, direction);
+}