1- import { Server } from '/scripts/classes/Server.js' ;
21/**@typedef {import('/scripts/index.js').NS } NS */
32
3+ // --- EXPORTED CONSTANTS ---
4+ const worker_size = 1.75 ;
5+
6+
47/** @param {NS } ns */
58export async function main ( ns ) {
69 ns . tprint ( 'No user servicable parts inside.' ) ;
@@ -17,6 +20,8 @@ export async function main(ns) {
1720 ns . tprint ( JSON . stringify ( servers ) ) ;
1821}
1922
23+
24+ // --- UTILITY FUNCTIONS ---
2025/**
2126 * @typedef {import(".").Player } Player
2227 * @property {number } exploits - The number of exploits owned by the player
@@ -131,11 +136,11 @@ export function percentToGraph(pct, graph=' '){
131136 const progressSteps = '▏▎▍▌▋▊▉█' ;
132137 let progressbar = Array . from ( graph ) ;
133138 let filled = Math . floor ( pct * progressbar . length ) ;
134- for ( let i = 0 ; i < filled ; i ++ ) {
139+ for ( let i = 0 ; i <= filled ; i ++ ) {
135140 progressbar [ i ] = progressSteps [ progressSteps . length - 1 ] ;
136141 }
137142 let pctleft = ( pct * progressbar . length ) - filled ;
138- let whichbar = Math . round ( pctleft * progressSteps . length ) ;
143+ let whichbar = Math . floor ( pctleft * progressSteps . length ) ;
139144 progressbar [ filled ] = progressSteps [ whichbar ] ;
140145 progressbar = progressbar . join ( '' ) ;
141146 return progressbar ;
@@ -213,6 +218,11 @@ export function getAllServerObjects(servers, ns) {
213218export function updateAttackStatus ( _servers , ns ) {
214219 // We have a mix of Arrays and servername-keyed Objects in my codebase. Ought to convert to all Arrays, but I haven't paid the technical debt yet.
215220 let servers = Object . values ( _servers ) ;
221+ // Reset our counts.
222+ for ( const server of servers ) {
223+ server . running = { grow : 0 , hack : 0 , weaken : 0 } ;
224+ server . targetedBy = { grow : 0 , hack : 0 , weaken : 0 } ;
225+ }
216226
217227 // Server.running and Server.targetedBy need to know what's running on all the servers.
218228 let isHackProcess = ( proc ) =>
@@ -222,8 +232,6 @@ export function updateAttackStatus(_servers, ns) {
222232 let isGrowProcess = ( proc ) =>
223233 proc . filename . includes ( 'grow' ) && proc . args . length > 0 && servers . some ( ( s ) => s . name === proc . args [ 0 ] ) ;
224234 for ( const server of servers ) {
225- server . running = { grow : 0 , hack : 0 , weaken : 0 } ;
226- server . targetedBy = { grow : 0 , hack : 0 , weaken : 0 } ;
227235 let ps = ns . ps ( server . name ) ;
228236 for ( const proc of ps ) {
229237 let procType = 'unknown' ;
@@ -357,3 +365,135 @@ export function getPoolFromServers(servers, ns) {
357365 }
358366 return pool ;
359367}
368+
369+ export class C2Message {
370+ /**
371+ * @param {string } from
372+ * @param {string } to
373+ * @param {string } action
374+ * @param {string } key
375+ * @param {* } value
376+ * @param {import("/scripts/index.js").NS } ns
377+ */
378+ constructor ( to , from , action , key , value , ns ) {
379+ this . type = 'C2Message' ;
380+ this . subtype = '' ;
381+ this . to = to ;
382+ this . from = from ;
383+ this . action = action ;
384+ this . key = key ;
385+ this . value = value ;
386+ this . createtime = ns . getTimeSinceLastAug ( ) ;
387+ }
388+ }
389+
390+ export class C2Command extends C2Message {
391+ constructor ( to , from , action , key , value , ns ) {
392+ super ( to , from , action , key , value , ns ) ;
393+ this . subtype = 'C2Command' ;
394+ }
395+ }
396+
397+ export class C2Response extends C2Message {
398+ constructor ( to , from , action , key , value , ns ) {
399+ super ( to , from , action , key , value , ns ) ;
400+ this . subtype = 'C2Response' ;
401+ }
402+ }
403+
404+
405+ /**
406+ * @export
407+ * @class Server
408+ */
409+ const PurchasedServerNames = [
410+ 'Alpha(α)' , 'Beta(β)' , 'Gamma(γ)' , 'Delta(Δ)' , 'Epsilon(ε)' , 'Zeta(ζ)' , 'Eta(η)' ,
411+ 'Theta(θ)' , 'Iota(ι)' , 'Kappa(κ)' , 'Lambda(λ)' , 'Mu(μ)' , 'Nu(ν)' , 'Xi(ξ)' , 'Omicron(ο)' ,
412+ 'Pi(π)' , 'Rho(ρ)' , 'Sigma(σ)' , 'Tau(τ)' , 'Upsilon(υ)' , 'Phi(φ)' , 'Chi(χ)' , 'Psi(Ψ)' ,
413+ 'Omega(Ω)' , 'Aleph(א)' , 'daemon' ,
414+ ] ;
415+
416+ export class Server {
417+ /**
418+ * Creates an instance of Server.
419+ * @param {string } servername
420+ * @param {import(".").NS } ns
421+ * @memberof Server
422+ */
423+ constructor ( servername , ns ) {
424+ this . name = servername ;
425+ this . update ( ns ) ;
426+ this . running = { hack : 0 , grow : 0 , weaken : 0 } ;
427+ this . targetedBy = { hack : 0 , grow : 0 , weaken : 0 } ;
428+ this . desired = { hack : 0 , grow : 0 , weaken : 0 } ;
429+ this . isPurchasedServer = false ;
430+ // Let's not actually call ns.getPurchasedServers. That's expensive! Just check for our common server names.
431+ let basename = this . name . split ( '-' ) [ 0 ] ;
432+ if ( PurchasedServerNames . includes ( basename ) ) {
433+ this . isPurchasedServer = true ;
434+ }
435+ this . symbol = this . name [ 0 ] ;
436+
437+ let left = this . name . indexOf ( '(' ) ;
438+ let right = this . name . lastIndexOf ( ')' ) ;
439+ if ( left !== - 1 && right !== - 1 ) {
440+ this . symbol = this . name . substring ( left + 1 , right )
441+ }
442+ }
443+ update ( ns ) {
444+ let servername = this . name ;
445+
446+ this . ram = ns . getServerMaxRam ( servername ) ;
447+ this . cores = ns . getServer ( servername ) . cpuCores ;
448+ // Try to leave an extra 10% free on home
449+ this . freeRam = this . ram - ns . getServerUsedRam ( servername ) ;
450+ this . rooted = ns . hasRootAccess ( servername ) ;
451+ this . slots = 0 ;
452+ if ( this . rooted ) {
453+ this . slots = Math . floor ( this . freeRam / worker_size ) ;
454+ }
455+ this . maxMoney = ns . getServerMaxMoney ( servername ) ;
456+ this . currentMoney = ns . getServerMoneyAvailable ( servername ) ;
457+ this . hackFactor = ns . hackAnalyze ( servername ) ;
458+ this . hackTime = ns . getHackTime ( servername ) ;
459+ this . growTime = ns . getGrowTime ( servername ) ;
460+ this . weakenTime = ns . getWeakenTime ( servername ) ;
461+ this . securityBase = ns . getServerMinSecurityLevel ( servername ) ;
462+ this . securityCurrent = ns . getServerSecurityLevel ( servername ) ;
463+ this . levelRequired = ns . getServerRequiredHackingLevel ( servername ) ;
464+ }
465+ }
466+ export class SubSystem {
467+ /**
468+ * @param {string } name - The human readable name of this subsystem
469+ * @param {string } filename - The script name that starts this subsystem
470+ */
471+ constructor ( name , filename , host ) {
472+ this . name = name ;
473+ this . filename = filename ;
474+ this . host = host ;
475+ this . status = 'UNKNOWN' ;
476+ /** @type {import("/scripts/index.js").ProcessInfo } */
477+ this . process = { } ;
478+ /** @type {import("/scripts/index.js").RunningScript } */
479+ this . scriptInfo = { } ;
480+ } // end constructor()
481+
482+ /**
483+ * @param {import("/scripts/index.js").NS } ns
484+ */
485+ refreshStatus ( ns ) {
486+ let ps = ns . ps ( this . host ) ;
487+ ps . reverse ( ) ;
488+ this . status = 'STOPPED' ;
489+ for ( const process of ps ) {
490+ let isSystemScript = this . filename === process . filename ;
491+ if ( isSystemScript ) {
492+ this . status = 'RUNNING' ;
493+ this . process = process ;
494+ this . scriptInfo = ns . getRunningScript ( this . filename , this . host , ...process . args ) ;
495+ break ;
496+ }
497+ }
498+ } // end refreshStatus()
499+ }
0 commit comments