@hotbunny/hackhub-content-sdk 0.9.5 → 0.9.7

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 +26 -11
  2. package/index.d.ts +32 -4
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @hotbunny/hackhub-content-sdk
1
+ # Hackhub Content SDK
2
2
 
3
3
  Official modding SDK for [HackHub - Ultimate Hacker Simulator](https://store.steampowered.com/app/2980270/HackHub__Ultimate_Hacker_Simulator/) on Steam. Create custom quests, websites, terminal commands, desktop apps, and more.
4
4
 
@@ -27,6 +27,7 @@ import { Bootstrap, RegisterModPackage } from "@hotbunny/hackhub-content-sdk";
27
27
 
28
28
  @RegisterModPackage
29
29
  export default class MyMod extends Bootstrap {
30
+
30
31
  OnModPackageLoaded() {
31
32
  console.log("Mod loaded!");
32
33
  }
@@ -34,6 +35,7 @@ export default class MyMod extends Bootstrap {
34
35
  OnModPackageUnloaded() {
35
36
  console.log("Mod unloaded");
36
37
  }
38
+
37
39
  }
38
40
  ```
39
41
 
@@ -42,7 +44,7 @@ export default class MyMod extends Bootstrap {
42
44
  Quests use a generic type parameter for type-safe data. `CreateData()` initializes the data once when the quest is first claimed. After that, access via `this.Data` and update via `this.SetData()`:
43
45
 
44
46
  ```typescript
45
- import { Quest, Events, Network, RegisterQuest } from "@hotbunny/hackhub-content-sdk";
47
+ import { Quest, Network, RegisterQuest } from "@hotbunny/hackhub-content-sdk";
46
48
 
47
49
  interface InfiltrationData {
48
50
  targetIp: string;
@@ -51,10 +53,10 @@ interface InfiltrationData {
51
53
 
52
54
  @RegisterQuest
53
55
  class InfiltrationQuest extends Quest<InfiltrationData> {
56
+
54
57
  Name = "Infiltration";
55
58
  Title = "Server Infiltration";
56
59
  Description = "Hack into the target server and download the data.";
57
- Employer = { name: "Mr. X", avatar: "mrx" };
58
60
  Rewards = { money: 5000, xp: 200 };
59
61
  Objectives = [
60
62
  { name: "scan", description: "Scan the target server" },
@@ -74,21 +76,21 @@ class InfiltrationQuest extends Quest<InfiltrationData> {
74
76
 
75
77
  OnStart() {
76
78
  Network.createSubnetNetwork({
77
- ip: this.Data.targetIp, // fully typed
79
+ ip: this.Data.targetIp,
78
80
  type: "ROUTER",
79
81
  ports: [{ external: 22, internal: 22, active: true, service: "ssh" }],
80
82
  users: [Network.createUser({ username: "admin", password: "secret123" })],
81
83
  children: [],
82
84
  });
83
85
 
84
- Events.on("Terminal.NmapScan", (data) => {
86
+ this.Events.on("Terminal.NmapScan", (data) => {
85
87
  if (data.ip === this.Data.targetIp) {
86
- this.SetData("attempts", this.Data.attempts + 1); // type-safe key & value
88
+ this.SetData("attempts", this.Data.attempts + 1);
87
89
  this.completeObjective("scan");
88
90
  }
89
91
  });
90
92
 
91
- Events.on("Terminal.SSH.Connected", (data) => {
93
+ this.Events.on("Terminal.SSH.Connected", (data) => {
92
94
  if (data.ip === this.Data.targetIp) this.completeObjective("connect");
93
95
  });
94
96
  }
@@ -96,6 +98,7 @@ class InfiltrationQuest extends Quest<InfiltrationData> {
96
98
  OnComplete() {
97
99
  Network.destroyNetwork(this.Data.targetIp);
98
100
  }
101
+
99
102
  }
100
103
  ```
101
104
 
@@ -106,14 +109,11 @@ Quests can send in-game emails and start phone call dialogs:
106
109
  ```typescript
107
110
  @RegisterQuest
108
111
  class StoryQuest extends Quest<{ contacted: boolean }> {
112
+
109
113
  Name = "StoryQuest";
110
114
  Title = "Story Quest";
111
115
  Objectives = [{ name: "start", description: "Begin the mission" }];
112
116
 
113
- CreateData() {
114
- return { contacted: false };
115
- }
116
-
117
117
  Mails = [
118
118
  { title: "Mission Briefing", content: "Your target is ready. Good luck." },
119
119
  ];
@@ -130,10 +130,15 @@ class StoryQuest extends Quest<{ contacted: boolean }> {
130
130
  ],
131
131
  };
132
132
 
133
+ CreateData() {
134
+ return { contacted: false };
135
+ }
136
+
133
137
  OnStart() {
134
138
  this.sendMail(0);
135
139
  this.createDialog("default");
136
140
  }
141
+
137
142
  }
138
143
  ```
139
144
 
@@ -144,10 +149,12 @@ import { Website, RegisterWebsite } from "@hotbunny/hackhub-content-sdk";
144
149
 
145
150
  @RegisterWebsite
146
151
  class MyWebsite extends Website {
152
+
147
153
  SiteName = "darkforum";
148
154
  DisplayName = "DarkForum";
149
155
  Description = "Underground hacking forum";
150
156
  HTML = "website.html";
157
+
151
158
  }
152
159
  ```
153
160
 
@@ -158,12 +165,14 @@ import { Command, RegisterCommand } from "@hotbunny/hackhub-content-sdk";
158
165
 
159
166
  @RegisterCommand
160
167
  class PingCommand extends Command {
168
+
161
169
  CommandName = "myping";
162
170
  Description = "Custom ping command";
163
171
 
164
172
  OnCommand(args: string[], tools: any) {
165
173
  tools.println(`Pinging ${args[0] || "nowhere"}...`);
166
174
  }
175
+
167
176
  }
168
177
  ```
169
178
 
@@ -174,11 +183,13 @@ import { App, RegisterApp } from "@hotbunny/hackhub-content-sdk";
174
183
 
175
184
  @RegisterApp
176
185
  class MyApp extends App {
186
+
177
187
  AppName = "mytool";
178
188
  DisplayName = "My Tool";
179
189
  Description = "A custom desktop application";
180
190
  HTML = "app.html";
181
191
  Size = { width: 600, height: 400 };
192
+
182
193
  }
183
194
  ```
184
195
 
@@ -191,6 +202,7 @@ import { Bootstrap, ModSettingDefinition, ModSettings, RegisterModPackage } from
191
202
 
192
203
  @RegisterModPackage
193
204
  export default class MyMod extends Bootstrap {
205
+
194
206
  Settings: ModSettingDefinition[] = [
195
207
  {
196
208
  key: "difficulty",
@@ -212,6 +224,7 @@ export default class MyMod extends Bootstrap {
212
224
  const hints = ModSettings.get<boolean>("showHints");
213
225
  console.log(`Difficulty: ${difficulty}, Hints: ${hints}`);
214
226
  }
227
+
215
228
  }
216
229
  ```
217
230
 
@@ -222,7 +235,9 @@ For fully custom settings panels, use an HTML file rendered in iframe:
222
235
  ```typescript
223
236
  @RegisterModPackage
224
237
  export default class MyMod extends Bootstrap {
238
+
225
239
  SettingsHTML = "settings.html";
240
+
226
241
  }
227
242
  ```
228
243
 
package/index.d.ts CHANGED
@@ -1077,9 +1077,30 @@ export declare abstract class Bootstrap {
1077
1077
  /** Called when the mod is being unloaded (e.g. disabled by user). */
1078
1078
  OnModPackageUnloaded(): void;
1079
1079
  }
1080
+ /**
1081
+ * Scoped event manager for a quest. All listeners registered via
1082
+ * `this.Events.on()` are automatically removed when the quest
1083
+ * completes or is abandoned, preventing memory leaks.
1084
+ */
1085
+ export declare class QuestEvents {
1086
+ private _listeners;
1087
+ /** @internal */ _globalOn?: (event: string, callback: Function) => () => void;
1088
+ /**
1089
+ * Listen to a game event or custom event. The listener is automatically
1090
+ * removed when the quest completes or is abandoned.
1091
+ */
1092
+ on<T extends string>(event: T, callback: (data: T extends keyof ModEventMap ? ModEventMap[T] : any) => void): () => void;
1093
+ /** Remove a specific listener. */
1094
+ off(event: string, callback: Function): void;
1095
+ /** Remove all listeners registered through this quest. */
1096
+ offAll(): void;
1097
+ }
1080
1098
  /**
1081
1099
  * Base class for mod quests. Extend with a generic type for type-safe quest data.
1082
1100
  *
1101
+ * Use `this.Events.on()` instead of the global `Events.on()` so listeners
1102
+ * are automatically cleaned up when the quest completes or is abandoned.
1103
+ *
1083
1104
  * @example
1084
1105
  * ```ts
1085
1106
  * interface MyData { targetIp: string; attempts: number; }
@@ -1097,8 +1118,9 @@ export declare abstract class Bootstrap {
1097
1118
  * }
1098
1119
  *
1099
1120
  * OnStart() {
1100
- * console.log(this.Data.targetIp); // fully typed
1101
- * this.SetData("attempts", 1); // type-safe key & value
1121
+ * this.Events.on("Terminal.NmapScan", (data) => {
1122
+ * if (data.ip === this.Data.targetIp) this.completeObjective("scan");
1123
+ * });
1102
1124
  * }
1103
1125
  * }
1104
1126
  * ```
@@ -1132,9 +1154,14 @@ export declare abstract class Quest<T extends Record<string, any> = Record<strin
1132
1154
  Dialog?: QuestDialogDefinition;
1133
1155
  /** Quest data created by CreateData(). Populated at runtime by the game engine. */
1134
1156
  Data: T;
1157
+ /**
1158
+ * Scoped event manager. Listeners registered here are automatically
1159
+ * cleaned up when the quest completes or is abandoned.
1160
+ */
1161
+ Events: QuestEvents;
1135
1162
  /**
1136
1163
  * Called when the quest is first claimed/started.
1137
- * Use this to set up event listeners for objective completion.
1164
+ * Use this to set up event listeners via `this.Events.on()`.
1138
1165
  */
1139
1166
  OnStart(): void | Promise<void>;
1140
1167
  /** Called when all objectives are completed and the quest finishes. */
@@ -1316,6 +1343,7 @@ export declare abstract class App {
1316
1343
  */
1317
1344
  Exports?: Record<string, any>;
1318
1345
  }
1346
+ type () => void$1 = () => void;
1319
1347
  /**
1320
1348
  * Game events API. Allows mods to listen to in-game events
1321
1349
  * such as terminal commands, file operations, network events, etc.
@@ -1353,7 +1381,7 @@ export declare namespace Events {
1353
1381
  * For known `ModEventMap` keys, the callback is fully typed.
1354
1382
  * For custom string events, the callback receives `any`.
1355
1383
  */
1356
- export function on<T extends string>(event: T, callback: (data: T extends keyof ModEventMap ? ModEventMap[T] : any) => void): () => void;
1384
+ export function on<T extends string>(event: T, callback: (data: T extends keyof ModEventMap ? ModEventMap[T] : any) => void): () => void$1;
1357
1385
  /** Remove a specific event listener. */
1358
1386
  export function off(event: string, callback: Function): void;
1359
1387
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotbunny/hackhub-content-sdk",
3
- "version": "0.9.5",
3
+ "version": "0.9.7",
4
4
  "description": "Official modding SDK for HackHub - Ultimate Hacker Simulator on Steam. Create custom quests, websites, terminal commands, and desktop apps.",
5
5
  "types": "index.d.ts",
6
6
  "exports": {