@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.
- package/README.md +26 -11
- package/index.d.ts +32 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
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,
|
|
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,
|
|
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);
|
|
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
|
-
*
|
|
1101
|
-
*
|
|
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
|
|
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.
|
|
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": {
|