Lightweight, strongly typed pub/sub messenger for game loops. GameMessenger lets systems talk without tight coupling and supports both immediate and queued (pumpable) delivery.
- Strongly typed subscribe/publish API with
SubscriptionTokenfor safe unsubscription - Immediate delivery or queued delivery you process later with
PumpQueued - Handlers can unsubscribe themselves while messages are flowing (dispatch uses snapshots)
- Tiny surface area:
IGameMessenger,GameMessenger,Delivery,SubscriptionToken
- Reference the library (package name
OliveGameStudio.Messengerwhen published) or add the project directly:dotnet add package OliveGameStudio.Messenger # or dotnet add reference src/OliveGameStudio.Messenger.csproj - Create a messenger and subscribe:
using OliveGameStudio; var messenger = new GameMessenger(); var spawnedToken = messenger.Subscribe<PlayerSpawned>(msg => { Console.WriteLine($"Spawned {msg.Id} at {msg.Position}"); }); messenger.Publish(new PlayerSpawned("alpha", (0, 0))); // For queued subscriptions, call PumpQueued() each frame to flush the queue.
Delivery.Immediate: handlers fire as soon asPublishis called.Delivery.EndOfFrame: handlers are queued; callPumpQueued()(e.g., once per frame) to run them.
Example mixing both:
var messenger = new GameMessenger();
// Immediate handler
messenger.Subscribe<DamageTaken>(d => Console.WriteLine($"HP - {d.Amount}"), Delivery.Immediate);
// Queued handler (batch damage at end of frame)
messenger.Subscribe<DamageTaken>(d => pendingDamage += d.Amount, Delivery.EndOfFrame);
messenger.Publish(new DamageTaken(5));
// Later in the frame loop
messenger.PumpQueued();Keep the SubscriptionToken to remove a handler later:
var token = messenger.Subscribe<InputEvent>(_ => HandleInput(), Delivery.Immediate);
// ... when no longer needed
messenger.Unsubscribe<InputEvent>(token);GameMessenger is not thread-safe; interact with it from the same thread (typically your main game loop).
cd src
dotnet build OliveGameStudio.Messenger.csprojAdd your license information here.