EventBusService
Typed publish/subscribe event bus for cross-mod communication.
What is it for?
Vintage Story mods communicate through direct ModSystem references or watched attributes. EventBusService provides a typed pub/sub channel: mods can publish events without knowing who subscribes, and subscribe to event types without a hard reference to the publisher.
When to use it
- Notify other mods when something happens in your mod (player death, combat, objective completion).
- React to events from another mod without adding a project reference.
- Decouple systems that would otherwise call each other directly.
Quick example
Define an event
using ArcanumLib.Events;
public record PlayerKilledEvent : IEvent
{
public string VictimUid { get; init; } = "";
public string KillerUid { get; init; } = "";
public string Cause { get; init; } = "";
}
Subscribe
using ArcanumLib.Core;
using ArcanumLib.Events;
var bus = ArcanumServices.Get<IEventBusService>();
var sub = bus!.Subscribe<PlayerKilledEvent>(e =>
{
ArcanumServices.Get<ICoreAPI>()?.Logger.Notification("Player {0} was killed by {1}", e.VictimUid, e.KillerUid);
});
// Later: sub.Dispose() unsubscribes.
// Or add to a CleanupScope / EventScope.
Publish
bus!.Publish(new PlayerKilledEvent
{
VictimUid = victim.PlayerUID,
KillerUid = killer?.PlayerUID ?? "environment",
Cause = "falling"
});
API overview
Subscribe<T>(Action<T> handler, EventBusPriority priority)
Subscribes a handler to events of type T. Returns an EventBusSubscription that unsubscribes on dispose.
| Parameter | Type | Description |
|---|---|---|
handler | Action<T> | Called when an event of type T is published. |
priority | EventBusPriority | Higher priority handlers run first. Default is Normal. |
Publish<T>(T evt)
Publishes an event to all subscribers of type T. Handlers run synchronously in priority order. Exceptions in one handler do not block subsequent handlers.
Returns the number of handlers invoked.
PublishAsync<T>(T evt)
Publishes an event on the next game tick, marshalled to the main thread. Use this when handlers may touch entities or world state that must be accessed on the main thread. If no API/world is available, falls back to synchronous publish.
Returns the number of handlers that will be invoked.
Clear<T>()
Removes all subscriptions for event type T.
ClearAll()
Removes all subscriptions for all event types. Intended for world shutdown.
SubscriberCount<T>()
Returns the number of active subscriptions for event type T.
GetDiagnostics()
Returns a list of EventBusSubscriptionInfo records for every tracked subscription, including invocation count, average time, and last error. See Diagnostics for details.
GetDanglingSubscriptions()
Returns a list of subscription keys (EventType[Tag]) that have active subscribers but were never published. Useful for detecting typo’d event names.
ActiveSubscriptionCount()
Returns the total number of active (non-disposed) subscriptions across all event types and tags.
EventBusPriority
| Value | Description |
|---|---|
Low | Runs after normal-priority handlers. |
Normal | Default. |
High | Runs before normal-priority handlers. |
Highest | Runs first. |
Notes
- Thread-safe: all operations are lock-guarded.
EventBusSubscriptionimplementsIDisposable— add it to aCleanupScopefor automatic cleanup.- Exceptions in handlers are logged and swallowed so one bad handler doesn’t break the bus.
- Events are plain classes or records implementing
IEvent(a marker interface). - The service is registered in
ArcanumServicesbyArcanumLibModSystemduring startup and disposed on world unload.