Skip to content

ModEventMap ​

The ModEventMap interface defines all typed game events available through the Events.on() and Events.emit() APIs. These events correspond to in-game actions and systems.

ModEventMap is the authoritative source for event payloads: it is generated from the game's own event bus, so your editor infers the exact payload for an event name. The Events guide lists all 99 events with their payload types.

Declaration Merging ​

You can extend ModEventMap to add type-safe custom events:

typescript
declare module "@hotbunny/hackhub-content-sdk" {
    interface ModEventMap {
        "MyMod.BossDefeated": { bossName: string; reward: number };
        "MyMod.LevelUp": { level: number; xp: number };
    }
}

After declaration merging, Events.on() and Events.emit() provide full type inference:

typescript
Events.on("MyMod.BossDefeated", (data) => {
    // data is typed as { bossName: string; reward: number }
    console.log(data.bossName);
});

Payloads are not all objects ​

A payload is whatever the engine raised, which is not always a wrapper object. ModEventMap maps each name to one of:

ShapeExample events
A named *Event interfaceTerminal.NmapScan, Network.PortChanges, Bank.Transfer
A bare stringTerminal.SSH.Connected, Terminal.Geoip, WeeChat.Connected, Subfinder.Try
A bare booleanBettercap.NetProbe
nullNetwork.WifiDisconnected, Bettercap.Open
undefinedGame.SessionStarted, Metasploit.Msfconsole
FileInfoTerminal.Cat, Terminal.Ls, Files.Deleted, Hashcat
An engine object with PascalCase fieldsQuest.Claimed, Browser.WebsiteOpened

Because the map is typed, destructuring a primitive payload is a compile error rather than a silent undefined:

typescript
// Right: the payload IS the IP.
Events.on("Terminal.SSH.Connected", (ip) => ip === "192.168.1.50");

// Wrong: Property 'ip' does not exist on type 'string'.
Events.on("Terminal.SSH.Connected", ({ ip }) => ip === "192.168.1.50");

Deprecated payload interfaces ​

A number of *Event interfaces described payloads that the game never actually sent. They are still exported so older packs keep compiling, but each is marked @deprecated with the shape to use instead. Hover one in your editor to see the replacement.

Among them: SSHConnectedEvent, FTPConnectEvent, GeoipEvent, TerminalSSHShutdownEvent, TerminalLynxSearchEvent, WeeChatConnectedEvent, WeeChatDisconnectedEvent, SubfinderTryEvent, BCCNewsOpenedEvent, BettercapNetProbeEvent, NetworkWifiDisconnectedEvent, MetasploitMsfconsoleEvent, CatEvent, TerminalLsEvent, HashcatEvent, SSHFileDownloadEvent.

If a condition written against a payload field never matches, this is usually why.

Using Events in Quests ​

Inside a Quest class, use this.Events.on() for automatic cleanup. Register listeners in OnObjectivesStart() (runs on claim and on every game start), not OnStart() (runs once at claim). Listeners are lost on reload and only OnObjectivesStart() re-attaches them:

typescript
@RegisterQuest
class HackTheServer extends Quest {
    // Runs on claim and on every game start, so listeners survive reloads.
    OnObjectivesStart() {
        this.Events.on("Terminal.NmapScan", (data) => {
            if (data.ip === "192.168.1.50") {
                this.completeObjective("scan");
            }
        });

        this.Events.on("Terminal.SSH.Connected", (ip) => {
            if (ip === "192.168.1.50") {
                this.completeObjective("connect");
            }
        });
    }
}

Custom Events for Cross-Mod Communication ​

typescript
// Register (optional, for discoverability)
Events.register("MyMod.DataReady");

// Emit
Events.emit("MyMod.DataReady", { items: ["sword", "shield"] });

// Listen (from any mod)
Events.on("MyMod.DataReady", (data) => {
    console.log(data.items);
});

Custom events are delivered through both the game event bus and the custom event bus, allowing both game-engine systems and other mods to react.

HotBunny Interactive Entertainment Inc.