2022-04-20 11:32:10 -04:00
import { ArgParser } from '/scripts/lib/arg-parser' ;
import { addCSS , htmlPrint , pruneTree , serializeFunction , terminal } from '/scripts/lib/utils' ;
import { connectionString } from '/scripts/connect' ;
import { scanNetwork } from '/scripts/crawler' ;
2022-02-24 16:58:39 -05:00
2022-04-20 11:32:10 -04:00
const CSS = `
# terminal a : not ( [ href ] ) : hover {
cursor : pointer ;
text - decoration : underline ;
}
. srv - fnr { color : # BBBB11 ; }
. srv - fr {
color : # FFFF44 ;
font - weight : bold ;
}
. srv - nr { color : # 11 BB11 ; }
. srv - r {
color : # 00 FF00 ;
font - weight : bold ;
} `
export const factionServers = [ 'CSEC' , 'avmnite-02h' , 'I.I.I.I' , 'run4theh111z' , 'w0r1d_d43m0n' ] ;
2022-03-15 20:41:23 -04:00
/ * *
2022-04-20 11:32:10 -04:00
* Scan the network for servers and display as an ASCII tree . Servers with root access are highlighted & bold .
*
* @ param { NS } ns - BitBurner API
2022-03-15 20:41:23 -04:00
* /
2022-02-24 16:58:39 -05:00
export async function main ( ns ) {
2022-04-20 11:32:10 -04:00
// Setup
ns . disableLog ( 'ALL' ) ;
const argParser = new ArgParser ( 'network-graph.js' , 'Scan the network for servers and display as an ASCII tree. Servers with root access are highlighted & bold. Click to automatically connect.' , [
{ name : 'server' , desc : 'Point to start scan from, defaults to local server' , optional : true , default : ns . getHostname ( ) } ,
{ name : 'depth' , desc : 'Depth to scan to' , flags : [ '-d' , '--depth' ] , default : Infinity } ,
2022-04-26 16:46:52 -04:00
{ name : 'filter' , desc : 'Filter to servers matching name' , flags : [ '-f' , '--filter' ] } ,
{ name : 'regex' , desc : 'Filter to servers matching pattern' , flags : [ '-e' , '--regex' ] } ,
2022-04-20 11:32:10 -04:00
{ name : 'level' , desc : 'Display the required hack level & number of ports to root: [level|port]' , flags : [ '-l' , '--level' ] , default : false } ,
{ name : 'notRooted' , desc : 'Filter to servers that have not been rooted' , flags : [ '-n' , '--not-rooted' ] , default : false } ,
{ name : 'rooted' , desc : 'Filter to servers that have been rooted' , flags : [ '-r' , '--rooted' ] , default : false } ,
{ name : 'specs' , desc : 'Display the server specifications: {CPU|RAM}' , flags : [ '-s' , '--specs' ] , default : false } ,
{ name : 'usage' , desc : 'Display the server utilization: (USG%)' , flags : [ '-u' , '--usage' ] , default : false } ,
{ name : 'verbose' , desc : 'Display level, specs & usage in that order: [HL|P] {CPU|RAM} (USG%)' , flags : [ '-v' , '--verbose' ] , default : false } ,
] ) ;
const args = argParser . parse ( ns . args ) ;
2022-02-24 16:58:39 -05:00
/ * *
2022-04-20 11:32:10 -04:00
* Get the color class for the server .
*
* @ param { string } server - Server to figure out color for .
2022-02-24 16:58:39 -05:00
* /
2022-04-20 11:32:10 -04:00
function color ( server ) {
const rooted = ns . getServer ( server ) . hasAdminRights ; // Already using getServer so we might as well keep using it
if ( factionServers . includes ( server ) ) return rooted ? 'srv-fr' : 'srv-fnr' ;
return rooted ? 'srv-r' : 'srv-nr' ;
2022-02-24 16:58:39 -05:00
}
2022-04-20 11:32:10 -04:00
/ * *
* Create serialized connection command .
*
* @ param { string } server - server to connect to .
* /
function connectFn ( server ) {
return serializeFunction ( terminal , connectionString ( ns , server , 'home' ) ) ;
}
2022-03-15 22:05:34 -04:00
2022-04-20 11:32:10 -04:00
/ * *
* Iterate tree & convert to ascii .
*
* @ param { Object } tree - Tree to parse
* @ param { string } spacer - Spacer text for tree formatting
* /
function render ( tree , spacer = ' ' ) {
const nodes = Object . keys ( tree ) ;
for ( let i = 0 ; i < nodes . length ; i ++ ) {
const server = nodes [ i ] , info = ns . getServer ( server ) ;
let stats = '' ;
if ( args [ 'level' ] || args [ 'verbose' ] ) stats += ` [ ${ info . requiredHackingSkill } | ${ info . openPortCount } ] ` ;
if ( args [ 'specs' ] || args [ 'verbose' ] ) stats += ` { ${ info . cpuCores } | ${ info . maxRam } } ` ;
if ( args [ 'usage' ] || args [ 'verbose' ] ) stats += ` ( ${ Math . round ( info . ramUsed / info . maxRam * 100 ) || 0 } %) ` ;
const last = i == nodes . length - 1 ;
const branch = last ? '└─ ' : '├─ ' ;
htmlPrint ( spacer + branch + ` <a class=" ${ color ( server ) } " onclick=" ${ connectFn ( server ) } "> ${ server + stats } </a> ` ) ;
2022-04-26 16:36:01 -04:00
render ( tree [ server ] , spacer + ( last ? ' ' : '│ ' ) ) ;
2022-04-20 11:32:10 -04:00
}
2022-03-15 22:05:34 -04:00
}
2022-04-20 11:32:10 -04:00
// Help
if ( args [ 'help' ] || args [ '_error' ] . length )
return ns . tprint ( argParser . help ( args [ 'help' ] ? null : args [ '_error' ] [ 0 ] , args [ '_command' ] ) ) ;
// Gather network information
const [ ignore , network ] = scanNetwork ( ns , args [ 'server' ] , args [ 'depth' ] ) ;
// Add flags filters
if ( args [ 'regex' ] ) pruneTree ( network , s => RegExp ( args [ 'regex' ] ) . test ( s ) ) ;
if ( args [ 'filter' ] ) pruneTree ( network , s => s == args [ 'filter' ] ) ;
if ( args [ 'rooted' ] ) pruneTree ( network , s => ns . getServer ( s ) . hasAdminRights ) ; // Already using getServer so we might as well keep using it
if ( args [ 'notRooted' ] ) pruneTree ( network , s => ! ns . getServer ( s ) . hasAdminRights ) ; // Already using getServer so we might as well keep using it
// Output
addCSS ( 'network-graph' , CSS ) ;
htmlPrint ( ` \n <a class="srv-tree-span ${ color ( args [ 'server' ] ) } " onclick=" ${ connectFn ( args [ 'server' ] ) } "> ${ args [ 'server' ] } </a> ` ) ;
render ( network ) ;
htmlPrint ( '\n' ) ;
}
/ * *
* BitBurner autocomplete .
*
* @ param { { servers : string [ ] , txts : string [ ] , scripts : string [ ] , flags : string [ ] } } data - Contextual information
* @ returns { string [ ] } - Pool of autocomplete options
* /
export function autocomplete ( data ) {
return [ ... data . servers ] ;
2022-02-24 16:58:39 -05:00
}