@hotbunny/hackhub-content-sdk 0.6.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +237 -76
  2. package/index.d.ts +279 -4
  3. package/package.json +8 -4
package/README.md CHANGED
@@ -1,140 +1,301 @@
1
1
  # @hotbunny/hackhub-content-sdk
2
2
 
3
- Type definitions and API reference for creating HackHub mods.
3
+ Official modding SDK for [HackHub](https://store.steampowered.com/app/3137230/HackHub/) -- the ultimate hacker simulator on Steam. Create custom quests, websites, terminal commands, desktop apps, and more.
4
4
 
5
- ## Quick Start
5
+ ## Getting Started
6
6
 
7
- The easiest way to create a new mod is with the interactive CLI:
7
+ ### Create a New Mod
8
8
 
9
9
  ```bash
10
10
  npm create hackhub-mod
11
11
  ```
12
12
 
13
- This will scaffold a ready-to-go project with templates, build config, and everything set up.
13
+ The CLI scaffolds a complete mod project with build config, templates, and TypeScript support.
14
14
 
15
- ## Manual Installation
15
+ ### Manual Setup
16
16
 
17
17
  ```bash
18
18
  npm install @hotbunny/hackhub-content-sdk --save-dev
19
19
  ```
20
20
 
21
- ## Example
21
+ ## Mod Entry Point
22
+
23
+ Every mod needs a `Bootstrap` class decorated with `@RegisterModPackage`:
22
24
 
23
25
  ```typescript
24
- import {
25
- Bootstrap,
26
- Quest,
27
- Events,
28
- Network,
29
- RegisterModPackage,
30
- RegisterQuest,
31
- } from "@hotbunny/hackhub-content-sdk";
32
-
33
- @RegisterModPackage()
34
- class MyMod extends Bootstrap {
26
+ import { Bootstrap, RegisterModPackage, Storage } from "@hotbunny/hackhub-content-sdk";
27
+
28
+ @RegisterModPackage
29
+ export default class MyMod extends Bootstrap {
35
30
  OnModPackageLoaded() {
36
- console.log("My mod loaded!");
31
+ const difficulty = Storage.get<string>("difficulty");
32
+ console.log(`Loaded with difficulty: ${difficulty}`);
33
+ }
34
+
35
+ OnModPackageUnloaded() {
36
+ console.log("Mod unloaded");
37
37
  }
38
38
  }
39
+ ```
39
40
 
40
- @RegisterQuest()
41
- class MyQuest extends Quest {
41
+ ## Quests
42
+
43
+ ```typescript
44
+ import { Quest, Network, RegisterQuest } from "@hotbunny/hackhub-content-sdk";
45
+
46
+ @RegisterQuest
47
+ class InfiltrationQuest extends Quest {
42
48
  definition = {
43
- name: "MyQuest",
44
- title: "My Custom Quest",
45
- description: "A quest added by a mod.",
46
- rewards: { money: 100 },
49
+ name: "Infiltration",
50
+ title: "Server Infiltration",
51
+ description: "Hack into the target server and download the data.",
52
+ employer: { name: "Mr. X", avatar: "mrx" },
53
+ rewards: { money: 5000, xp: 200 },
47
54
  objectives: [
48
55
  {
49
56
  name: "scan",
50
- description: "Scan the target",
51
- trigger: {
52
- event: "Terminal.NmapScan",
53
- condition: (data) => data.ip === "10.0.0.1",
54
- },
57
+ description: "Scan the target server",
58
+ trigger: { event: "Terminal.NmapScan", condition: (data) => data.ip === this.Data.targetIp },
59
+ },
60
+ {
61
+ name: "connect",
62
+ description: "Connect via SSH",
63
+ trigger: { event: "Terminal.SSH.Connected", condition: (data) => data.ip === this.Data.targetIp },
55
64
  },
56
65
  ],
57
66
  };
58
67
 
68
+ Data = {
69
+ targetIp: "10.0.0.50",
70
+ };
71
+
59
72
  OnStart() {
60
73
  Network.createSubnetNetwork({
61
- ip: "10.0.0.1",
74
+ ip: this.Data.targetIp,
62
75
  type: "ROUTER",
63
- ports: [{ external: 80, internal: 80, active: true, service: "http" }],
64
- users: [Network.createUser({ username: "admin" })],
76
+ ports: [{ external: 22, internal: 22, active: true, service: "ssh" }],
77
+ users: [Network.createUser({ username: "admin", password: "secret123" })],
65
78
  children: [],
66
79
  });
67
80
  }
68
81
  }
69
82
  ```
70
83
 
71
- ## API Overview
84
+ ### Quest Mail & Dialogs
85
+
86
+ Quests can send in-game emails and start phone call dialogs:
87
+
88
+ ```typescript
89
+ @RegisterQuest
90
+ class StoryQuest extends Quest {
91
+ // ... definition, Data ...
92
+
93
+ Mails = [
94
+ { title: "Mission Briefing", content: "Your target is ready. Good luck." },
95
+ ];
96
+
97
+ Dialog = {
98
+ default: [
99
+ { speaker: "Handler", text: "Are you ready for the mission?", options: [
100
+ { label: "Yes", text: "I'm ready.", switchBranch: "briefing" },
101
+ { label: "No", text: "Not yet.", isEnd: true },
102
+ ]},
103
+ ],
104
+ briefing: [
105
+ { speaker: "Handler", text: "Good luck out there.", isEnd: true },
106
+ ],
107
+ };
108
+
109
+ OnStart() {
110
+ this.sendMail(0);
111
+ this.createDialog("default");
112
+ }
113
+ }
114
+ ```
115
+
116
+ ## Websites
117
+
118
+ ```typescript
119
+ import { Website, RegisterWebsite } from "@hotbunny/hackhub-content-sdk";
120
+
121
+ @RegisterWebsite
122
+ class MyWebsite extends Website {
123
+ SiteName = "darkforum";
124
+ DisplayName = "DarkForum";
125
+ Description = "Underground hacking forum";
126
+ HTML = "website.html";
127
+ }
128
+ ```
129
+
130
+ ## Terminal Commands
131
+
132
+ ```typescript
133
+ import { Command, RegisterCommand } from "@hotbunny/hackhub-content-sdk";
134
+
135
+ @RegisterCommand
136
+ class PingCommand extends Command {
137
+ CommandName = "myping";
138
+ Description = "Custom ping command";
139
+
140
+ OnCommand(args: string[], tools: any) {
141
+ tools.println(`Pinging ${args[0] || "nowhere"}...`);
142
+ }
143
+ }
144
+ ```
145
+
146
+ ## Desktop Apps
147
+
148
+ ```typescript
149
+ import { App, RegisterApp } from "@hotbunny/hackhub-content-sdk";
150
+
151
+ @RegisterApp
152
+ class MyApp extends App {
153
+ AppName = "mytool";
154
+ DisplayName = "My Tool";
155
+ Description = "A custom desktop application";
156
+ HTML = "app.html";
157
+ Size = { width: 600, height: 400 };
158
+ }
159
+ ```
160
+
161
+ ## Mod Settings
72
162
 
73
- ### Base Classes
163
+ Players can configure your mod from the in-game Mods menu. Settings values are accessible via `Storage.get(key)`.
74
164
 
75
- | Class | Purpose |
76
- |-------|---------|
77
- | `Bootstrap` | Mod entry point, receives lifecycle callbacks |
78
- | `Quest` | Define custom quests with objectives and rewards |
79
- | `Website` | Add in-game websites to the browser |
80
- | `Command` | Register custom terminal commands |
81
- | `App` | Create desktop applications |
165
+ ```typescript
166
+ import { Bootstrap, ModSettingDefinition, RegisterModPackage, Storage } from "@hotbunny/hackhub-content-sdk";
82
167
 
83
- ### API Namespaces
168
+ @RegisterModPackage
169
+ export default class MyMod extends Bootstrap {
170
+ Settings: ModSettingDefinition[] = [
171
+ {
172
+ key: "difficulty",
173
+ label: "Difficulty",
174
+ type: "select",
175
+ default: "normal",
176
+ options: [
177
+ { label: "Easy", value: "easy" },
178
+ { label: "Normal", value: "normal" },
179
+ { label: "Hard", value: "hard" },
180
+ ],
181
+ },
182
+ { key: "showHints", label: "Show Hints", type: "toggle", default: true },
183
+ { key: "maxEnemies", label: "Max Enemies", type: "slider", default: 5, min: 1, max: 20 },
184
+ ];
185
+
186
+ OnModPackageLoaded() {
187
+ const difficulty = Storage.get<string>("difficulty");
188
+ const hints = Storage.get<boolean>("showHints");
189
+ console.log(`Difficulty: ${difficulty}, Hints: ${hints}`);
190
+ }
191
+ }
192
+ ```
193
+
194
+ Available setting types: `toggle`, `select`, `text`, `number`, `slider`.
195
+
196
+ For fully custom settings panels, use an HTML file rendered in iframe:
197
+
198
+ ```typescript
199
+ @RegisterModPackage
200
+ export default class MyMod extends Bootstrap {
201
+ SettingsHTML = "settings.html";
202
+ }
203
+ ```
204
+
205
+ ## API Reference
206
+
207
+ ### Namespaces
84
208
 
85
209
  | Namespace | Purpose |
86
210
  |-----------|---------|
87
- | `Events` | Listen to game events, emit custom cross-mod events |
88
- | `Files` | Create, read, write, delete files in the game filesystem |
89
- | `Network` | Create networks, manage ports, firewalls, domains |
211
+ | `Events` | Listen to 60+ game events, emit custom events |
212
+ | `Files` | Create, read, write, delete in-game files |
213
+ | `Network` | Create networks, ports, firewalls, domains |
90
214
  | `Mail` | Send in-game emails |
91
- | `Bank` | Manage bank transactions |
92
- | `Storage` | Persistent key-value storage (per-mod) |
93
- | `Variables` | Session-only variables (per-mod, reset on game close) |
215
+ | `Bank` | Bank accounts and transactions |
216
+ | `Random` | Random generation (id, password, username, pick, etc.) |
217
+ | `Storage` | Persistent key-value storage per mod |
218
+ | `Variables` | Session-only variables (reset on game close) |
94
219
  | `SharedStorage` | Persistent storage shared between mods |
95
220
  | `SharedVariables` | Session variables shared between mods |
96
221
  | `Shell` | Execute terminal commands programmatically |
97
- | `UI` | Show notifications and toasts |
98
- | `Twotter` | In-game Twitter -- create users, post tweets |
99
- | `Kisscord` | In-game Discord -- create users, send messages |
100
- | `WeeChat` | In-game IRC -- create servers, send messages |
222
+ | `UI` | Notifications and toasts |
223
+ | `Twotter` | In-game social media (Twitter-like) |
224
+ | `Kisscord` | In-game messaging (Discord-like) |
225
+ | `WeeChat` | In-game IRC chat |
101
226
 
102
- ### Decorators
227
+ ### Random
103
228
 
104
229
  ```typescript
105
- @RegisterModPackage() // Register the mod's Bootstrap class
106
- @RegisterQuest() // Register a Quest
107
- @RegisterWebsite() // Register a Website
108
- @RegisterCommand() // Register a terminal Command
109
- @RegisterApp() // Register a desktop App
110
- ```
230
+ import { Random } from "@hotbunny/hackhub-content-sdk";
111
231
 
112
- ## Events
232
+ Random.id(); // Short unique ID
233
+ Random.uuid(); // UUID v4
234
+ Random.number(1, 100); // Random integer 1-100
235
+ Random.password(); // Random password
236
+ Random.username(); // Random username
237
+ Random.pick(["a", "b", "c"]); // Random array element
238
+ Random.pickMultiple(arr, 3); // 3 unique random elements
239
+ await Random.sleep(2000); // Wait 2 seconds
240
+ ```
113
241
 
114
- ### Listening to Game Events
242
+ ### Events
115
243
 
116
244
  ```typescript
117
- Events.on("Terminal.NmapScan", (data) => {
118
- console.log(`Player scanned ${data.ip}`);
119
- });
245
+ import { Events } from "@hotbunny/hackhub-content-sdk";
246
+
247
+ // Listen to game events
248
+ Events.on("Terminal.NmapScan", (data) => console.log(`Scanned ${data.ip}`));
249
+ Events.on("Bettercap.Open", () => console.log("Bettercap opened"));
250
+ Events.on("Process.Killed", (data) => console.log(`Killed ${data.name}`));
251
+
252
+ // Custom cross-mod events
253
+ Events.emit("MyMod.ScoreUpdated", { score: 100 });
254
+ Events.on("MyMod.ScoreUpdated", (data) => console.log(data.score));
120
255
  ```
121
256
 
122
- ### Custom Cross-Mod Events
257
+ ## Manifest
123
258
 
124
- ```typescript
125
- declare module "@hotbunny/hackhub-content-sdk" {
126
- interface ModEventMap {
127
- "MyMod.BossDefeated": { bossName: string; reward: number };
128
- }
259
+ Each mod requires a `manifest.json` in its root:
260
+
261
+ ```json
262
+ {
263
+ "id": "my-mod-id",
264
+ "name": "My Mod",
265
+ "version": "1.0.0",
266
+ "author": "Your Name",
267
+ "description": "A brief description of the mod",
268
+ "apiVersion": 1,
269
+ "permissions": ["filesystem", "network", "events"],
270
+ "cover": "cover.png",
271
+ "tags": ["quest", "network"]
129
272
  }
273
+ ```
130
274
 
131
- Events.register("MyMod.BossDefeated");
132
- Events.emit("MyMod.BossDefeated", { bossName: "Hydra", reward: 500 });
275
+ ### Permissions
133
276
 
134
- Events.on("MyMod.BossDefeated", (data) => {
135
- console.log(`Boss ${data.bossName} defeated!`);
136
- });
137
- ```
277
+ | Permission | Grants access to |
278
+ |------------|-----------------|
279
+ | `filesystem` | Files API |
280
+ | `network` | Network API |
281
+ | `events` | Events API |
282
+ | `mail` | Mail API |
283
+ | `bank` | Bank API |
284
+ | `shell` | Shell API |
285
+ | `ui` | UI API |
286
+
287
+ ## Steam Workshop
288
+
289
+ Mods support Steam Workshop for easy distribution:
290
+
291
+ - **Upload** local mods to Workshop from the in-game Mods menu
292
+ - **Subscribe** to mods on Workshop -- they're automatically downloaded and loaded
293
+ - **Update** published mods with change notes
294
+
295
+ ## Links
296
+
297
+ - [HackHub on Steam](https://store.steampowered.com/app/3137230/HackHub/)
298
+ - [Steam Workshop](https://steamcommunity.com/app/3137230/workshop/)
138
299
 
139
300
  ## License
140
301
 
package/index.d.ts CHANGED
@@ -180,6 +180,61 @@ export interface WeeChatMessageDefinition {
180
180
  /** Callback fired after this message is sent. */
181
181
  onSent?: () => void | Promise<void>;
182
182
  }
183
+ /** A mail message sent during a quest (e.g. from an employer NPC). */
184
+ export interface QuestMailDefinition {
185
+ /** Mail subject line. */
186
+ title: string;
187
+ /** Mail body content (plain text or HTML string). */
188
+ content: string;
189
+ /** If true, the player can reply to this mail. */
190
+ replyable?: boolean;
191
+ /** Attachment file to include with the mail. */
192
+ attachment?: {
193
+ name: string;
194
+ extension?: string;
195
+ content?: string;
196
+ };
197
+ }
198
+ /** A phone-call dialog tree for quests. Keys are branch names. */
199
+ export interface QuestDialogDefinition {
200
+ [branchName: string]: QuestDialogSpeech[];
201
+ }
202
+ /** A single speech line in a phone-call dialog. */
203
+ export interface QuestDialogSpeech {
204
+ /** Who is speaking (NPC name or "player"). */
205
+ speaker: string;
206
+ /** The spoken text. */
207
+ text: string;
208
+ /** Audio file path (resolved via mod-asset://). Empty string if none. */
209
+ audio?: string;
210
+ /** If true, this is the last line and the call ends. */
211
+ isEnd?: boolean;
212
+ /** Delay in ms before the next line auto-plays. */
213
+ timeout?: number;
214
+ /** Callback fired when this speech line ends. */
215
+ onEnd?: () => void;
216
+ /** Player response options (branching). */
217
+ options?: QuestDialogOption[];
218
+ }
219
+ /** A selectable response option in a dialog. */
220
+ export interface QuestDialogOption {
221
+ /** Short label shown on the button. */
222
+ label: string;
223
+ /** Full text the player says. */
224
+ text: string;
225
+ /** Audio file path. Empty string if none. */
226
+ audio?: string;
227
+ /** Switch to a different dialog branch by name. */
228
+ switchBranch?: string;
229
+ /** Jump to a specific index within the current/target branch. */
230
+ nextIndex?: number;
231
+ /** If true, the call ends after this option. */
232
+ isEnd?: boolean;
233
+ /** Delay in ms before proceeding. */
234
+ timeout?: number;
235
+ /** Callback fired when this option is selected. */
236
+ onSelect?: () => void;
237
+ }
183
238
  /**
184
239
  * Game events that mods can listen to.
185
240
  * This is a curated subset of the internal GameEvents, exposing only
@@ -390,6 +445,120 @@ export interface RemoteConnectionDisconnectedEvent {
390
445
  ip: string;
391
446
  service?: string;
392
447
  }
448
+ export interface TerminalCdEvent {
449
+ path: string;
450
+ }
451
+ export interface TerminalLsEvent {
452
+ id: string;
453
+ name: string;
454
+ }
455
+ export interface TerminalOpensslEvent {
456
+ file: string;
457
+ }
458
+ export interface TerminalSSHShutdownEvent {
459
+ ip: string;
460
+ }
461
+ export interface TerminalLynxSearchEvent {
462
+ query: string;
463
+ }
464
+ export interface TerminalLynxLookupEvent {
465
+ data: any;
466
+ }
467
+ export interface TerminalMxlookupEvent {
468
+ domain: string;
469
+ ip: string;
470
+ }
471
+ export interface TerminalIfconfigEvent {
472
+ terminalIp: string;
473
+ }
474
+ export interface MetasploitMsfconsoleEvent {
475
+ }
476
+ export interface MetasploitShowOptionsEvent {
477
+ name: string;
478
+ type: string;
479
+ }
480
+ export interface MetasploitSetOptionEvent {
481
+ name: string;
482
+ value: string | number;
483
+ allFilled: boolean;
484
+ }
485
+ export interface MetasploitRootgrabEvent {
486
+ ip: string;
487
+ file: {
488
+ id: string;
489
+ name: string;
490
+ };
491
+ }
492
+ export interface MeterpreterDownloadEvent {
493
+ host: string;
494
+ file: {
495
+ id: string;
496
+ name: string;
497
+ };
498
+ }
499
+ export interface SubfinderResultsEvent {
500
+ domain: string;
501
+ subdomains: any[];
502
+ }
503
+ export interface NucleiResultsEvent {
504
+ file: any;
505
+ hosts: string[];
506
+ }
507
+ export interface HashcatEvent {
508
+ id: string;
509
+ name: string;
510
+ }
511
+ export interface JohnDecryptHashEvent {
512
+ hash: string;
513
+ password: string;
514
+ }
515
+ export interface FernFindPasswordEvent {
516
+ user: any;
517
+ model: string;
518
+ }
519
+ export interface BettercapOpenEvent {
520
+ }
521
+ export interface BettercapCloseEvent {
522
+ }
523
+ export interface BettercapNetProbeEvent {
524
+ active: boolean;
525
+ }
526
+ export interface BettercapNetShowEvent {
527
+ }
528
+ export interface BettercapWifiReconEvent {
529
+ }
530
+ export interface BettercapWifiDeAuthEvent {
531
+ }
532
+ export interface MailMailboxOpenedEvent {
533
+ from: string;
534
+ to: string;
535
+ subject: string;
536
+ }
537
+ export interface TwotterAccountLogoutEvent {
538
+ id: string;
539
+ username: string;
540
+ }
541
+ export interface BrowserMetaEvent {
542
+ title: string;
543
+ url: string;
544
+ }
545
+ export interface ProcessKilledEvent {
546
+ pid: number;
547
+ name: string;
548
+ }
549
+ export interface WiresharkStartedEvent {
550
+ interface: string;
551
+ }
552
+ export interface WiresharkStoppedEvent {
553
+ interface: string;
554
+ }
555
+ export interface Python3ExecFileEvent {
556
+ args: string[];
557
+ file: any;
558
+ }
559
+ export interface BCCNewsOpenedEvent {
560
+ articleId: string;
561
+ }
393
562
  /**
394
563
  * Map of event names to their payload types.
395
564
  * Mod authors use these as: Events.on("Terminal.NmapScan", (data) => { ... })
@@ -461,6 +630,38 @@ export interface ModEventMap {
461
630
  "RemoteConnection.Established": RemoteConnectionEstablishedEvent;
462
631
  "RemoteConnection.Disconnected": RemoteConnectionDisconnectedEvent;
463
632
  "AppStore.Downloaded": string;
633
+ "Terminal.Cd": TerminalCdEvent;
634
+ "Terminal.Ls": TerminalLsEvent;
635
+ "Terminal.Openssl": TerminalOpensslEvent;
636
+ "Terminal.SSH.Shutdown": TerminalSSHShutdownEvent;
637
+ "Terminal.Lynx.Search": TerminalLynxSearchEvent;
638
+ "Terminal.Lynx.Lookup": TerminalLynxLookupEvent;
639
+ "Terminal.Mxlookup": TerminalMxlookupEvent;
640
+ "Terminal.Ifconfig": TerminalIfconfigEvent;
641
+ "Metasploit.Msfconsole": MetasploitMsfconsoleEvent;
642
+ "Metasploit.ShowOptions": MetasploitShowOptionsEvent;
643
+ "Metasploit.SetOption": MetasploitSetOptionEvent;
644
+ "Metasploit.Rootgrab": MetasploitRootgrabEvent;
645
+ "Meterpreter.Download": MeterpreterDownloadEvent;
646
+ "Subfinder.Results": SubfinderResultsEvent;
647
+ "Nuclei.Results": NucleiResultsEvent;
648
+ "Hashcat": HashcatEvent;
649
+ "John.DecryptHash": JohnDecryptHashEvent;
650
+ "Fern.FindPassword": FernFindPasswordEvent;
651
+ "Bettercap.Open": BettercapOpenEvent;
652
+ "Bettercap.Close": BettercapCloseEvent;
653
+ "Bettercap.NetProbe": BettercapNetProbeEvent;
654
+ "Bettercap.NetShow": BettercapNetShowEvent;
655
+ "Bettercap.WifiRecon": BettercapWifiReconEvent;
656
+ "Bettercap.WifiDeAuth": BettercapWifiDeAuthEvent;
657
+ "Mail.MailboxOpened": MailMailboxOpenedEvent;
658
+ "Twotter.AccountLogout": TwotterAccountLogoutEvent;
659
+ "Browser.Meta": BrowserMetaEvent;
660
+ "Process.Killed": ProcessKilledEvent;
661
+ "Wireshark.Started": WiresharkStartedEvent;
662
+ "Wireshark.Stopped": WiresharkStoppedEvent;
663
+ "Python3.ExecFile": Python3ExecFileEvent;
664
+ "BCC.News.Opened": BCCNewsOpenedEvent;
464
665
  }
465
666
  export type ModEventName = keyof ModEventMap;
466
667
  export type ModEventCallback<T extends ModEventName> = (data: ModEventMap[T]) => void;
@@ -711,6 +912,9 @@ export interface ModManifest {
711
912
  dependencies?: string[];
712
913
  permissions?: ModPermission[];
713
914
  icon?: string;
915
+ cover?: string;
916
+ workshopId?: string;
917
+ tags?: string[];
714
918
  }
715
919
  export type ModPermission = "filesystem" | "network" | "events" | "mail" | "bank" | "shell" | "ui";
716
920
  export interface ModInfo {
@@ -720,8 +924,13 @@ export interface ModInfo {
720
924
  author: string;
721
925
  description: string;
722
926
  icon?: string;
927
+ cover?: string;
723
928
  enabled: boolean;
929
+ status?: ModStatus;
724
930
  error?: string;
931
+ permissions?: ModPermission[];
932
+ workshopId?: string;
933
+ tags?: string[];
725
934
  }
726
935
  export declare enum ModStatus {
727
936
  Pending = "PENDING",
@@ -730,6 +939,19 @@ export declare enum ModStatus {
730
939
  Error = "ERROR",
731
940
  Disabled = "DISABLED"
732
941
  }
942
+ export interface ModSettingDefinition {
943
+ key: string;
944
+ label: string;
945
+ type: "toggle" | "select" | "text" | "number" | "slider";
946
+ default: any;
947
+ options?: {
948
+ label: string;
949
+ value: string;
950
+ }[];
951
+ min?: number;
952
+ max?: number;
953
+ step?: number;
954
+ }
733
955
  export interface TwotterCreateUserOptions {
734
956
  id?: string;
735
957
  username?: string;
@@ -828,19 +1050,28 @@ export interface WeeChatServer {
828
1050
  *
829
1051
  * @RegisterModPackage
830
1052
  * export class MyMod extends Bootstrap {
1053
+ * Settings = [
1054
+ * { key: "difficulty", label: "Difficulty", type: "select" as const, default: "normal", options: [
1055
+ * { label: "Easy", value: "easy" },
1056
+ * { label: "Normal", value: "normal" },
1057
+ * { label: "Hard", value: "hard" },
1058
+ * ]},
1059
+ * { key: "showHints", label: "Show Hints", type: "toggle" as const, default: true },
1060
+ * ];
1061
+ *
831
1062
  * OnModPackageLoaded() {
832
1063
  * console.log("My mod has been loaded!");
833
1064
  * }
834
- *
835
- * OnModPackageUnloaded() {
836
- * console.log("My mod has been unloaded.");
837
- * }
838
1065
  * }
839
1066
  * ```
840
1067
  */
841
1068
  export declare abstract class Bootstrap {
842
1069
  /** The parsed manifest.json of this mod. Set by the loader at runtime. */
843
1070
  Manifest: ModManifest;
1071
+ /** Declarative settings definitions rendered in the Mods UI. */
1072
+ Settings?: ModSettingDefinition[];
1073
+ /** Path to an HTML file for a custom settings panel (rendered in iframe). */
1074
+ SettingsHTML?: string;
844
1075
  /** Called after the mod package and all its registered content are loaded. */
845
1076
  OnModPackageLoaded(): void | Promise<void>;
846
1077
  /** Called when the mod is being unloaded (e.g. disabled by user). */
@@ -894,6 +1125,10 @@ export declare abstract class Quest {
894
1125
  KisscordChats?: KisscordChatDefinition[];
895
1126
  /** WeeChat (IRC) chat chains for this quest. */
896
1127
  WeeChatChats?: WeeChatChatDefinition[];
1128
+ /** Mail messages that can be sent during the quest via this.sendMail(index). */
1129
+ Mails?: QuestMailDefinition[];
1130
+ /** Phone-call dialog tree for this quest. Use this.createDialog(branch) to start. */
1131
+ Dialog?: QuestDialogDefinition;
897
1132
  /**
898
1133
  * Called when the quest is first claimed/started.
899
1134
  * Use this to set up event listeners for objective completion.
@@ -909,6 +1144,12 @@ export declare abstract class Quest {
909
1144
  CreateData(): any;
910
1145
  /** Complete an objective by its name. */
911
1146
  completeObjective(name: string): void;
1147
+ /** Send a mail from the Mails array by index. */
1148
+ sendMail(index: number, from?: string, to?: string): void;
1149
+ /** Start a phone-call dialog. Defaults to "default" branch. */
1150
+ createDialog(branch?: string, startIndex?: number): void;
1151
+ /** @internal */ _sendMailInternal?: (index: number, from?: string, to?: string) => void;
1152
+ /** @internal */ _createDialogInternal?: (branch: string, startIndex: number) => void;
912
1153
  }
913
1154
  /**
914
1155
  * Base class for mod websites. Mod authors extend this to create
@@ -1576,6 +1817,40 @@ export declare namespace WeeChat {
1576
1817
  export function getHistory(host?: string): WeeChatMessage[];
1577
1818
  export {};
1578
1819
  }
1820
+ /**
1821
+ * Random generation helpers for mod authors.
1822
+ *
1823
+ * @example
1824
+ * ```ts
1825
+ * import { Random } from "@hotbunny/hackhub-content-sdk";
1826
+ *
1827
+ * const uniqueId = Random.id();
1828
+ * const pin = Random.number(1000, 9999);
1829
+ * const pass = Random.password();
1830
+ * const user = Random.username();
1831
+ * const winner = Random.pick(["Alice", "Bob", "Charlie"]);
1832
+ * await Random.sleep(2000);
1833
+ * ```
1834
+ */
1835
+ export declare namespace Random {
1836
+ /** Generate a short unique ID. Default length is 10. */
1837
+ export function id(length?: number): string;
1838
+ /** Generate a UUID (v4-like). */
1839
+ export function uuid(): string;
1840
+ /** Generate a random integer between min and max (inclusive). */
1841
+ export function number(min?: number, max?: number): number;
1842
+ /** Get a random password from the game's password list. */
1843
+ export function password(): string;
1844
+ /** Get a random username from the game's username list. */
1845
+ export function username(): string;
1846
+ /** Pick a random element from an array. */
1847
+ export function pick<T>(array: T[]): T;
1848
+ /** Pick multiple unique random elements from an array. */
1849
+ export function pickMultiple<T>(array: T[], count: number): T[];
1850
+ /** Sleep for the given number of milliseconds. */
1851
+ export function sleep(ms: number): Promise<void>;
1852
+ export {};
1853
+ }
1579
1854
  /**
1580
1855
  * Marks a class as the mod's entry point.
1581
1856
  * Each mod must have exactly one @RegisterModPackage class extending Bootstrap.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hotbunny/hackhub-content-sdk",
3
- "version": "0.6.0",
4
- "description": "Type definitions and build tools for HackHub mod development",
3
+ "version": "0.9.1",
4
+ "description": "Official modding SDK for HackHub - the ultimate hacker simulator on Steam. Create custom quests, websites, terminal commands, and desktop apps.",
5
5
  "types": "index.d.ts",
6
6
  "exports": {
7
7
  ".": {
@@ -19,10 +19,14 @@
19
19
  ],
20
20
  "keywords": [
21
21
  "hackhub",
22
+ "hacker-simulator",
23
+ "hacking-game",
24
+ "steam",
22
25
  "modding",
23
- "sdk",
24
- "types",
26
+ "modding-sdk",
25
27
  "game-modding",
28
+ "steam-workshop",
29
+ "typescript",
26
30
  "hotbunny"
27
31
  ],
28
32
  "repository": {