Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 62 additions & 11 deletions SSMP/Networking/Packet/PacketHandlerRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ internal class PacketHandlerRegistry<TPacketId, THandler>
private readonly Dictionary<TPacketId, THandler> _handlers = new();

/// <summary>
/// Whether to dispatch handler invocations to the Unity main thread.
/// Client handlers typically need main thread dispatch; server handlers do not.
/// The dispatcher that handles how to call the packet handlers.
/// For clients, this will be the <see cref="ClientPacketHandlerRegistryDispatcher"/>, which invokes packet
/// handlers on the Unity main thread.
/// For servers, this will be the <see cref="ServerPacketHandlerRegistryDispatcher"/>, which directly invokes the
/// packet handlers.
/// </summary>
private readonly bool _dispatchToMainThread;
private readonly IPacketHandlerRegistryDispatcher _dispatcher;

/// <summary>
/// Descriptive name for logging messages.
Expand All @@ -35,10 +38,10 @@ internal class PacketHandlerRegistry<TPacketId, THandler>
/// Constructs a new packet handler registry.
/// </summary>
/// <param name="registryName">Name for logging purposes (e.g., "client update", "server connection").</param>
/// <param name="dispatchToMainThread">Whether to dispatch handler calls to Unity main thread.</param>
public PacketHandlerRegistry(string registryName, bool dispatchToMainThread) {
/// <param name="dispatcher">The dispatcher that handles how to call the packet handlers.</param>
public PacketHandlerRegistry(string registryName, IPacketHandlerRegistryDispatcher dispatcher) {
_registryName = registryName;
_dispatchToMainThread = dispatchToMainThread;
_dispatcher = dispatcher;
}

/// <summary>
Expand Down Expand Up @@ -77,11 +80,7 @@ public void Execute(TPacketId packetId, Action<THandler> invoker) {
return;
}

if (_dispatchToMainThread) {
ThreadUtil.RunActionOnMainThread(() => SafeInvoke(packetId, handler, invoker));
} else {
SafeInvoke(packetId, handler, invoker);
}
_dispatcher.Dispatch(() => SafeInvoke(packetId, handler, invoker));
}

/// <summary>
Expand All @@ -95,3 +94,55 @@ private void SafeInvoke(TPacketId packetId, THandler handler, Action<THandler> i
}
}
}

/// <summary>
/// Interface for packet handler dispatchers.
/// </summary>
internal interface IPacketHandlerRegistryDispatcher {
/// <summary>
/// Dispatch this handler with the given action.
/// </summary>
void Dispatch(Action action);
}

/// <summary>
/// Implementation of packet handler dispatcher to immediately invoke the handler directly for the server-side.
/// </summary>
internal class ServerPacketHandlerRegistryDispatcher : IPacketHandlerRegistryDispatcher {
/// <summary>
/// Publicly accessible static instance, since instances can not vary.
/// </summary>
public static readonly ServerPacketHandlerRegistryDispatcher Instance = new();

/// <summary>
/// Private constructor to prevent access outside of static instance.
/// </summary>
private ServerPacketHandlerRegistryDispatcher() {
}

/// <inheritdoc/>
public void Dispatch(Action action) {
action.Invoke();
}
}

/// <summary>
/// Implementation of packet handler dispatcher to invoke the handler on Unity's main thread.
/// </summary>
internal class ClientPacketHandlerRegistryDispatcher : IPacketHandlerRegistryDispatcher {
/// <summary>
/// Publicly accessible static instance, since instances can not vary.
/// </summary>
public static readonly ClientPacketHandlerRegistryDispatcher Instance = new();

/// <summary>
/// Private constructor to prevent access outside of static instance.
/// </summary>
private ClientPacketHandlerRegistryDispatcher() {
}

/// <inheritdoc/>
public void Dispatch(Action action) {
ThreadUtil.RunActionOnMainThread(action);
}
}
12 changes: 6 additions & 6 deletions SSMP/Networking/Packet/PacketManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,16 @@ internal class PacketManager {
#region Standard Packet Registries

private readonly PacketHandlerRegistry<ClientUpdatePacketId, ClientPacketHandler> _clientUpdateRegistry = new(
"client update", true
"client update", ClientPacketHandlerRegistryDispatcher.Instance
);
private readonly PacketHandlerRegistry<ClientConnectionPacketId, ClientPacketHandler> _clientConnectionRegistry = new(
"client connection", true
"client connection", ClientPacketHandlerRegistryDispatcher.Instance
);
private readonly PacketHandlerRegistry<ServerUpdatePacketId, ServerPacketHandler> _serverUpdateRegistry = new(
"server update", false
"server update", ServerPacketHandlerRegistryDispatcher.Instance
);
private readonly PacketHandlerRegistry<ServerConnectionPacketId, ServerPacketHandler> _serverConnectionRegistry = new(
"server connection", false
"server connection", ServerPacketHandlerRegistryDispatcher.Instance
);

#endregion
Expand Down Expand Up @@ -268,7 +268,7 @@ string nameType
) {
if (!registryDict.TryGetValue(addonId, out var registry)) {
registry = new PacketHandlerRegistry<byte, ClientPacketHandler>(
$"client addon {nameType} (Addon {addonId})", true
$"client addon {nameType} (Addon {addonId})", ClientPacketHandlerRegistryDispatcher.Instance
);
registryDict[addonId] = registry;
}
Expand Down Expand Up @@ -323,7 +323,7 @@ string nameType
) {
if (!registryDict.TryGetValue(addonId, out var registry)) {
registry = new PacketHandlerRegistry<byte, ServerPacketHandler>(
$"server addon {nameType} (Addon {addonId})", false
$"server addon {nameType} (Addon {addonId})", ServerPacketHandlerRegistryDispatcher.Instance
);
registryDict[addonId] = registry;
}
Expand Down
Loading