-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathhack-daemon.js
More file actions
382 lines (312 loc) · 16.1 KB
/
hack-daemon.js
File metadata and controls
382 lines (312 loc) · 16.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
/** The botnet's workers.
* The hack-daemon will intelligently hack, weaken, and grow with the
* exact amount of threads needed. It can also handle hack EXP farming,
* sharing of the CPU (only for home and private servers), and stock
* market manipulation!
*
* Written By: Zharay
* URL: https://github.com/Zharay/BitburnerBotnet
*
* Requires that the coordinator is running with targets posted via ports.
**/
/** @param {NS} ns */
export async function main(ns) {
ns.disableLog("ALL");
const debug = false; // Enables debug logs.
const homeCPU = 1; // The number of CPUs on your home server. Better to just set it here than waste RAM
const expRuns = 2; // The number of cycles to complete before looking to using your remaining RAM on EXP farms
const homeReservedRAM = 5; // (GB) Amount of RAM to reserve on home server.
var host = ns.getHostname();
ns.print("Host: " + host);
// These are temporary defaults. They get overwritten by the coordinator!
var target = "n00dles";
var threshModifier = 0.6;
if (!ns.serverExists(target)) {
ns.print("ERROR: Server [" + target + "] does not exist");
return;
}
// Tell the coordinator we exist!
ns.print("Posting host information to coordinator...");
await ns.tryWritePort(11, host);
// Get targets from coordinator
var gTargets = ns.getPortHandle(1);
var gStatus = ns.getPortHandle(3);
var gExp = ns.getPortHandle(5);
var gLock = ns.getPortHandle(6);
var outLock = ns.getPortHandle(15);
var fShare = ns.getPortHandle(17);
var fHostKill = ns.getPortHandle(18);
var fKill = ns.getPortHandle(20);
while (gTargets.peek() == "NULL PORT DATA") {
ns.print("Waiting for targets to be added by coordinator...")
await ns.sleep(1000);
}
var randWait = 1000 * Math.floor(randomIntFromInterval(3, 30));
ns.print("Waiting for [" + (randWait / 1000) + "] seconds");
await ns.sleep(randWait);
var jTargets = JSON.parse(gTargets.peek());
var jStatus = JSON.parse(gStatus.peek());
var jExp = JSON.parse(gExp.peek());
var jLocks = JSON.parse(gLock.peek());
var jLockRequest = {"target" : "", "host": host, "task" : "", "done" : false};
var weakenID = new Array(jTargets.length).fill(0);
var growID = new Array(jTargets.length).fill(0);
var hackID = new Array(jTargets.length).fill(0);
var curRuns = 0;
var reservedRam = host == "home" ? homeReservedRAM : 0;
while(fKill.peek() == "NULL PORT DATA" && fHostKill.peek() != host) {
jTargets = JSON.parse(gTargets.peek());
ns.print("-----------------Starting Loop-------------------");
// If share is enabled, stop everything and just share.
if (fShare.peek() != "NULL PORT DATA" && (host == "home" || host.includes("pserv"))) {
if (ns.getScriptRam("shareCPU.js") <= ns.getServerMaxRam(host) - ns.getServerUsedRam(host) - reservedRam) {
var numThreads = Math.floor((ns.getServerMaxRam(host) - ns.getServerUsedRam(host) - reservedRam) / ns.getScriptRam("shareCPU.js"));
if (numThreads > 0) {
ns.print(`[${target}] Sharing CPU to contracts... (Threads: ${numThreads})`);
ns.run("shareCPU.js", numThreads, new Date().getMinutes());
}
}
// Wait and restart loop
randWait = 1000 * Math.floor(randomIntFromInterval(3, 5));
ns.print("Waiting for [" + (randWait / 1000) + "] seconds");
await ns.sleep(randWait);
continue;
}
// Cycle the targets from coordinator
for (var indexTarget in jTargets) {
jStatus = JSON.parse(gStatus.peek());
jLocks = JSON.parse(gLock.peek());
target = jTargets[indexTarget].target;
jLockRequest.target = target;
threshModifier = jTargets[indexTarget].thresholdModifier;
var currentLocks = jLocks.find(x => x.target == target);
if (fHostKill.peek() == host)
break;
/** Weaken: <NOTE: The more threads tossed at it the better.>
* We only weaken if : 1) We are close to the min threshold
* 2) Or if there is a reported security risk
* 3) If we even have enough to run the script
* 4) If there is no lock
*/
var securityThreshold = ns.getServerMinSecurityLevel(target) + 5;
if (jStatus[indexTarget].isTarget
&& (ns.getServerSecurityLevel(target) > securityThreshold || jStatus[indexTarget].security > 5)
&& (ns.getScriptRam("weaken.js") <= ns.getServerMaxRam(host) - ns.getServerUsedRam(host) - reservedRam)
&& currentLocks.weakenLock == "") {
// Try to set lock
jLockRequest.task = "weaken";
jLockRequest.done = false;
ns.print(`[${target}] Attempting to lock weakening...`)
await outLock.tryWrite(JSON.stringify(jLockRequest));
// Wait for coordinator to process locks
while(currentLocks.weakenLock == "") {
await ns.sleep(500);
jLocks = JSON.parse(gLock.peek());
currentLocks = jLocks.find(x => x.target == target);
}
if (currentLocks.weakenLock == host) {
ns.print(`[${target}] Lock Success!`);
var currentThreads = parseInt(jStatus[indexTarget].weakenThreads);
if (isNaN(currentThreads)) {
ns.print(`[${target}] ERROR: currentThreads = NaN! (${rawTargetStatus})`);
} else if (currentThreads < 0) {
ns.print(`[${target}] ERROR: currentThreads = ${currentThreads}`);
}
// There is a breach if we are beyond a minimum limit x2 (typically happens when hacking wins more than its chance to fail)
var securityBreach = (ns.getServerSecurityLevel(target) + jStatus[indexTarget].security >= securityThreshold * 2) ? 2 : 1;
// Security threat generated from grow/hack
var securityThreat = (jStatus[indexTarget].security > 5 ? jStatus[indexTarget].security : 0);
// [NOTE] Weaken lowers security by 0.05 per thread!
// If there is a security breach, multiply the threads we need by 2x
var reqThreads = (Math.ceil((ns.getServerSecurityLevel(target) + securityThreat - securityThreshold) / 0.05) * securityBreach) - currentThreads;
var numThreads = Math.min(reqThreads, Math.floor((ns.getServerMaxRam(host) - ns.getServerUsedRam(host) - reservedRam) / ns.getScriptRam("weaken.js")));
if (numThreads > 0) {
ns.print(`[${target}] Weakening... (Threads: ${numThreads})`);
weakenID[indexTarget] = ns.run("weaken.js", numThreads, target, host, numThreads, ns.getScriptRam("weaken.js")*numThreads, 0);
} else {
ns.print(`[${target}] Skipping weaken. Enough threads working on it. [${numThreads} / ${currentThreads}]`);
}
ns.print("Sleeping for 1 sec...")
await ns.sleep(1000);
jLockRequest.done = true;
ns.print(`[${target}] Removing weakening lock down...`);
await outLock.tryWrite(JSON.stringify(jLockRequest));
} else {
ns.print(`[${target}] LATE LOCKED : [${currentLocks.weakenLock}] has locked weakening...`);
}
} else if (currentLocks.weakenLock != "") {
ns.print(`[${target}] LOCKED : [${currentLocks.weakenLock}] has locked weakening...`);
}
if (fHostKill.peek() == host)
break;
await ns.sleep(400);
jStatus = JSON.parse(gStatus.peek());
jLocks = JSON.parse(gLock.peek());
currentLocks = jLocks.find(x => x.target == target);
/**Grow <Growth is always a 1 CPU deal unless its on home. We now go for 98%>
* Grow only when: The money available is less than 98% of the maximum (reason is due to hacking going to specified threshold)
* If, in addition to the above, the number of hack threads is below the 98% threshold
* If we have enough RAM to even run the script
* If there is no lock set.
*/
if (((jStatus[indexTarget].isTarget && !jStatus[indexTarget].isLong && !jStatus[indexTarget].isShort) || (jStatus[indexTarget].isLong && jStatus[indexTarget].profitChange < 0))
&& (ns.getServerMoneyAvailable(target) - (ns.getServerMoneyAvailable(target) - (ns.hackAnalyze(target) * jStatus[indexTarget].hackThreads * ns.hackAnalyzeChance(target)))) < (ns.getServerMaxMoney(target)*0.98)
&& (ns.getScriptRam("grow.js") <= ns.getServerMaxRam(host) - ns.getServerUsedRam(host) - reservedRam)
&& currentLocks.growLock == "") {
// Try to set lock
jLockRequest.task = "grow";
jLockRequest.done = false;
ns.print(`[${target}] Attempting to lock growth...`)
await outLock.tryWrite(JSON.stringify(jLockRequest));
// Wait for coordinator to process locks
while(currentLocks.growLock == "") {
await ns.sleep(400);
jLocks = JSON.parse(gLock.peek());
currentLocks = jLocks.find(x => x.target == target);
}
if (currentLocks.growLock == host) {
ns.print(`[${target}] Lock Success!`);
var currentThreads = parseInt(jStatus[indexTarget].growThreads);
if (isNaN(currentThreads)) {
ns.print(`[${target}] ERROR: currentThreads = NaN! (${rawTargetStatus})`);
} else if (currentThreads < 0) {
ns.print(`[${target}] ERROR: currentThreads = ${currentThreads}`);
}
// growthAnalyze = Asks for the multiplier amount you want to grow the current amount by!
// X = Max / (Available - Hacking)
// Hacking = [% Amount Taken] * Max * NumThreads * Chance
// Above ignored if (Available == 0 || amountGrow <= 0)
var amountGrow = ns.getServerMaxMoney(target) / (ns.getServerMoneyAvailable(target) - (ns.hackAnalyze(target) * ns.getServerMoneyAvailable(target) * jStatus[indexTarget].hackThreads * ns.hackAnalyzeChance(target)));
var reqThreads = 1;
if (ns.getServerMoneyAvailable(target) == 0 || amountGrow <= 0)
reqThreads = (ns.getServerMaxRam(host) - ns.getServerUsedRam(host) - reservedRam) / ns.getScriptRam("grow.js");
else
reqThreads = ns.growthAnalyze(target, amountGrow, (host == "home" ? homeCPU : 1)) - currentThreads;
var numThreads = Math.floor(Math.min(reqThreads, (ns.getServerMaxRam(host) - ns.getServerUsedRam(host) - reservedRam) / ns.getScriptRam("grow.js")));
if (numThreads > 0) {
ns.print(`[${target}] Growing... (Threads: ${numThreads})`);
growID[indexTarget] = ns.run("grow.js", numThreads, target, threshModifier, host, numThreads, ns.getScriptRam("grow.js")*numThreads, ns.growthAnalyzeSecurity(numThreads, target, (host == "home" ? homeCPU : 1)));
} else {
ns.print(`[${target}] Skipping growth. Enough threads working on it. [${numThreads} / ${currentThreads}]`);
}
ns.print("Sleeping for 1 sec...")
await ns.sleep(1000);
jLockRequest.done = true;
ns.print(`[${target}] Removing growth lock down...`);
await outLock.tryWrite(JSON.stringify(jLockRequest));
} else {
ns.print(`[${target}] LATE LOCKED : [${currentLocks.growLock}] has locked growth...`);
}
} else if (currentLocks.growLock != "") {
ns.print(`[${target}] LOCKED : [${currentLocks.growLock}] has locked growth...`);
}
if (fHostKill.peek() == host)
break;
await ns.sleep(400);
jStatus = JSON.parse(gStatus.peek());
jLocks = JSON.parse(gLock.peek());
currentLocks = jLocks.find(x => x.target == target);
/**Hack <Hack is fast and dumb. Be careful!>
* Only hack if: If the money available is greater than our threshold (which is a % of its maximum)
* OR if it's a short stock (hack it to the ground for stock profits)
* If the chance to hack the target is over 10%
* If you have the RAM needed to run the script
* If there is no lock
*/
var moneyThreshold = ns.getServerMaxMoney(target) * threshModifier;
if (((jStatus[indexTarget].isTarget && !jStatus[indexTarget].isLong && !jStatus[indexTarget].isShort) || ((jStatus[indexTarget].isShort && jStatus[indexTarget].profitChange > 0)))
&& ((ns.getServerMoneyAvailable(target) >= moneyThreshold) || jStatus[indexTarget].isShort)
&& ns.hackAnalyzeChance(target) >= 0.1
&& (ns.getScriptRam("hack.js") <= ns.getServerMaxRam(host) - ns.getServerUsedRam(host) - reservedRam)
&& currentLocks.hackLock == "") {
// Try to set lock
jLockRequest.task = "hack";
jLockRequest.done = false;
ns.print(`[${target}] Attempting to lock hacking...`)
await outLock.tryWrite(JSON.stringify(jLockRequest));
// Wait for coordinator to process locks
while(currentLocks.hackLock == "") {
await ns.sleep(400);
jLocks = JSON.parse(gLock.peek());
currentLocks = jLocks.find(x => x.target == target);
}
if (currentLocks.hackLock == host) {
ns.print(`[${target}] Lock Success!`);
var currentThreads = parseInt(jStatus[indexTarget].hackThreads);
if (isNaN(currentThreads)) {
ns.print(`[${target}] ERROR: currentThreads = NaN! (${rawTargetStatus})`);
} else if (currentThreads < 0) {
ns.print(`[${target}] ERROR: currentThreads = ${currentThreads}`);
}
// Take chance into consideration...
var reqThreads = Math.floor((ns.hackAnalyzeThreads(target, ns.getServerMoneyAvailable(target) - (moneyThreshold * (jStatus[indexTarget].isShort ? 0 : 1)))) / ns.hackAnalyzeChance(target)) - currentThreads;
var numThreads = Math.floor(Math.min(reqThreads, (ns.getServerMaxRam(host) - ns.getServerUsedRam(host) - reservedRam) / ns.getScriptRam("hack.js")));
if (numThreads > 0) {
ns.print(`[${target}] Hacking... (Threads: ${numThreads})`);
hackID[indexTarget] = ns.run("hack.js", numThreads, target, host, numThreads, ns.getScriptRam("hack.js")*numThreads, ns.hackAnalyzeSecurity(numThreads, target));
} else {
ns.print(`[${target}] Skipping hack. Enough threads working on it. [${numThreads} / ${currentThreads}]`);
}
ns.print("Sleeping for 1 sec...")
await ns.sleep(1000);
jLockRequest.done = true;
ns.print(`[${target}] Removing hack lock down...`);
await outLock.tryWrite(JSON.stringify(jLockRequest));
} else {
ns.print(`[${target}] LATE LOCKED : [${currentLocks.hackLock}] has locked hacking...`);
}
} else if (currentLocks.hackLock != "") {
ns.print(`[${target}] LOCKED : [${currentLocks.hackLock}] has locked hacking...`);
}
await ns.sleep(400);
}
if (fHostKill.peek() == host)
break;
/**EXP Farm!
* We only go into this if we have enough RAM to do so after going trough all our targets.
*/
jExp = JSON.parse(gExp.peek());
var availableRAM = ns.getServerMaxRam(host) - ns.getServerUsedRam(host) - reservedRam;
var minRamRequired = (ns.getScriptRam("weaken.js") + ns.getScriptRam("grow.js") + ns.getScriptRam("hack.js"));
ns.print(`EXP Ram Left: ${availableRAM} (Req: ${minRamRequired})`);
if (availableRAM >= minRamRequired && jExp.length > 0 && curRuns >= expRuns) {
ns.print("Dedicating free RAM to EXP Farming...");
var farmIndex = randomIntFromInterval(1, jExp.length) - 1;
ns.print("[EXP] You have chosen [" + jExp[farmIndex].target + "]");
// We split available RAM by a 40/40/20% split. Hacking always goes too fast and is too devastating otherwise.
var weakThreads = Math.floor((availableRAM * 0.4) / ns.getScriptRam("weaken.js"));
var growThreads = Math.floor((availableRAM * 0.4) / ns.getScriptRam("grow.js"));
var hackThreads = Math.floor((availableRAM * 0.2) / ns.getScriptRam("hack.js"));
if (weakThreads >= 1) {
ns.print("[EXP] Running " + weakThreads + " weakens on [" + jExp[farmIndex].target + "]");
ns.run("weaken.js", weakThreads, jExp[farmIndex].target, "EXP", weakThreads);
}
if (growThreads >= 1) {
ns.print("[EXP] Running " + growThreads + " growths on [" + jExp[farmIndex].target + "]");
ns.run("grow.js", growThreads, jExp[farmIndex].target, threshModifier, "EXP", growThreads);
}
if (hackThreads >= 1) {
ns.print("[EXP] Running " + hackThreads + " hacks on [" + jExp[farmIndex].target + "]");
ns.run("hack.js", hackThreads, jExp[farmIndex].target, "EXP", hackThreads);
}
curRuns = 0;
}
else if (curRuns < expRuns) curRuns++;
if (fHostKill.peek() == host)
break;
randWait = 1000 * Math.floor(randomIntFromInterval(3, 5));
ns.print("Waiting for [" + (randWait / 1000) + "] seconds");
await ns.sleep(randWait);
}
// The only thing that can make this request is buy-server
if (fHostKill.peek() == host) {
fHostKill.read();
ns.print(`[${host}] was requested to kill itself. Cleared request!`);
}
}
/** @param {min} min number
* @param {max} max number
*/
function randomIntFromInterval(min, max) { // min and max included
return Math.max(Math.floor(Math.random() * (max - min + 1)) + min, 0);
}