Frostdev

KilnWikiModding

Events

One event bus for every mod and service: subscribe, cancel, decide, post your own. About 110 event types.

Works today 4 min read Updated

Kiln has one event bus, Events, like Forge’s EVENT_BUS. Kiln’s services post about 110 event types on it: players, combat, chat, crafting, building, quests, world progress and more. Mods post their own on the same bus.

Subscribe

public sealed class MyMod : Mod
{
    [Subscribe]                                          // registered before OnLoad, removed on unload
    private void OnJoin(PlayerJoinedEvent e) => Log.Info($"{e.Player.Name} joined");

    [Subscribe(EventPriority.High)]
    private void OnChat(ChatMessageEvent e) { if (e.Text.Contains("spoiler")) e.Cancel(); }

    public override void OnLoad()
    {
        var sub = Events.On<EntityDeathEvent>(e => Log.Info($"{e.Victim} killed by {e.Killer}"));
        // sub.Dispose() stops it early; unloading the mod stops it anyway
    }
}
  • [Subscribe] on a method of your Mod class, or Events.On<T>(handler, priority, receiveCanceled). Events.Register(obj) picks up the [Subscribe] methods of any object.
  • Order: Highest, High, Normal, Low, Lowest, then Monitor (for looking, not changing). Same priority: in the order they subscribed.
  • A handler for a base class gets every event derived from it.
  • Every subscription of a mod ends when it unloads, so hot reload needs no clean-up.
  • A handler that throws is logged and the others still run. After 5 faults it’s removed.

Cancel and decide

Some events can be stopped, some can be changed, and some ask a question.

Kind What you do Example
cancelable e.Cancel(). Later handlers are skipped unless they subscribed with ReceiveCanceled = true; those may un-cancel a chat line nobody sees, a hit that never happens
with values change a field before the game uses it EntityHurtEvent.Amount, EntityFallEvent.Damage, ChatMessageEvent.Text
result e.Allow(), e.Deny(), or leave it Default for the game’s own answer DialogueKnowledgeEvent, KnowledgeRequestEvent

e.CanceledBy says which mod canceled.

[Subscribe] private void OnHurt(EntityHurtEvent e) { if (e.IsPlayer && InSafeZone(e.Position)) e.Cancel(); else e.Amount /= 2; }
[Subscribe] private void OnFall(EntityFallEvent e) => e.Damage /= 2;
[Subscribe] private void OnToss(ItemTossEvent e) { if (IsQuestItem(e.ItemId)) e.Cancel(); }

The event families

The main types. Each service’s page or the API reference has the rest.

Family Events Can cancel or change
Lifecycle ModsLoadedEvent, ServerStartingEvent, ServerStartedEvent, ServerStoppingEvent, WorldLoadedEvent, WorldSavingEvent, WorldSavedEvent, ModReloadedEvent, ModDisabledEvent, ConfigChangedEvent
Players PlayerJoinedEvent, PlayerLeftEvent, PlayerLevelChangedEvent, PlayerSkillsChangedEvent, PlayerEquipmentChangedEvent, PlayerHotbarChangedEvent
Player states and actions PlayerStateChangedEvent (glide, swim, climb, sit, sleep, Shroud and about 340 more), PlayerActionEvent (attack, cast, dodge, jump, use, interact), PlayerConsumeEvent, PlayerConsumedEvent, PlayerJumpEvent, PlayerGlideEvent, PlayerClientActionEvent an action, a meal, some client commands
Combat EntityHurtEvent, EntityHealEvent, EntityKnockbackEvent, EntityFallEvent, EntityDamagedEvent, EntityDeathEvent, EntityDropsEvent, PlayerRespawnEvent hurt, heal, knockback, fall (amounts too), drops
Chat and commands ChatMessageEvent, CommandExecutingEvent, CommandExecutedEvent a line (and its text), a command
World and gameplay CraftEvent, ItemCraftedEvent, InteractEvent, LootEvent, ItemPickupEvent, ItemTossEvent, BuildEvent, TeleportEvent (also redirect), NaturalSpawnEvent, EntityJoinLevelEvent, EntityLeaveLevelEvent craft, interact, loot, toss, teleport, spawns
Building BuildEditingEvent, BuildEditEvent an edit
Items ItemsGivenEvent, ItemsTakenEvent, WaterRefilledEvent
Abilities and programs AbilityCastEvent, AbilityCastedEvent, ImpactStartingEvent, ImpactStartedEvent, ImpactEndedEvent, ImpactDamageEvent, ImpactBuffEvent, SequenceStartedEvent a cast, a program starting
Talents TalentUnlockingEvent, TalentChangedEvent, GameNodesRefundedEvent an unlock
Quests and dialogue QuestStartedEvent, QuestStepEvent, QuestCompletedEvent, QuestFailedEvent, QuestObjectiveProgressEvent, ConversationOptionEvent, DialogueLineEvent, KnowledgeChangedEvent quest steps, a conversation option; knowledge results
World progress FlameLevelChangedEvent, SpireUnlockedEvent, ShrineFoundEvent, ShroudRootDestroyedEvent, BossKilledEvent, ChestLootedEvent, QuestStatusChangedEvent reports only
Creatures CreatureStateEvent, CreatureTargetEvent, CreatureVariantAppliedEvent, VillagerStateEvent
Rules, time, settings PlayerRulesChangedEvent, TimeSetEvent, DayStartedEvent, NightStartedEvent, SettingChangedEvent, PermissionsChangedEvent
Network and content NetPeerReadyEvent, NetPeerLeftEvent, NetVanillaClientEvent, NetClientHandshakeEvent, ContentReadyEvent, ContentSyncedEvent, ConfigSyncedEvent a handshake
Client UI ScreenChangedEvent, RenderFrameEvent (every frame, on the render thread: Drawing)

Many events cost nothing until someone subscribes: Kiln starts watching the game for them only then. Subscribe to what you need, not to KilnEvent.

Your own events

public sealed class StormStartedEvent : CancelableEvent { public float Strength { get; init; } }

var ev = Events.Post(new StormStartedEvent { Strength = 0.8f });   // runs every handler, then returns the event
if (!ev.Canceled) StartStorm(ev.Strength);

Derive from KilnEvent, CancelableEvent, ResultEvent or CancelableResultEvent. Other mods subscribe to your type like any other, through a shared library mod (Other mods). Posting inside a handler works. Events.HasSubscribers<T>() is cheap: check it before building an expensive event.

Threads

  • Events.Post runs on the tick thread, as do all events Kiln posts on a server. Handlers can use the whole API.
  • Events.Enqueue(ev) works from any thread: the event is posted at the start of the next step.
  • In the client, events run on the game’s main thread. Register in OnLoad, which can run in the main menu, and act when the world is there.

See Code mods for the tick thread and await.

Enshrouded is a trademark of Keen Games GmbH. Kiln is unofficial.