mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-26 17:43:48 +01:00
most terminal converted to ts
This commit is contained in:
parent
8097364242
commit
2922e42055
13
package-lock.json
generated
13
package-lock.json
generated
@ -61,6 +61,7 @@
|
|||||||
"@babel/preset-react": "^7.0.0",
|
"@babel/preset-react": "^7.0.0",
|
||||||
"@babel/preset-typescript": "^7.15.0",
|
"@babel/preset-typescript": "^7.15.0",
|
||||||
"@testing-library/cypress": "^8.0.1",
|
"@testing-library/cypress": "^8.0.1",
|
||||||
|
"@types/file-saver": "^2.0.3",
|
||||||
"@types/jest": "^27.0.1",
|
"@types/jest": "^27.0.1",
|
||||||
"@types/lodash": "^4.14.168",
|
"@types/lodash": "^4.14.168",
|
||||||
"@types/node": "^16.9.1",
|
"@types/node": "^16.9.1",
|
||||||
@ -3689,6 +3690,12 @@
|
|||||||
"@babel/types": "^7.3.0"
|
"@babel/types": "^7.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/file-saver": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-MBIou8pd/41jkff7s97B47bc9+p0BszqqDJsO51yDm49uUxeKzrfuNl5fSLC6BpLEWKA8zlwyqALVmXrFwoBHQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/glob": {
|
"node_modules/@types/glob": {
|
||||||
"version": "7.1.4",
|
"version": "7.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz",
|
||||||
@ -30122,6 +30129,12 @@
|
|||||||
"@babel/types": "^7.3.0"
|
"@babel/types": "^7.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/file-saver": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-MBIou8pd/41jkff7s97B47bc9+p0BszqqDJsO51yDm49uUxeKzrfuNl5fSLC6BpLEWKA8zlwyqALVmXrFwoBHQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/glob": {
|
"@types/glob": {
|
||||||
"version": "7.1.4",
|
"version": "7.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz",
|
||||||
|
244
package.json
244
package.json
@ -1,154 +1,308 @@
|
|||||||
{
|
{
|
||||||
|
|
||||||
"name": "bitburner",
|
"name": "bitburner",
|
||||||
|
|
||||||
"license": "SEE LICENSE IN license.txt",
|
"license": "SEE LICENSE IN license.txt",
|
||||||
|
|
||||||
"version": "0.53.0",
|
"version": "0.53.0",
|
||||||
|
|
||||||
"main": "electron-main.js",
|
"main": "electron-main.js",
|
||||||
|
|
||||||
"author": {
|
"author": {
|
||||||
|
|
||||||
"name": "Daniel Xie"
|
"name": "Daniel Xie"
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
|
||||||
"url": "https://github.com/danielyxie/bitburner/issues"
|
"url": "https://github.com/danielyxie/bitburner/issues"
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
||||||
"@material-ui/core": "^4.11.3",
|
"@material-ui/core": "^4.11.3",
|
||||||
|
|
||||||
"@material-ui/icons": "^4.11.2",
|
"@material-ui/icons": "^4.11.2",
|
||||||
|
|
||||||
"@monaco-editor/react": "^4.2.2",
|
"@monaco-editor/react": "^4.2.2",
|
||||||
|
|
||||||
"@types/js-beautify": "^1.13.2",
|
"@types/js-beautify": "^1.13.2",
|
||||||
|
|
||||||
"@types/numeral": "0.0.25",
|
"@types/numeral": "0.0.25",
|
||||||
|
|
||||||
"@types/react": "^16.8.6",
|
"@types/react": "^16.8.6",
|
||||||
|
|
||||||
"@types/react-dom": "^16.8.2",
|
"@types/react-dom": "^16.8.2",
|
||||||
|
|
||||||
"acorn": "^8.4.1",
|
"acorn": "^8.4.1",
|
||||||
|
|
||||||
"acorn-walk": "^8.1.1",
|
"acorn-walk": "^8.1.1",
|
||||||
|
|
||||||
"ajv": "^5.1.5",
|
"ajv": "^5.1.5",
|
||||||
|
|
||||||
"ajv-keywords": "^2.0.0",
|
"ajv-keywords": "^2.0.0",
|
||||||
|
|
||||||
"arg": "^5.0.0",
|
"arg": "^5.0.0",
|
||||||
|
|
||||||
"async": "^2.6.1",
|
"async": "^2.6.1",
|
||||||
|
|
||||||
"autosize": "^4.0.2",
|
"autosize": "^4.0.2",
|
||||||
|
|
||||||
"brace": "^0.11.1",
|
"brace": "^0.11.1",
|
||||||
|
|
||||||
"codemirror": "^5.58.2",
|
"codemirror": "^5.58.2",
|
||||||
|
|
||||||
"decimal.js": "7.2.3",
|
"decimal.js": "7.2.3",
|
||||||
|
|
||||||
"enhanced-resolve": "^4.0.0",
|
"enhanced-resolve": "^4.0.0",
|
||||||
|
|
||||||
"escodegen": "^1.11.0",
|
"escodegen": "^1.11.0",
|
||||||
|
|
||||||
"escope": "^3.6.0",
|
"escope": "^3.6.0",
|
||||||
|
|
||||||
"file-saver": "^1.3.8",
|
"file-saver": "^1.3.8",
|
||||||
|
|
||||||
"interpret": "^1.0.0",
|
"interpret": "^1.0.0",
|
||||||
|
|
||||||
"jquery": "^3.5.0",
|
"jquery": "^3.5.0",
|
||||||
|
|
||||||
"jshint": "^2.10.2",
|
"jshint": "^2.10.2",
|
||||||
|
|
||||||
"json-loader": "^0.5.4",
|
"json-loader": "^0.5.4",
|
||||||
|
|
||||||
"jsplumb": "^2.6.8",
|
"jsplumb": "^2.6.8",
|
||||||
|
|
||||||
"jszip": "^3.7.0",
|
"jszip": "^3.7.0",
|
||||||
|
|
||||||
"loader-runner": "^2.3.0",
|
"loader-runner": "^2.3.0",
|
||||||
|
|
||||||
"loader-utils": "^1.1.0",
|
"loader-utils": "^1.1.0",
|
||||||
|
|
||||||
"mathjax-full": "^3.2.0",
|
"mathjax-full": "^3.2.0",
|
||||||
|
|
||||||
"mathjax-react": "^1.0.6",
|
"mathjax-react": "^1.0.6",
|
||||||
|
|
||||||
"memory-fs": "~0.4.1",
|
"memory-fs": "~0.4.1",
|
||||||
|
|
||||||
"monaco-editor": "^0.27.0",
|
"monaco-editor": "^0.27.0",
|
||||||
|
|
||||||
"node-sass": "^6.0.1",
|
"node-sass": "^6.0.1",
|
||||||
|
|
||||||
"normalize.css": "^8.0.0",
|
"normalize.css": "^8.0.0",
|
||||||
|
|
||||||
"numeral": "2.0.6",
|
"numeral": "2.0.6",
|
||||||
|
|
||||||
"react": "^16.8.3",
|
"react": "^16.8.3",
|
||||||
|
|
||||||
"react-dom": "^16.8.3",
|
"react-dom": "^16.8.3",
|
||||||
|
|
||||||
"react-modal": "^3.12.1",
|
"react-modal": "^3.12.1",
|
||||||
|
|
||||||
"sprintf-js": "^1.1.1",
|
"sprintf-js": "^1.1.1",
|
||||||
|
|
||||||
"tapable": "^1.0.0",
|
"tapable": "^1.0.0",
|
||||||
|
|
||||||
"treant-js": "^1.0.1",
|
"treant-js": "^1.0.1",
|
||||||
|
|
||||||
"unused-webpack-plugin": "^2.4.0",
|
"unused-webpack-plugin": "^2.4.0",
|
||||||
|
|
||||||
"uuid": "^3.2.1",
|
"uuid": "^3.2.1",
|
||||||
|
|
||||||
"w3c-blob": "0.0.1"
|
"w3c-blob": "0.0.1"
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"description": "A cyberpunk-themed incremental game",
|
"description": "A cyberpunk-themed incremental game",
|
||||||
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
||||||
"@babel/core": "^7.3.4",
|
"@babel/core": "^7.3.4",
|
||||||
|
|
||||||
"@babel/preset-env": "^7.15.0",
|
"@babel/preset-env": "^7.15.0",
|
||||||
|
|
||||||
"@babel/preset-react": "^7.0.0",
|
"@babel/preset-react": "^7.0.0",
|
||||||
|
|
||||||
"@babel/preset-typescript": "^7.15.0",
|
"@babel/preset-typescript": "^7.15.0",
|
||||||
|
|
||||||
"@testing-library/cypress": "^8.0.1",
|
"@testing-library/cypress": "^8.0.1",
|
||||||
|
|
||||||
|
"@types/file-saver": "^2.0.3",
|
||||||
|
|
||||||
"@types/jest": "^27.0.1",
|
"@types/jest": "^27.0.1",
|
||||||
|
|
||||||
"@types/lodash": "^4.14.168",
|
"@types/lodash": "^4.14.168",
|
||||||
|
|
||||||
"@types/node": "^16.9.1",
|
"@types/node": "^16.9.1",
|
||||||
|
|
||||||
"@typescript-eslint/eslint-plugin": "^4.22.0",
|
"@typescript-eslint/eslint-plugin": "^4.22.0",
|
||||||
|
|
||||||
"@typescript-eslint/parser": "^4.22.0",
|
"@typescript-eslint/parser": "^4.22.0",
|
||||||
|
|
||||||
"babel-jest": "^27.0.6",
|
"babel-jest": "^27.0.6",
|
||||||
|
|
||||||
"babel-loader": "^8.0.5",
|
"babel-loader": "^8.0.5",
|
||||||
|
|
||||||
"beautify-lint": "^1.0.3",
|
"beautify-lint": "^1.0.3",
|
||||||
|
|
||||||
"benchmark": "^2.1.1",
|
"benchmark": "^2.1.1",
|
||||||
|
|
||||||
"bundle-loader": "~0.5.0",
|
"bundle-loader": "~0.5.0",
|
||||||
|
|
||||||
"css-loader": "^0.28.11",
|
"css-loader": "^0.28.11",
|
||||||
|
|
||||||
"cypress": "^8.3.1",
|
"cypress": "^8.3.1",
|
||||||
"es6-promise-polyfill": "^1.1.1",
|
|
||||||
"eslint": "^7.24.0",
|
|
||||||
"eslint-plugin-node": "^11.1.0",
|
|
||||||
"file-loader": "^1.1.11",
|
|
||||||
"fork-ts-checker-webpack-plugin": "^6.3.3",
|
|
||||||
"html-webpack-plugin": "^3.2.0",
|
|
||||||
"http-server": "^13.0.1",
|
|
||||||
"i18n-webpack-plugin": "^1.0.0",
|
|
||||||
"istanbul": "^0.4.5",
|
|
||||||
"jest": "^27.1.0",
|
|
||||||
"js-beautify": "^1.5.10",
|
|
||||||
"jsdom": "^15.0.0",
|
|
||||||
"jsdom-global": "^3.0.2",
|
|
||||||
"json5": "^1.0.1",
|
|
||||||
"less": "^3.9.0",
|
|
||||||
"less-loader": "^4.1.0",
|
|
||||||
"lodash": "^4.17.21",
|
|
||||||
"mini-css-extract-plugin": "^0.4.1",
|
|
||||||
"mkdirp": "^0.5.1",
|
|
||||||
"null-loader": "^1.0.0",
|
|
||||||
"prettier": "^2.3.2",
|
|
||||||
"raw-loader": "~0.5.0",
|
|
||||||
"regenerator-runtime": "^0.13.9",
|
|
||||||
"sass-loader": "^7.0.3",
|
|
||||||
"script-loader": "~0.7.0",
|
|
||||||
"should": "^11.1.1",
|
|
||||||
"simple-git": "^1.96.0",
|
|
||||||
"sinon": "^2.3.2",
|
|
||||||
"source-map": "^0.7.3",
|
|
||||||
"start-server-and-test": "^1.14.0",
|
|
||||||
"style-loader": "^0.21.0",
|
|
||||||
"stylelint": "^9.2.1",
|
|
||||||
"stylelint-declaration-use-variable": "^1.6.1",
|
|
||||||
"stylelint-order": "^0.8.1",
|
|
||||||
"typescript": "^4.2.4",
|
|
||||||
"uglify-es": "^3.3.9",
|
|
||||||
"uglifyjs-webpack-plugin": "^1.3.0",
|
|
||||||
"url-loader": "^1.0.1",
|
|
||||||
"watchpack": "^1.6.0",
|
|
||||||
"webpack": "^4.46.0",
|
|
||||||
"webpack-cli": "^3.3.12",
|
|
||||||
"webpack-dev-middleware": "^3.7.3",
|
|
||||||
"webpack-dev-server": "^3.11.2",
|
|
||||||
"worker-loader": "^2.0.0",
|
|
||||||
"electron": "^14.0.1",
|
"electron": "^14.0.1",
|
||||||
"electron-packager": "^15.4.0"
|
|
||||||
|
"electron-packager": "^15.4.0",
|
||||||
|
|
||||||
|
"es6-promise-polyfill": "^1.1.1",
|
||||||
|
|
||||||
|
"eslint": "^7.24.0",
|
||||||
|
|
||||||
|
"eslint-plugin-node": "^11.1.0",
|
||||||
|
|
||||||
|
"file-loader": "^1.1.11",
|
||||||
|
|
||||||
|
"fork-ts-checker-webpack-plugin": "^6.3.3",
|
||||||
|
|
||||||
|
"html-webpack-plugin": "^3.2.0",
|
||||||
|
|
||||||
|
"http-server": "^13.0.1",
|
||||||
|
|
||||||
|
"i18n-webpack-plugin": "^1.0.0",
|
||||||
|
|
||||||
|
"istanbul": "^0.4.5",
|
||||||
|
|
||||||
|
"jest": "^27.1.0",
|
||||||
|
|
||||||
|
"js-beautify": "^1.5.10",
|
||||||
|
|
||||||
|
"jsdom": "^15.0.0",
|
||||||
|
|
||||||
|
"jsdom-global": "^3.0.2",
|
||||||
|
|
||||||
|
"json5": "^1.0.1",
|
||||||
|
|
||||||
|
"less": "^3.9.0",
|
||||||
|
|
||||||
|
"less-loader": "^4.1.0",
|
||||||
|
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
|
||||||
|
"mini-css-extract-plugin": "^0.4.1",
|
||||||
|
|
||||||
|
"mkdirp": "^0.5.1",
|
||||||
|
|
||||||
|
"null-loader": "^1.0.0",
|
||||||
|
|
||||||
|
"prettier": "^2.3.2",
|
||||||
|
|
||||||
|
"raw-loader": "~0.5.0",
|
||||||
|
|
||||||
|
"regenerator-runtime": "^0.13.9",
|
||||||
|
|
||||||
|
"sass-loader": "^7.0.3",
|
||||||
|
|
||||||
|
"script-loader": "~0.7.0",
|
||||||
|
|
||||||
|
"should": "^11.1.1",
|
||||||
|
|
||||||
|
"simple-git": "^1.96.0",
|
||||||
|
|
||||||
|
"sinon": "^2.3.2",
|
||||||
|
|
||||||
|
"source-map": "^0.7.3",
|
||||||
|
|
||||||
|
"start-server-and-test": "^1.14.0",
|
||||||
|
|
||||||
|
"style-loader": "^0.21.0",
|
||||||
|
|
||||||
|
"stylelint": "^9.2.1",
|
||||||
|
|
||||||
|
"stylelint-declaration-use-variable": "^1.6.1",
|
||||||
|
|
||||||
|
"stylelint-order": "^0.8.1",
|
||||||
|
|
||||||
|
"typescript": "^4.2.4",
|
||||||
|
|
||||||
|
"uglify-es": "^3.3.9",
|
||||||
|
|
||||||
|
"uglifyjs-webpack-plugin": "^1.3.0",
|
||||||
|
|
||||||
|
"url-loader": "^1.0.1",
|
||||||
|
|
||||||
|
"watchpack": "^1.6.0",
|
||||||
|
|
||||||
|
"webpack": "^4.46.0",
|
||||||
|
|
||||||
|
"webpack-cli": "^3.3.12",
|
||||||
|
|
||||||
|
"webpack-dev-middleware": "^3.7.3",
|
||||||
|
|
||||||
|
"webpack-dev-server": "^3.11.2",
|
||||||
|
|
||||||
|
"worker-loader": "^2.0.0"
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
||||||
"node": ">=8 || <=9"
|
"node": ">=8 || <=9"
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"homepage": "https://github.com/danielyxie/bitburner",
|
"homepage": "https://github.com/danielyxie/bitburner",
|
||||||
|
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
||||||
"url": "git+https://github.com/danielyxie/bitburner.git"
|
"url": "git+https://github.com/danielyxie/bitburner.git"
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
||||||
"cy:test": "start-server-and-test start http://localhost:8000 cy:run",
|
"cy:test": "start-server-and-test start http://localhost:8000 cy:run",
|
||||||
|
|
||||||
"cy:dev": "start-server-and-test start:dev http://localhost:8000 cy:open",
|
"cy:dev": "start-server-and-test start:dev http://localhost:8000 cy:open",
|
||||||
|
|
||||||
"cy:open": "cypress open",
|
"cy:open": "cypress open",
|
||||||
|
|
||||||
"cy:run": "cypress run",
|
"cy:run": "cypress run",
|
||||||
|
|
||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
|
|
||||||
"start": "http-server -p 8000",
|
"start": "http-server -p 8000",
|
||||||
|
|
||||||
"start:dev": "webpack-dev-server --progress --env.devServer --mode development",
|
"start:dev": "webpack-dev-server --progress --env.devServer --mode development",
|
||||||
|
|
||||||
"start:container": "webpack-dev-server --progress --env.devServer --mode development --env.runInContainer",
|
"start:container": "webpack-dev-server --progress --env.devServer --mode development --env.runInContainer",
|
||||||
|
|
||||||
"build:dev": "webpack --mode development",
|
"build:dev": "webpack --mode development",
|
||||||
|
|
||||||
"lint": "npm run lint:jsts & npm run lint:style",
|
"lint": "npm run lint:jsts & npm run lint:style",
|
||||||
|
|
||||||
"lint:jsts": "eslint --fix . --ext js,jsx,ts,tsx",
|
"lint:jsts": "eslint --fix . --ext js,jsx,ts,tsx",
|
||||||
|
|
||||||
"lint:style": "stylelint --fix ./css/*",
|
"lint:style": "stylelint --fix ./css/*",
|
||||||
|
|
||||||
"preinstall": "node ./scripts/engines-check.js",
|
"preinstall": "node ./scripts/engines-check.js",
|
||||||
|
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
|
|
||||||
"test:watch": "jest --watch",
|
"test:watch": "jest --watch",
|
||||||
|
|
||||||
"watch": "webpack --watch --mode production",
|
"watch": "webpack --watch --mode production",
|
||||||
|
|
||||||
"watch:dev": "webpack --watch --mode development",
|
"watch:dev": "webpack --watch --mode development",
|
||||||
|
|
||||||
"package-electron": "electron-packager .package bitburner --all --out .build --overwrite --icon .package/icon.png"
|
"package-electron": "electron-packager .package bitburner --all --out .build --overwrite --icon .package/icon.png"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +179,6 @@ export class CodingContract {
|
|||||||
removePopup(popupId);
|
removePopup(popupId);
|
||||||
},
|
},
|
||||||
onAttempt: (val: string) => {
|
onAttempt: (val: string) => {
|
||||||
console.error("attempting");
|
|
||||||
if (this.isSolution(val)) {
|
if (this.isSolution(val)) {
|
||||||
resolve(CodingContractResult.Success);
|
resolve(CodingContractResult.Success);
|
||||||
} else {
|
} else {
|
||||||
|
@ -54,7 +54,7 @@ export function executeDarkwebTerminalCommand(commandArray: string[]): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function listAllDarkwebItems(): void {
|
export function listAllDarkwebItems(): void {
|
||||||
for (const key in DarkWebItems) {
|
for (const key in DarkWebItems) {
|
||||||
const item = DarkWebItems[key];
|
const item = DarkWebItems[key];
|
||||||
postElement(
|
postElement(
|
||||||
@ -65,7 +65,7 @@ function listAllDarkwebItems(): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buyDarkwebItem(itemName: string): void {
|
export function buyDarkwebItem(itemName: string): void {
|
||||||
itemName = itemName.toLowerCase();
|
itemName = itemName.toLowerCase();
|
||||||
|
|
||||||
// find the program that matches, if any
|
// find the program that matches, if any
|
||||||
|
1
src/Fconf/Fconf.d.ts
vendored
1
src/Fconf/Fconf.d.ts
vendored
@ -1 +1,2 @@
|
|||||||
export declare function parseFconfSettings(config: string): void;
|
export declare function parseFconfSettings(config: string): void;
|
||||||
|
export declare function createFconf(): string;
|
||||||
|
@ -7,7 +7,7 @@ export interface IEngine {
|
|||||||
_lastUpdate: number;
|
_lastUpdate: number;
|
||||||
hideAllContent: () => void;
|
hideAllContent: () => void;
|
||||||
loadTerminalContent: () => void;
|
loadTerminalContent: () => void;
|
||||||
loadScriptEditorContent: () => void;
|
loadScriptEditorContent: (filename?: string, code?: string) => void;
|
||||||
loadActiveScriptsContent: () => void;
|
loadActiveScriptsContent: () => void;
|
||||||
loadCreateProgramContent: () => void;
|
loadCreateProgramContent: () => void;
|
||||||
loadCharacterContent: () => void;
|
loadCharacterContent: () => void;
|
||||||
|
1
src/Message/MessageHelpers.d.ts
vendored
Normal file
1
src/Message/MessageHelpers.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export declare function showMessage(msg: Message): void;
|
1
src/NetscriptWorker.d.ts
vendored
Normal file
1
src/NetscriptWorker.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export declare function startWorkerScript(script: RunningScript, server: BaseServer): boolean;
|
@ -24,6 +24,7 @@ import { Exploit } from "../Exploits/Exploit";
|
|||||||
import { ICorporation } from "../Corporation/ICorporation";
|
import { ICorporation } from "../Corporation/ICorporation";
|
||||||
import { IGang } from "../Gang/IGang";
|
import { IGang } from "../Gang/IGang";
|
||||||
import { IBladeburner } from "../Bladeburner/IBladeburner";
|
import { IBladeburner } from "../Bladeburner/IBladeburner";
|
||||||
|
import { ICodingContractReward } from "../CodingContracts";
|
||||||
|
|
||||||
export interface IPlayer {
|
export interface IPlayer {
|
||||||
// Class members
|
// Class members
|
||||||
@ -207,4 +208,5 @@ export interface IPlayer {
|
|||||||
queueAugmentation(augmentationName: string): void;
|
queueAugmentation(augmentationName: string): void;
|
||||||
receiveInvite(factionName: string): void;
|
receiveInvite(factionName: string): void;
|
||||||
updateSkillLevels(): void;
|
updateSkillLevels(): void;
|
||||||
|
gainCodingContractReward(reward: ICodingContractReward, difficulty?: number): string;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
export interface IPlayer {
|
import { BaseServer } from "../Server/BaseServer";
|
||||||
hacking_skill: number;
|
import { ITerminal } from "../Terminal/ITerminal";
|
||||||
sourceFiles: any[];
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
}
|
|
||||||
|
|
||||||
export interface IProgramCreate {
|
export interface IProgramCreate {
|
||||||
level: number;
|
level: number;
|
||||||
@ -13,10 +12,16 @@ export interface IProgramCreate {
|
|||||||
export class Program {
|
export class Program {
|
||||||
name = "";
|
name = "";
|
||||||
create: IProgramCreate | null;
|
create: IProgramCreate | null;
|
||||||
|
run: (terminal: ITerminal, player: IPlayer, server: BaseServer, args: string[]) => void;
|
||||||
|
|
||||||
constructor(name: string, create: IProgramCreate | null) {
|
constructor(
|
||||||
|
name: string,
|
||||||
|
create: IProgramCreate | null,
|
||||||
|
run: (terminal: ITerminal, player: IPlayer, server: BaseServer, args: string[]) => void,
|
||||||
|
) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.create = create;
|
this.create = create;
|
||||||
|
this.run = run;
|
||||||
}
|
}
|
||||||
|
|
||||||
htmlID(): string {
|
htmlID(): string {
|
||||||
|
@ -5,5 +5,5 @@ import { IMap } from "../types";
|
|||||||
export const Programs: IMap<Program> = {};
|
export const Programs: IMap<Program> = {};
|
||||||
|
|
||||||
for (const params of programsMetadata) {
|
for (const params of programsMetadata) {
|
||||||
Programs[params.key] = new Program(params.name, params.create);
|
Programs[params.key] = new Program(params.name, params.create, params.run);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,18 @@
|
|||||||
import { IPlayer, IProgramCreate } from "../Program";
|
import { IProgramCreate } from "../Program";
|
||||||
import { CONSTANTS } from "../../Constants";
|
import { CONSTANTS } from "../../Constants";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { Server } from "../../Server/Server";
|
||||||
|
import { ITerminal } from "../../Terminal/ITerminal";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { HacknetServer } from "../../Hacknet/HacknetServer";
|
||||||
|
import { convertTimeMsToTimeElapsedString } from "../../../utils/StringHelperFunctions";
|
||||||
|
import { getServer } from "../../Server/ServerHelpers";
|
||||||
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||||
|
import { createPopup } from "../../ui/React/createPopup";
|
||||||
|
import { BitFlumePopup } from "../../BitNode/ui/BitFlumePopup";
|
||||||
|
|
||||||
|
import { calculateHackingTime, calculateGrowTime, calculateWeakenTime } from "../../Hacking";
|
||||||
|
|
||||||
function requireHackingLevel(lvl: number) {
|
function requireHackingLevel(lvl: number) {
|
||||||
return function (p: IPlayer) {
|
return function (p: IPlayer) {
|
||||||
@ -17,6 +30,7 @@ export interface IProgramCreationParams {
|
|||||||
key: string;
|
key: string;
|
||||||
name: string;
|
name: string;
|
||||||
create: IProgramCreate | null;
|
create: IProgramCreate | null;
|
||||||
|
run: (terminal: ITerminal, player: IPlayer, server: BaseServer, args: string[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const programsMetadata: IProgramCreationParams[] = [
|
export const programsMetadata: IProgramCreationParams[] = [
|
||||||
@ -29,6 +43,25 @@ export const programsMetadata: IProgramCreationParams[] = [
|
|||||||
req: requireHackingLevel(1),
|
req: requireHackingLevel(1),
|
||||||
time: CONSTANTS.MillisecondsPerFiveMinutes,
|
time: CONSTANTS.MillisecondsPerFiveMinutes,
|
||||||
},
|
},
|
||||||
|
run: (terminal: ITerminal, player: IPlayer, server: BaseServer): void => {
|
||||||
|
if (!(server instanceof Server)) {
|
||||||
|
terminal.error("Cannot nuke this kind of server.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (server.hasAdminRights) {
|
||||||
|
terminal.print("You already have root access to this computer. There is no reason to run NUKE.exe");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server.openPortCount >= player.getCurrentServer().numOpenPortsRequired) {
|
||||||
|
server.hasAdminRights = true;
|
||||||
|
terminal.print("NUKE successful! Gained root access to " + player.getCurrentServer().hostname);
|
||||||
|
// TODO: Make this take time rather than be instant
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal.print("NUKE unsuccessful. Not enough ports have been opened");
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "BruteSSHProgram",
|
key: "BruteSSHProgram",
|
||||||
@ -39,6 +72,20 @@ export const programsMetadata: IProgramCreationParams[] = [
|
|||||||
req: requireHackingLevel(50),
|
req: requireHackingLevel(50),
|
||||||
time: CONSTANTS.MillisecondsPerFiveMinutes * 2,
|
time: CONSTANTS.MillisecondsPerFiveMinutes * 2,
|
||||||
},
|
},
|
||||||
|
run: (terminal: ITerminal, player: IPlayer, server: BaseServer): void => {
|
||||||
|
if (!(server instanceof Server)) {
|
||||||
|
terminal.error("Cannot run BruteSSH.exe on this kind of server.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (server.sshPortOpen) {
|
||||||
|
terminal.print("SSH Port (22) is already open!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
server.sshPortOpen = true;
|
||||||
|
terminal.print("Opened SSH Port(22)!");
|
||||||
|
server.openPortCount++;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "FTPCrackProgram",
|
key: "FTPCrackProgram",
|
||||||
@ -49,6 +96,20 @@ export const programsMetadata: IProgramCreationParams[] = [
|
|||||||
req: requireHackingLevel(100),
|
req: requireHackingLevel(100),
|
||||||
time: CONSTANTS.MillisecondsPerHalfHour,
|
time: CONSTANTS.MillisecondsPerHalfHour,
|
||||||
},
|
},
|
||||||
|
run: (terminal: ITerminal, player: IPlayer, server: BaseServer): void => {
|
||||||
|
if (!(server instanceof Server)) {
|
||||||
|
terminal.error("Cannot run FTPCrack.exe on this kind of server.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (server.ftpPortOpen) {
|
||||||
|
terminal.print("FTP Port (21) is already open!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
server.ftpPortOpen = true;
|
||||||
|
terminal.print("Opened FTP Port (21)!");
|
||||||
|
server.openPortCount++;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "RelaySMTPProgram",
|
key: "RelaySMTPProgram",
|
||||||
@ -59,6 +120,20 @@ export const programsMetadata: IProgramCreationParams[] = [
|
|||||||
req: requireHackingLevel(250),
|
req: requireHackingLevel(250),
|
||||||
time: CONSTANTS.MillisecondsPer2Hours,
|
time: CONSTANTS.MillisecondsPer2Hours,
|
||||||
},
|
},
|
||||||
|
run: (terminal: ITerminal, player: IPlayer, server: BaseServer): void => {
|
||||||
|
if (!(server instanceof Server)) {
|
||||||
|
terminal.error("Cannot run relaySMTP.exe on this kind of server.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (server.smtpPortOpen) {
|
||||||
|
terminal.print("SMTP Port (25) is already open!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
server.smtpPortOpen = true;
|
||||||
|
terminal.print("Opened SMTP Port (25)!");
|
||||||
|
server.openPortCount++;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "HTTPWormProgram",
|
key: "HTTPWormProgram",
|
||||||
@ -69,6 +144,20 @@ export const programsMetadata: IProgramCreationParams[] = [
|
|||||||
req: requireHackingLevel(500),
|
req: requireHackingLevel(500),
|
||||||
time: CONSTANTS.MillisecondsPer4Hours,
|
time: CONSTANTS.MillisecondsPer4Hours,
|
||||||
},
|
},
|
||||||
|
run: (terminal: ITerminal, player: IPlayer, server: BaseServer): void => {
|
||||||
|
if (!(server instanceof Server)) {
|
||||||
|
terminal.error("Cannot run HTTPWorm.exe on this kind of server.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (server.httpPortOpen) {
|
||||||
|
terminal.print("HTTP Port (80) is already open!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
server.httpPortOpen = true;
|
||||||
|
terminal.print("Opened HTTP Port (80)!");
|
||||||
|
server.openPortCount++;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "SQLInjectProgram",
|
key: "SQLInjectProgram",
|
||||||
@ -79,6 +168,20 @@ export const programsMetadata: IProgramCreationParams[] = [
|
|||||||
req: requireHackingLevel(750),
|
req: requireHackingLevel(750),
|
||||||
time: CONSTANTS.MillisecondsPer8Hours,
|
time: CONSTANTS.MillisecondsPer8Hours,
|
||||||
},
|
},
|
||||||
|
run: (terminal: ITerminal, player: IPlayer, server: BaseServer): void => {
|
||||||
|
if (!(server instanceof Server)) {
|
||||||
|
terminal.error("Cannot run SQLInject.exe on this kind of server.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (server.sqlPortOpen) {
|
||||||
|
terminal.print("SQL Port (1433) is already open!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
server.sqlPortOpen = true;
|
||||||
|
terminal.print("Opened SQL Port (1433)!");
|
||||||
|
server.openPortCount++;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "DeepscanV1",
|
key: "DeepscanV1",
|
||||||
@ -89,6 +192,10 @@ export const programsMetadata: IProgramCreationParams[] = [
|
|||||||
req: requireHackingLevel(75),
|
req: requireHackingLevel(75),
|
||||||
time: CONSTANTS.MillisecondsPerQuarterHour,
|
time: CONSTANTS.MillisecondsPerQuarterHour,
|
||||||
},
|
},
|
||||||
|
run: (terminal: ITerminal): void => {
|
||||||
|
terminal.print("This executable cannot be run.");
|
||||||
|
terminal.print("DeepscanV1.exe lets you run 'scan-analyze' with a depth up to 5.");
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "DeepscanV2",
|
key: "DeepscanV2",
|
||||||
@ -99,6 +206,10 @@ export const programsMetadata: IProgramCreationParams[] = [
|
|||||||
req: requireHackingLevel(400),
|
req: requireHackingLevel(400),
|
||||||
time: CONSTANTS.MillisecondsPer2Hours,
|
time: CONSTANTS.MillisecondsPer2Hours,
|
||||||
},
|
},
|
||||||
|
run: (terminal: ITerminal): void => {
|
||||||
|
terminal.print("This executable cannot be run.");
|
||||||
|
terminal.print("DeepscanV2.exe lets you run 'scan-analyze' with a depth up to 10.");
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "ServerProfiler",
|
key: "ServerProfiler",
|
||||||
@ -109,6 +220,46 @@ export const programsMetadata: IProgramCreationParams[] = [
|
|||||||
req: requireHackingLevel(75),
|
req: requireHackingLevel(75),
|
||||||
time: CONSTANTS.MillisecondsPerHalfHour,
|
time: CONSTANTS.MillisecondsPerHalfHour,
|
||||||
},
|
},
|
||||||
|
run: (terminal: ITerminal, player: IPlayer, server: BaseServer, args: string[]): void => {
|
||||||
|
if (args.length !== 1) {
|
||||||
|
terminal.print("Must pass a server hostname or IP as an argument for ServerProfiler.exe");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetServer = getServer(args[0]);
|
||||||
|
if (targetServer == null) {
|
||||||
|
terminal.print("Invalid server IP/hostname");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetServer instanceof HacknetServer) {
|
||||||
|
terminal.print(`ServerProfiler.exe cannot be run on a Hacknet Server.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal.print(targetServer.hostname + ":");
|
||||||
|
terminal.print("Server base security level: " + targetServer.baseDifficulty);
|
||||||
|
terminal.print("Server current security level: " + targetServer.hackDifficulty);
|
||||||
|
terminal.print("Server growth rate: " + targetServer.serverGrowth);
|
||||||
|
terminal.print(
|
||||||
|
`Netscript hack() execution time: ${convertTimeMsToTimeElapsedString(
|
||||||
|
calculateHackingTime(targetServer, player) * 1000,
|
||||||
|
true,
|
||||||
|
)}`,
|
||||||
|
);
|
||||||
|
terminal.print(
|
||||||
|
`Netscript grow() execution time: ${convertTimeMsToTimeElapsedString(
|
||||||
|
calculateGrowTime(targetServer, player) * 1000,
|
||||||
|
true,
|
||||||
|
)}`,
|
||||||
|
);
|
||||||
|
terminal.print(
|
||||||
|
`Netscript weaken() execution time: ${convertTimeMsToTimeElapsedString(
|
||||||
|
calculateWeakenTime(targetServer, player) * 1000,
|
||||||
|
true,
|
||||||
|
)}`,
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "AutoLink",
|
key: "AutoLink",
|
||||||
@ -119,6 +270,11 @@ export const programsMetadata: IProgramCreationParams[] = [
|
|||||||
req: requireHackingLevel(25),
|
req: requireHackingLevel(25),
|
||||||
time: CONSTANTS.MillisecondsPerQuarterHour,
|
time: CONSTANTS.MillisecondsPerQuarterHour,
|
||||||
},
|
},
|
||||||
|
run: (terminal: ITerminal): void => {
|
||||||
|
terminal.print("This executable cannot be run.");
|
||||||
|
terminal.print("AutoLink.exe lets you automatically connect to other servers when using 'scan-analyze'.");
|
||||||
|
terminal.print("When using scan-analyze, click on a server's hostname to connect to it.");
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "BitFlume",
|
key: "BitFlume",
|
||||||
@ -129,10 +285,31 @@ export const programsMetadata: IProgramCreationParams[] = [
|
|||||||
req: bitFlumeRequirements(),
|
req: bitFlumeRequirements(),
|
||||||
time: CONSTANTS.MillisecondsPerFiveMinutes / 20,
|
time: CONSTANTS.MillisecondsPerFiveMinutes / 20,
|
||||||
},
|
},
|
||||||
|
run: (terminal: ITerminal, player: IPlayer): void => {
|
||||||
|
const popupId = "bitflume-popup";
|
||||||
|
createPopup(popupId, BitFlumePopup, {
|
||||||
|
player: player,
|
||||||
|
popupId: popupId,
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "Flight",
|
key: "Flight",
|
||||||
name: "fl1ght.exe",
|
name: "fl1ght.exe",
|
||||||
create: null,
|
create: null,
|
||||||
|
run: (terminal: ITerminal, player: IPlayer): void => {
|
||||||
|
const numAugReq = Math.round(BitNodeMultipliers.DaedalusAugsRequirement * 30);
|
||||||
|
const fulfilled =
|
||||||
|
player.augmentations.length >= numAugReq && player.money.gt(1e11) && player.hacking_skill >= 2500;
|
||||||
|
if (!fulfilled) {
|
||||||
|
terminal.print(`Augmentations: ${player.augmentations.length} / ${numAugReq}`);
|
||||||
|
terminal.print(`Money: ${numeralWrapper.formatMoney(player.money.toNumber())} / $100b`);
|
||||||
|
terminal.print(`Hacking skill: ${player.hacking_skill} / 2500`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal.print("We will contact you.");
|
||||||
|
terminal.print("-- Daedalus --");
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
6
src/Script/ScriptHelpers.d.ts
vendored
Normal file
6
src/Script/ScriptHelpers.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export declare function findRunningScript(
|
||||||
|
filename: string,
|
||||||
|
args: (string | number)[],
|
||||||
|
server: BaseServer,
|
||||||
|
): RunningScript | null;
|
||||||
|
export declare function findRunningScriptByPid(pid: number, server: BaseServer): RunningScript | null;
|
@ -1,5 +1,6 @@
|
|||||||
import { AllServers, createUniqueRandomIp, ipExists } from "./AllServers";
|
import { AllServers, createUniqueRandomIp, ipExists } from "./AllServers";
|
||||||
import { Server, IConstructorParams } from "./Server";
|
import { Server, IConstructorParams } from "./Server";
|
||||||
|
import { BaseServer } from "./BaseServer";
|
||||||
import { calculateServerGrowth } from "./formulas/grow";
|
import { calculateServerGrowth } from "./formulas/grow";
|
||||||
|
|
||||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
@ -141,7 +142,7 @@ export function getServer(s: string): Server | HacknetServer | null {
|
|||||||
// Returns the i-th server on the specified server's network
|
// Returns the i-th server on the specified server's network
|
||||||
// A Server's serverOnNetwork property holds only the IPs. This function returns
|
// A Server's serverOnNetwork property holds only the IPs. This function returns
|
||||||
// the actual Server object
|
// the actual Server object
|
||||||
export function getServerOnNetwork(server: Server, i: number): Server | HacknetServer | null {
|
export function getServerOnNetwork(server: BaseServer, i: number): Server | HacknetServer | null {
|
||||||
if (i > server.serversOnNetwork.length) {
|
if (i > server.serversOnNetwork.length) {
|
||||||
console.error("Tried to get server on network that was out of range");
|
console.error("Tried to get server on network that was out of range");
|
||||||
return null;
|
return null;
|
||||||
|
@ -1,20 +1,16 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { createStyles, makeStyles, useTheme, Theme } from "@material-ui/core/styles";
|
import { createStyles, makeStyles, Theme } from "@material-ui/core/styles";
|
||||||
import Drawer from "@material-ui/core/Drawer";
|
import Drawer from "@material-ui/core/Drawer";
|
||||||
import List from "@material-ui/core/List";
|
import List from "@material-ui/core/List";
|
||||||
import Divider from "@material-ui/core/Divider";
|
import Divider from "@material-ui/core/Divider";
|
||||||
import IconButton from "@material-ui/core/IconButton";
|
|
||||||
import ChevronLeftIcon from "@material-ui/icons/ChevronLeft";
|
import ChevronLeftIcon from "@material-ui/icons/ChevronLeft";
|
||||||
import ChevronRightIcon from "@material-ui/icons/ChevronRight";
|
import ChevronRightIcon from "@material-ui/icons/ChevronRight";
|
||||||
import ListItem from "@material-ui/core/ListItem";
|
import ListItem from "@material-ui/core/ListItem";
|
||||||
import ListSubheader from "@material-ui/core/ListSubheader";
|
|
||||||
import ListItemIcon from "@material-ui/core/ListItemIcon";
|
import ListItemIcon from "@material-ui/core/ListItemIcon";
|
||||||
import ListItemText from "@material-ui/core/ListItemText";
|
import ListItemText from "@material-ui/core/ListItemText";
|
||||||
import Typography from "@material-ui/core/Typography";
|
import Typography from "@material-ui/core/Typography";
|
||||||
import Collapse from "@material-ui/core/Collapse";
|
import Collapse from "@material-ui/core/Collapse";
|
||||||
import InboxIcon from "@material-ui/icons/MoveToInbox";
|
|
||||||
import MailIcon from "@material-ui/icons/Mail";
|
|
||||||
|
|
||||||
import { Theme as BBTheme, colors } from "../../ui/React/Theme";
|
import { Theme as BBTheme, colors } from "../../ui/React/Theme";
|
||||||
|
|
||||||
@ -341,7 +337,7 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const [open, setOpen] = useState(true);
|
const [open, setOpen] = useState(true);
|
||||||
const toggleDrawer = () => setOpen((old) => !old);
|
const toggleDrawer = (): void => setOpen((old) => !old);
|
||||||
return (
|
return (
|
||||||
<BBTheme>
|
<BBTheme>
|
||||||
<Drawer
|
<Drawer
|
||||||
|
1
src/Terminal.d.ts
vendored
Normal file
1
src/Terminal.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export declare const Terminal: any;
|
2198
src/Terminal.jsx
2198
src/Terminal.jsx
File diff suppressed because it is too large
Load Diff
30
src/Terminal/ITerminal.ts
Normal file
30
src/Terminal/ITerminal.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { TextFile } from "../TextFile";
|
||||||
|
import { Script } from "../Script/Script";
|
||||||
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
|
import { IEngine } from "../IEngine";
|
||||||
|
|
||||||
|
export interface ITerminal {
|
||||||
|
print(s: string, config?: any): void;
|
||||||
|
error(s: string): void;
|
||||||
|
|
||||||
|
startAnalyze(): void;
|
||||||
|
startBackdoor(player: IPlayer): void;
|
||||||
|
startHack(player: IPlayer): void;
|
||||||
|
finishHack(player: IPlayer, cancelled?: boolean): void;
|
||||||
|
finishBackdoor(player: IPlayer, cancelled?: boolean): void;
|
||||||
|
finishAnalyze(player: IPlayer, cancelled?: boolean): void;
|
||||||
|
finishAction(player: IPlayer, cancelled?: boolean): void;
|
||||||
|
getFilepath(filename: string): string;
|
||||||
|
getFile(player: IPlayer, filename: string): Script | TextFile | string | null;
|
||||||
|
getScript(player: IPlayer, filename: string): Script | null;
|
||||||
|
getTextFile(player: IPlayer, filename: string): TextFile | null;
|
||||||
|
getLitFile(player: IPlayer, filename: string): string | null;
|
||||||
|
resetTerminalInput(): void;
|
||||||
|
cwd(): string;
|
||||||
|
setcwd(dir: string): void;
|
||||||
|
runContract(player: IPlayer, name: string): void;
|
||||||
|
executeScanAnalyzeCommand(player: IPlayer, depth?: number, all?: boolean): void;
|
||||||
|
connectToServer(player: IPlayer, server: string): void;
|
||||||
|
executeCommand(engine: IEngine, player: IPlayer, command: string): void;
|
||||||
|
executeCommands(engine: IEngine, player: IPlayer, commands: string): void;
|
||||||
|
}
|
127
src/Terminal/Parser.ts
Normal file
127
src/Terminal/Parser.ts
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
import { substituteAliases } from "../Alias";
|
||||||
|
// Helper function that checks if an argument (which is a string) is a valid number
|
||||||
|
function isNumber(str: string): boolean {
|
||||||
|
if (typeof str != "string") {
|
||||||
|
return false;
|
||||||
|
} // Only process strings
|
||||||
|
return !isNaN(parseFloat(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ParseCommands(commands: string): string[] {
|
||||||
|
// Sanitize input
|
||||||
|
commands = commands.trim();
|
||||||
|
// Replace all extra whitespace in command with a single space
|
||||||
|
commands = commands.replace(/\s\s+/g, " ");
|
||||||
|
|
||||||
|
const match = commands.match(/(?:'[^']*'|"[^"]*"|[^;"])*/g);
|
||||||
|
if (!match) return [];
|
||||||
|
// Split commands and execute sequentially
|
||||||
|
const allCommands = match
|
||||||
|
.map(substituteAliases)
|
||||||
|
.map((c) => c.match(/(?:'[^']*'|"[^"]*"|[^;"])*/g))
|
||||||
|
.flat();
|
||||||
|
|
||||||
|
const out: string[] = [];
|
||||||
|
for (const c of allCommands) {
|
||||||
|
if (c === null) continue;
|
||||||
|
if (c.match(/^\s*$/)) {
|
||||||
|
continue;
|
||||||
|
} // Don't run commands that only have whitespace
|
||||||
|
out.push(c.trim());
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ParseCommand(command: string): (string | number)[] {
|
||||||
|
// This will be used to keep track of whether we're in a quote. This is for situations
|
||||||
|
// like the alias command:
|
||||||
|
// alias run="run NUKE.exe"
|
||||||
|
// We want the run="run NUKE.exe" to be parsed as a single command, so this flag
|
||||||
|
// will keep track of whether we have a quote in
|
||||||
|
let inQuote = ``;
|
||||||
|
|
||||||
|
// Returns an array with the command and its arguments in each index
|
||||||
|
// Properly handles quotation marks (e.g. `run foo.script "the sun"` will return [run, foo.script, the sun])
|
||||||
|
const args = [];
|
||||||
|
let start = 0,
|
||||||
|
i = 0;
|
||||||
|
let prevChar = ""; // Previous character
|
||||||
|
while (i < command.length) {
|
||||||
|
let escaped = false; // Check for escaped quotation marks
|
||||||
|
if (i >= 1) {
|
||||||
|
prevChar = command.charAt(i - 1);
|
||||||
|
if (prevChar === "\\") {
|
||||||
|
escaped = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const c = command.charAt(i);
|
||||||
|
if (c === '"') {
|
||||||
|
// Double quotes
|
||||||
|
if (!escaped && prevChar === " ") {
|
||||||
|
const endQuote = command.indexOf('"', i + 1);
|
||||||
|
if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === " ")) {
|
||||||
|
args.push(command.substr(i + 1, endQuote - i - 1));
|
||||||
|
if (endQuote === command.length - 1) {
|
||||||
|
start = i = endQuote + 1;
|
||||||
|
} else {
|
||||||
|
start = i = endQuote + 2; // Skip the space
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (inQuote === ``) {
|
||||||
|
inQuote = `"`;
|
||||||
|
} else if (inQuote === `"`) {
|
||||||
|
inQuote = ``;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (c === "'") {
|
||||||
|
// Single quotes, same thing as above
|
||||||
|
if (!escaped && prevChar === " ") {
|
||||||
|
const endQuote = command.indexOf("'", i + 1);
|
||||||
|
if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === " ")) {
|
||||||
|
args.push(command.substr(i + 1, endQuote - i - 1));
|
||||||
|
if (endQuote === command.length - 1) {
|
||||||
|
start = i = endQuote + 1;
|
||||||
|
} else {
|
||||||
|
start = i = endQuote + 2; // Skip the space
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (inQuote === ``) {
|
||||||
|
inQuote = `'`;
|
||||||
|
} else if (inQuote === `'`) {
|
||||||
|
inQuote = ``;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (c === " " && inQuote === ``) {
|
||||||
|
const arg = command.substr(start, i - start);
|
||||||
|
|
||||||
|
// If this is a number, convert it from a string to number
|
||||||
|
if (isNumber(arg)) {
|
||||||
|
args.push(parseFloat(arg));
|
||||||
|
} else {
|
||||||
|
args.push(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
start = i + 1;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the last argument
|
||||||
|
if (start !== i) {
|
||||||
|
const arg = command.substr(start, i - start);
|
||||||
|
|
||||||
|
// If this is a number, convert it from string to number
|
||||||
|
if (isNumber(arg)) {
|
||||||
|
args.push(parseFloat(arg));
|
||||||
|
} else {
|
||||||
|
args.push(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
692
src/Terminal/Terminal.ts
Normal file
692
src/Terminal/Terminal.ts
Normal file
@ -0,0 +1,692 @@
|
|||||||
|
import { postContent, hackProgressBarPost, hackProgressPost } from "../ui/postToTerminal";
|
||||||
|
import { ITerminal } from "./ITerminal";
|
||||||
|
import { IEngine } from "../IEngine";
|
||||||
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
|
import { HacknetServer } from "../Hacknet/HacknetServer";
|
||||||
|
import { BaseServer } from "../Server/BaseServer";
|
||||||
|
import { hackWorldDaemon } from "../RedPill";
|
||||||
|
import { Programs } from "../Programs/Programs";
|
||||||
|
import { CodingContractResult } from "../CodingContracts";
|
||||||
|
|
||||||
|
import { Terminal as OldTerminal } from "../Terminal";
|
||||||
|
import { TextFile } from "../TextFile";
|
||||||
|
import { Script } from "../Script/Script";
|
||||||
|
import { isScriptFilename } from "../Script/ScriptHelpersTS";
|
||||||
|
import { CONSTANTS } from "../Constants";
|
||||||
|
import { AllServers } from "../Server/AllServers";
|
||||||
|
|
||||||
|
import { removeLeadingSlash, isInRootDirectory, evaluateFilePath } from "./DirectoryHelpers";
|
||||||
|
import { checkIfConnectedToDarkweb } from "../DarkWeb/DarkWeb";
|
||||||
|
import { logBoxCreate } from "../../utils/LogBox";
|
||||||
|
import { iTutorialNextStep, iTutorialSteps, ITutorial } from "../InteractiveTutorial";
|
||||||
|
import { findRunningScript } from "../Script/ScriptHelpers";
|
||||||
|
import { TerminalHelpText } from "./HelpText";
|
||||||
|
import { GetServerByHostname, getServer, getServerOnNetwork } from "../Server/ServerHelpers";
|
||||||
|
import { ParseCommand, ParseCommands } from "./Parser";
|
||||||
|
import { SpecialServerIps, SpecialServerNames } from "../Server/SpecialServerIps";
|
||||||
|
import {
|
||||||
|
calculateHackingChance,
|
||||||
|
calculateHackingExpGain,
|
||||||
|
calculatePercentMoneyHacked,
|
||||||
|
calculateHackingTime,
|
||||||
|
} from "../Hacking";
|
||||||
|
import { numeralWrapper } from "../ui/numeralFormat";
|
||||||
|
import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
|
||||||
|
|
||||||
|
import { alias } from "./commands/alias";
|
||||||
|
import { analyze } from "./commands/analyze";
|
||||||
|
import { backdoor } from "./commands/backdoor";
|
||||||
|
import { buy } from "./commands/buy";
|
||||||
|
import { cat } from "./commands/cat";
|
||||||
|
import { cd } from "./commands/cd";
|
||||||
|
import { check } from "./commands/check";
|
||||||
|
import { connect } from "./commands/connect";
|
||||||
|
import { download } from "./commands/download";
|
||||||
|
import { expr } from "./commands/expr";
|
||||||
|
import { free } from "./commands/free";
|
||||||
|
import { hack } from "./commands/hack";
|
||||||
|
import { help } from "./commands/help";
|
||||||
|
import { home } from "./commands/home";
|
||||||
|
import { hostname } from "./commands/hostname";
|
||||||
|
import { ifconfig } from "./commands/ifconfig";
|
||||||
|
import { kill } from "./commands/kill";
|
||||||
|
import { killall } from "./commands/killall";
|
||||||
|
import { ls } from "./commands/ls";
|
||||||
|
import { lscpu } from "./commands/lscpu";
|
||||||
|
import { mem } from "./commands/mem";
|
||||||
|
import { mv } from "./commands/mv";
|
||||||
|
import { nano } from "./commands/nano";
|
||||||
|
import { ps } from "./commands/ps";
|
||||||
|
import { rm } from "./commands/rm";
|
||||||
|
import { run } from "./commands/run";
|
||||||
|
import { scan } from "./commands/scan";
|
||||||
|
import { scananalyze } from "./commands/scananalyze";
|
||||||
|
import { scp } from "./commands/scp";
|
||||||
|
import { sudov } from "./commands/sudov";
|
||||||
|
import { tail } from "./commands/tail";
|
||||||
|
import { theme } from "./commands/theme";
|
||||||
|
import { top } from "./commands/top";
|
||||||
|
import { unalias } from "./commands/unalias";
|
||||||
|
import { wget } from "./commands/wget";
|
||||||
|
import { clear } from "./commands/clear";
|
||||||
|
|
||||||
|
export class Terminal implements ITerminal {
|
||||||
|
print(s: string, config?: any): void {
|
||||||
|
postContent(s, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
error(s: string): void {
|
||||||
|
postContent(`ERROR: ${s}`, { color: "#ff2929" });
|
||||||
|
}
|
||||||
|
|
||||||
|
startHack(player: IPlayer): void {
|
||||||
|
OldTerminal.hackFlag = true;
|
||||||
|
|
||||||
|
// Hacking through Terminal should be faster than hacking through a script
|
||||||
|
OldTerminal.actionTime = calculateHackingTime(player.getCurrentServer(), player) / 4;
|
||||||
|
this.startAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
startBackdoor(player: IPlayer): void {
|
||||||
|
OldTerminal.backdoorFlag = true;
|
||||||
|
|
||||||
|
// Backdoor should take the same amount of time as hack
|
||||||
|
OldTerminal.actionTime = calculateHackingTime(player.getCurrentServer(), player) / 4;
|
||||||
|
this.startAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
startAnalyze(): void {
|
||||||
|
OldTerminal.analyzeFlag = true;
|
||||||
|
OldTerminal.actionTime = 1;
|
||||||
|
this.print("Analyzing system...");
|
||||||
|
this.startAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
startAction(): void {
|
||||||
|
OldTerminal.actionStarted = true;
|
||||||
|
|
||||||
|
hackProgressPost("Time left:");
|
||||||
|
hackProgressBarPost("[");
|
||||||
|
|
||||||
|
// Disable terminal
|
||||||
|
const elem = document.getElementById("terminal-input-td");
|
||||||
|
if (!elem) throw new Error("terminal-input-td should not be null");
|
||||||
|
elem.innerHTML = '<input type="text" class="terminal-input"/>';
|
||||||
|
$("input[class=terminal-input]").prop("disabled", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Complete the hack/analyze command
|
||||||
|
finishHack(player: IPlayer, cancelled = false): void {
|
||||||
|
if (!cancelled) {
|
||||||
|
const server = player.getCurrentServer();
|
||||||
|
|
||||||
|
// Calculate whether hack was successful
|
||||||
|
const hackChance = calculateHackingChance(server, player);
|
||||||
|
const rand = Math.random();
|
||||||
|
const expGainedOnSuccess = calculateHackingExpGain(server, player);
|
||||||
|
const expGainedOnFailure = expGainedOnSuccess / 4;
|
||||||
|
if (rand < hackChance) {
|
||||||
|
// Success!
|
||||||
|
if (
|
||||||
|
SpecialServerIps[SpecialServerNames.WorldDaemon] &&
|
||||||
|
SpecialServerIps[SpecialServerNames.WorldDaemon] == server.ip
|
||||||
|
) {
|
||||||
|
if (player.bitNodeN == null) {
|
||||||
|
player.bitNodeN = 1;
|
||||||
|
}
|
||||||
|
hackWorldDaemon(player.bitNodeN);
|
||||||
|
OldTerminal.hackFlag = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
server.backdoorInstalled = true;
|
||||||
|
let moneyGained = calculatePercentMoneyHacked(server, player);
|
||||||
|
moneyGained = Math.floor(server.moneyAvailable * moneyGained);
|
||||||
|
|
||||||
|
if (moneyGained <= 0) {
|
||||||
|
moneyGained = 0;
|
||||||
|
} // Safety check
|
||||||
|
|
||||||
|
server.moneyAvailable -= moneyGained;
|
||||||
|
player.gainMoney(moneyGained);
|
||||||
|
player.recordMoneySource(moneyGained, "hacking");
|
||||||
|
player.gainHackingExp(expGainedOnSuccess);
|
||||||
|
player.gainIntelligenceExp(expGainedOnSuccess / CONSTANTS.IntelligenceTerminalHackBaseExpGain);
|
||||||
|
|
||||||
|
server.fortify(CONSTANTS.ServerFortifyAmount);
|
||||||
|
|
||||||
|
this.print(
|
||||||
|
`Hack successful! Gained ${numeralWrapper.formatMoney(moneyGained)} and ${numeralWrapper.formatExp(
|
||||||
|
expGainedOnSuccess,
|
||||||
|
)} hacking exp`,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Failure
|
||||||
|
// player only gains 25% exp for failure? TODO Can change this later to balance
|
||||||
|
player.gainHackingExp(expGainedOnFailure);
|
||||||
|
this.print(
|
||||||
|
`Failed to hack ${server.hostname}. Gained ${numeralWrapper.formatExp(expGainedOnFailure)} hacking exp`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OldTerminal.hackFlag = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
finishBackdoor(player: IPlayer, cancelled = false): void {
|
||||||
|
if (!cancelled) {
|
||||||
|
const server = player.getCurrentServer();
|
||||||
|
if (
|
||||||
|
SpecialServerIps[SpecialServerNames.WorldDaemon] &&
|
||||||
|
SpecialServerIps[SpecialServerNames.WorldDaemon] == server.ip
|
||||||
|
) {
|
||||||
|
if (player.bitNodeN == null) {
|
||||||
|
player.bitNodeN = 1;
|
||||||
|
}
|
||||||
|
hackWorldDaemon(player.bitNodeN);
|
||||||
|
OldTerminal.backdoorFlag = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
server.backdoorInstalled = true;
|
||||||
|
this.print("Backdoor successful!");
|
||||||
|
}
|
||||||
|
OldTerminal.backdoorFlag = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
finishAnalyze(player: IPlayer, cancelled = false): void {
|
||||||
|
if (!cancelled) {
|
||||||
|
const currServ = player.getCurrentServer();
|
||||||
|
const isHacknet = currServ instanceof HacknetServer;
|
||||||
|
this.print(currServ.hostname + ": ");
|
||||||
|
const org = currServ.organizationName;
|
||||||
|
this.print("Organization name: " + (!isHacknet ? org : "player"));
|
||||||
|
const hasAdminRights = (!isHacknet && currServ.hasAdminRights) || isHacknet;
|
||||||
|
this.print("Root Access: " + (hasAdminRights ? "YES" : "NO"));
|
||||||
|
const hackingSkill = currServ.requiredHackingSkill;
|
||||||
|
this.print("Required hacking skill: " + (!isHacknet ? hackingSkill : "N/A"));
|
||||||
|
const security = currServ.hackDifficulty;
|
||||||
|
this.print("Server security level: " + (!isHacknet ? numeralWrapper.formatServerSecurity(security) : "N/A"));
|
||||||
|
const hackingChance = calculateHackingChance(currServ, player);
|
||||||
|
this.print("Chance to hack: " + (!isHacknet ? numeralWrapper.formatPercentage(hackingChance) : "N/A"));
|
||||||
|
const hackingTime = calculateHackingTime(currServ, player) * 1000;
|
||||||
|
this.print("Time to hack: " + (!isHacknet ? convertTimeMsToTimeElapsedString(hackingTime, true) : "N/A"));
|
||||||
|
this.print(
|
||||||
|
`Total money available on server: ${!isHacknet ? numeralWrapper.formatMoney(currServ.moneyAvailable) : "N/A"}`,
|
||||||
|
);
|
||||||
|
const numPort = currServ.numOpenPortsRequired;
|
||||||
|
this.print("Required number of open ports for NUKE: " + (!isHacknet ? numPort : "N/A"));
|
||||||
|
this.print("SSH port: " + (currServ.sshPortOpen ? "Open" : "Closed"));
|
||||||
|
this.print("FTP port: " + (currServ.ftpPortOpen ? "Open" : "Closed"));
|
||||||
|
this.print("SMTP port: " + (currServ.smtpPortOpen ? "Open" : "Closed"));
|
||||||
|
this.print("HTTP port: " + (currServ.httpPortOpen ? "Open" : "Closed"));
|
||||||
|
this.print("SQL port: " + (currServ.sqlPortOpen ? "Open" : "Closed"));
|
||||||
|
}
|
||||||
|
OldTerminal.analyzeFlag = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
finishAction(player: IPlayer, cancelled = false): void {
|
||||||
|
if (OldTerminal.hackFlag) {
|
||||||
|
this.finishHack(player, cancelled);
|
||||||
|
} else if (OldTerminal.backdoorFlag) {
|
||||||
|
this.finishBackdoor(player, cancelled);
|
||||||
|
} else if (OldTerminal.analyzeFlag) {
|
||||||
|
this.finishAnalyze(player, cancelled);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename the progress bar so that the next hacks dont trigger it. Re-enable terminal
|
||||||
|
$("#hack-progress-bar").attr("id", "old-hack-progress-bar");
|
||||||
|
$("#hack-progress").attr("id", "old-hack-progress");
|
||||||
|
OldTerminal.resetTerminalInput();
|
||||||
|
$("input[class=terminal-input]").prop("disabled", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
getFile(player: IPlayer, filename: string): Script | TextFile | string | null {
|
||||||
|
if (isScriptFilename(filename)) {
|
||||||
|
return this.getScript(player, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filename.endsWith(".lit")) {
|
||||||
|
return this.getLitFile(player, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filename.endsWith(".txt")) {
|
||||||
|
return this.getTextFile(player, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFilepath(filename: string): string {
|
||||||
|
const path = evaluateFilePath(filename, this.cwd());
|
||||||
|
if (path == null) {
|
||||||
|
throw new Error(`Invalid file path specified: ${filename}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInRootDirectory(path)) {
|
||||||
|
return removeLeadingSlash(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
getScript(player: IPlayer, filename: string): Script | null {
|
||||||
|
const s = player.getCurrentServer();
|
||||||
|
const filepath = this.getFilepath(filename);
|
||||||
|
for (const script of s.scripts) {
|
||||||
|
if (filepath === script.filename) {
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getTextFile(player: IPlayer, filename: string): TextFile | null {
|
||||||
|
const s = player.getCurrentServer();
|
||||||
|
const filepath = this.getFilepath(filename);
|
||||||
|
for (const txt of s.textFiles) {
|
||||||
|
if (filepath === txt.fn) {
|
||||||
|
return txt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getLitFile(player: IPlayer, filename: string): string | null {
|
||||||
|
const s = player.getCurrentServer();
|
||||||
|
const filepath = this.getFilepath(filename);
|
||||||
|
for (const lit of s.messages) {
|
||||||
|
if (typeof lit === "string" && filepath === lit) {
|
||||||
|
return lit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetTerminalInput(): void {
|
||||||
|
OldTerminal.resetTerminalInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
cwd(): string {
|
||||||
|
return OldTerminal.currDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
setcwd(dir: string): void {
|
||||||
|
OldTerminal.currDir = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
async runContract(player: IPlayer, contractName: string): Promise<void> {
|
||||||
|
// There's already an opened contract
|
||||||
|
if (OldTerminal.contractOpen) {
|
||||||
|
return this.error("There's already a Coding Contract in Progress");
|
||||||
|
}
|
||||||
|
|
||||||
|
const serv = player.getCurrentServer();
|
||||||
|
const contract = serv.getContract(contractName);
|
||||||
|
if (contract == null) {
|
||||||
|
return this.error("No such contract");
|
||||||
|
}
|
||||||
|
|
||||||
|
OldTerminal.contractOpen = true;
|
||||||
|
const res = await contract.prompt();
|
||||||
|
|
||||||
|
switch (res) {
|
||||||
|
case CodingContractResult.Success:
|
||||||
|
if (contract.reward !== null) {
|
||||||
|
const reward = player.gainCodingContractReward(contract.reward, contract.getDifficulty());
|
||||||
|
this.print(`Contract SUCCESS - ${reward}`);
|
||||||
|
}
|
||||||
|
serv.removeContract(contract);
|
||||||
|
break;
|
||||||
|
case CodingContractResult.Failure:
|
||||||
|
++contract.tries;
|
||||||
|
if (contract.tries >= contract.getMaxNumTries()) {
|
||||||
|
this.print("Contract <p style='color:red;display:inline'>FAILED</p> - Contract is now self-destructing");
|
||||||
|
serv.removeContract(contract);
|
||||||
|
} else {
|
||||||
|
this.print(
|
||||||
|
`Contract <p style='color:red;display:inline'>FAILED</p> - ${
|
||||||
|
contract.getMaxNumTries() - contract.tries
|
||||||
|
} tries remaining`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CodingContractResult.Cancelled:
|
||||||
|
default:
|
||||||
|
this.print("Contract cancelled");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
OldTerminal.contractOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
executeScanAnalyzeCommand(player: IPlayer, depth = 1, all = false): void {
|
||||||
|
// TODO Using array as stack for now, can make more efficient
|
||||||
|
this.print("~~~~~~~~~~ Beginning scan-analyze ~~~~~~~~~~");
|
||||||
|
this.print(" ");
|
||||||
|
|
||||||
|
// Map of all servers to keep track of which have been visited
|
||||||
|
const visited: {
|
||||||
|
[key: string]: number | undefined;
|
||||||
|
} = {};
|
||||||
|
for (const ip in AllServers) {
|
||||||
|
visited[ip] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stack: BaseServer[] = [];
|
||||||
|
const depthQueue: number[] = [0];
|
||||||
|
const currServ = player.getCurrentServer();
|
||||||
|
stack.push(currServ);
|
||||||
|
while (stack.length != 0) {
|
||||||
|
const s = stack.pop();
|
||||||
|
if (!s) continue;
|
||||||
|
const d = depthQueue.pop();
|
||||||
|
if (d === undefined) continue;
|
||||||
|
const isHacknet = s instanceof HacknetServer;
|
||||||
|
if (!all && (s as any).purchasedByPlayer && s.hostname != "home") {
|
||||||
|
continue; // Purchased server
|
||||||
|
} else if (visited[s.ip] || d > depth) {
|
||||||
|
continue; // Already visited or out-of-depth
|
||||||
|
} else if (!all && isHacknet) {
|
||||||
|
continue; // Hacknet Server
|
||||||
|
} else {
|
||||||
|
visited[s.ip] = 1;
|
||||||
|
}
|
||||||
|
for (let i = s.serversOnNetwork.length - 1; i >= 0; --i) {
|
||||||
|
const newS = getServerOnNetwork(s, i);
|
||||||
|
if (newS === null) continue;
|
||||||
|
stack.push(newS);
|
||||||
|
depthQueue.push(d + 1);
|
||||||
|
}
|
||||||
|
if (d == 0) {
|
||||||
|
continue;
|
||||||
|
} // Don't print current server
|
||||||
|
const titleDashes = Array((d - 1) * 4 + 1).join("-");
|
||||||
|
if (player.hasProgram(Programs.AutoLink.name)) {
|
||||||
|
this.print("<strong>" + titleDashes + "> <a class='scan-analyze-link'>" + s.hostname + "</a></strong>", false);
|
||||||
|
} else {
|
||||||
|
this.print("<strong>" + titleDashes + ">" + s.hostname + "</strong>");
|
||||||
|
}
|
||||||
|
|
||||||
|
const dashes = titleDashes + "--";
|
||||||
|
let c = "NO";
|
||||||
|
if (s.hasAdminRights) {
|
||||||
|
c = "YES";
|
||||||
|
}
|
||||||
|
this.print(
|
||||||
|
`${dashes}Root Access: ${c}${!isHacknet ? ", Required hacking skill: " + (s as any).requiredHackingSkill : ""}`,
|
||||||
|
);
|
||||||
|
if (s.hasOwnProperty("numOpenPortsRequired")) {
|
||||||
|
this.print(dashes + "Number of open ports required to NUKE: " + (s as any).numOpenPortsRequired);
|
||||||
|
}
|
||||||
|
this.print(dashes + "RAM: " + numeralWrapper.formatRAM(s.maxRam));
|
||||||
|
this.print(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
const links = document.getElementsByClassName("scan-analyze-link");
|
||||||
|
for (let i = 0; i < links.length; ++i) {
|
||||||
|
(() => {
|
||||||
|
const hostname = links[i].innerHTML.toString();
|
||||||
|
links[i].addEventListener("onclick", () => {
|
||||||
|
if (OldTerminal.analyzeFlag || OldTerminal.hackFlag || OldTerminal.backdoorFlag) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.connectToServer(player, hostname);
|
||||||
|
});
|
||||||
|
})(); // Immediate invocation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connectToServer(player: IPlayer, server: string): void {
|
||||||
|
const serv = getServer(server);
|
||||||
|
if (serv == null) {
|
||||||
|
this.error("Invalid server. Connection failed.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
player.getCurrentServer().isConnectedTo = false;
|
||||||
|
player.currentServer = serv.ip;
|
||||||
|
player.getCurrentServer().isConnectedTo = true;
|
||||||
|
this.print("Connected to " + serv.hostname);
|
||||||
|
this.setcwd("/");
|
||||||
|
if (player.getCurrentServer().hostname == "darkweb") {
|
||||||
|
checkIfConnectedToDarkweb(); // Posts a 'help' message if connecting to dark web
|
||||||
|
}
|
||||||
|
this.resetTerminalInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
executeCommands(engine: IEngine, player: IPlayer, commands: string): void {
|
||||||
|
// Sanitize input
|
||||||
|
commands = commands.trim();
|
||||||
|
commands = commands.replace(/\s\s+/g, " "); // Replace all extra whitespace in command with a single space
|
||||||
|
|
||||||
|
// Handle Terminal History - multiple commands should be saved as one
|
||||||
|
if (OldTerminal.commandHistory[OldTerminal.commandHistory.length - 1] != commands) {
|
||||||
|
OldTerminal.commandHistory.push(commands);
|
||||||
|
if (OldTerminal.commandHistory.length > 50) {
|
||||||
|
OldTerminal.commandHistory.splice(0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OldTerminal.commandHistoryIndex = OldTerminal.commandHistory.length;
|
||||||
|
const allCommands = ParseCommands(commands);
|
||||||
|
|
||||||
|
for (let i = 0; i < allCommands.length; i++) {
|
||||||
|
this.executeCommand(engine, player, allCommands[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
executeCommand(engine: IEngine, player: IPlayer, command: string): void {
|
||||||
|
if (OldTerminal.hackFlag || OldTerminal.backdoorFlag || OldTerminal.analyzeFlag) {
|
||||||
|
this.error(`Cannot execute command (${command}) while an action is in progress`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Allow usage of ./
|
||||||
|
if (command.startsWith("./")) {
|
||||||
|
command = "run " + command.slice(2);
|
||||||
|
}
|
||||||
|
// Only split the first space
|
||||||
|
const commandArray = ParseCommand(command);
|
||||||
|
if (commandArray.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const s = player.getCurrentServer();
|
||||||
|
/****************** Interactive Tutorial Terminal Commands ******************/
|
||||||
|
if (ITutorial.isRunning) {
|
||||||
|
const n00dlesServ = GetServerByHostname("n00dles");
|
||||||
|
if (n00dlesServ == null) {
|
||||||
|
throw new Error("Could not get n00dles server");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (ITutorial.currStep) {
|
||||||
|
case iTutorialSteps.TerminalHelp:
|
||||||
|
if (commandArray.length === 1 && commandArray[0] == "help") {
|
||||||
|
this.print(TerminalHelpText);
|
||||||
|
iTutorialNextStep();
|
||||||
|
} else {
|
||||||
|
this.print("Bad command. Please follow the tutorial");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case iTutorialSteps.TerminalLs:
|
||||||
|
if (commandArray.length === 1 && commandArray[0] == "ls") {
|
||||||
|
ls(this, engine, player, s, commandArray.slice(1));
|
||||||
|
iTutorialNextStep();
|
||||||
|
} else {
|
||||||
|
this.print("Bad command. Please follow the tutorial");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case iTutorialSteps.TerminalScan:
|
||||||
|
if (commandArray.length === 1 && commandArray[0] == "scan") {
|
||||||
|
scan(this, engine, player, s, commandArray.slice(1));
|
||||||
|
iTutorialNextStep();
|
||||||
|
} else {
|
||||||
|
this.print("Bad command. Please follow the tutorial");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case iTutorialSteps.TerminalScanAnalyze1:
|
||||||
|
if (commandArray.length == 1 && commandArray[0] == "scan-analyze") {
|
||||||
|
this.executeScanAnalyzeCommand(player, 1);
|
||||||
|
iTutorialNextStep();
|
||||||
|
} else {
|
||||||
|
this.print("Bad command. Please follow the tutorial");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case iTutorialSteps.TerminalScanAnalyze2:
|
||||||
|
if (commandArray.length == 2 && commandArray[0] == "scan-analyze" && commandArray[1] === 2) {
|
||||||
|
this.executeScanAnalyzeCommand(player, 2);
|
||||||
|
iTutorialNextStep();
|
||||||
|
} else {
|
||||||
|
this.print("Bad command. Please follow the tutorial");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case iTutorialSteps.TerminalConnect:
|
||||||
|
if (commandArray.length == 2) {
|
||||||
|
if (commandArray[0] == "connect" && (commandArray[1] == "n00dles" || commandArray[1] == n00dlesServ.ip)) {
|
||||||
|
player.getCurrentServer().isConnectedTo = false;
|
||||||
|
player.currentServer = n00dlesServ.ip;
|
||||||
|
player.getCurrentServer().isConnectedTo = true;
|
||||||
|
this.print("Connected to n00dles");
|
||||||
|
iTutorialNextStep();
|
||||||
|
} else {
|
||||||
|
this.print("Wrong command! Try again!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.print("Bad command. Please follow the tutorial");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case iTutorialSteps.TerminalAnalyze:
|
||||||
|
if (commandArray.length === 1 && commandArray[0] === "analyze") {
|
||||||
|
if (commandArray.length !== 1) {
|
||||||
|
this.print("Incorrect usage of analyze command. Usage: analyze");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.startAnalyze();
|
||||||
|
iTutorialNextStep();
|
||||||
|
} else {
|
||||||
|
this.print("Bad command. Please follow the tutorial");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case iTutorialSteps.TerminalNuke:
|
||||||
|
if (commandArray.length == 2 && commandArray[0] == "run" && commandArray[1] == "NUKE.exe") {
|
||||||
|
n00dlesServ.hasAdminRights = true;
|
||||||
|
this.print("NUKE successful! Gained root access to n00dles");
|
||||||
|
iTutorialNextStep();
|
||||||
|
} else {
|
||||||
|
this.print("Bad command. Please follow the tutorial");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case iTutorialSteps.TerminalManualHack:
|
||||||
|
if (commandArray.length == 1 && commandArray[0] == "hack") {
|
||||||
|
this.startHack(player);
|
||||||
|
iTutorialNextStep();
|
||||||
|
} else {
|
||||||
|
this.print("Bad command. Please follow the tutorial");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case iTutorialSteps.TerminalCreateScript:
|
||||||
|
if (commandArray.length == 2 && commandArray[0] == "nano" && commandArray[1] == "n00dles.script") {
|
||||||
|
engine.loadScriptEditorContent("n00dles.script", "");
|
||||||
|
iTutorialNextStep();
|
||||||
|
} else {
|
||||||
|
this.print("Bad command. Please follow the tutorial");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case iTutorialSteps.TerminalFree:
|
||||||
|
if (commandArray.length == 1 && commandArray[0] == "free") {
|
||||||
|
free(this, engine, player, s, commandArray.slice(1));
|
||||||
|
iTutorialNextStep();
|
||||||
|
} else {
|
||||||
|
this.print("Bad command. Please follow the tutorial");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case iTutorialSteps.TerminalRunScript:
|
||||||
|
if (commandArray.length == 2 && commandArray[0] == "run" && commandArray[1] == "n00dles.script") {
|
||||||
|
run(this, engine, player, s, commandArray.slice(1));
|
||||||
|
iTutorialNextStep();
|
||||||
|
} else {
|
||||||
|
this.print("Bad command. Please follow the tutorial");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case iTutorialSteps.ActiveScriptsToTerminal:
|
||||||
|
if (commandArray.length == 2 && commandArray[0] == "tail" && commandArray[1] == "n00dles.script") {
|
||||||
|
// Check that the script exists on this machine
|
||||||
|
const runningScript = findRunningScript("n00dles.script", [], player.getCurrentServer());
|
||||||
|
if (runningScript == null) {
|
||||||
|
this.print("Error: No such script exists");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logBoxCreate(runningScript);
|
||||||
|
iTutorialNextStep();
|
||||||
|
} else {
|
||||||
|
this.print("Bad command. Please follow the tutorial");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.print("Please follow the tutorial, or click 'Exit Tutorial' if you'd like to skip it");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/****************** END INTERACTIVE TUTORIAL ******************/
|
||||||
|
/* Command parser */
|
||||||
|
const commandName = commandArray[0];
|
||||||
|
if (typeof commandName === "number") {
|
||||||
|
this.error(`Command ${commandArray[0]} not found`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const commands: {
|
||||||
|
[key: string]: (
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
) => void;
|
||||||
|
} = {
|
||||||
|
alias: alias,
|
||||||
|
analyze: analyze,
|
||||||
|
backdoor: backdoor,
|
||||||
|
buy: buy,
|
||||||
|
cat: cat,
|
||||||
|
cd: cd,
|
||||||
|
check: check,
|
||||||
|
cls: clear,
|
||||||
|
clear: clear,
|
||||||
|
connect: connect,
|
||||||
|
download: download,
|
||||||
|
expr: expr,
|
||||||
|
free: free,
|
||||||
|
hack: hack,
|
||||||
|
help: help,
|
||||||
|
home: home,
|
||||||
|
hostname: hostname,
|
||||||
|
ifconfig: ifconfig,
|
||||||
|
kill: kill,
|
||||||
|
killall: killall,
|
||||||
|
ls: ls,
|
||||||
|
lscpu: lscpu,
|
||||||
|
mem: mem,
|
||||||
|
mv: mv,
|
||||||
|
nano: nano,
|
||||||
|
ps: ps,
|
||||||
|
rm: rm,
|
||||||
|
run: run,
|
||||||
|
scan: scan,
|
||||||
|
"scan-analyze": scananalyze,
|
||||||
|
scp: scp,
|
||||||
|
sudov: sudov,
|
||||||
|
tail: tail,
|
||||||
|
theme: theme,
|
||||||
|
top: top,
|
||||||
|
unalias: unalias,
|
||||||
|
wget: wget,
|
||||||
|
};
|
||||||
|
|
||||||
|
const f = commands[commandName.toLowerCase()];
|
||||||
|
if (!f) {
|
||||||
|
this.error(`Command ${commandArray[0]} not found`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
f(this, engine, player, s, commandArray.slice(1));
|
||||||
|
}
|
||||||
|
}
|
33
src/Terminal/commands/alias.ts
Normal file
33
src/Terminal/commands/alias.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { parseAliasDeclaration, printAliases } from "../../Alias";
|
||||||
|
|
||||||
|
export function alias(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length === 0) {
|
||||||
|
printAliases();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (args.length === 1) {
|
||||||
|
if (parseAliasDeclaration(args[0] + "")) {
|
||||||
|
terminal.print(`Set alias ${args[0]}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (args.length === 2) {
|
||||||
|
if (args[0] === "-g") {
|
||||||
|
if (parseAliasDeclaration(args[1] + "", true)) {
|
||||||
|
terminal.print(`Set global alias ${args[1]}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
terminal.error('Incorrect usage of alias command. Usage: alias [-g] [aliasname="value"]');
|
||||||
|
}
|
18
src/Terminal/commands/analyze.ts
Normal file
18
src/Terminal/commands/analyze.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
|
||||||
|
export function analyze(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 0) {
|
||||||
|
terminal.print("Incorrect usage of analyze command. Usage: analyze");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
terminal.startAnalyze();
|
||||||
|
}
|
41
src/Terminal/commands/backdoor.ts
Normal file
41
src/Terminal/commands/backdoor.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { Server } from "../../Server/Server";
|
||||||
|
import { HacknetServer } from "../../Hacknet/HacknetServer";
|
||||||
|
|
||||||
|
export function backdoor(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 0) {
|
||||||
|
terminal.print("Incorrect usage of backdoor command. Usage: backdoor");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(server instanceof Server)) {
|
||||||
|
terminal.error("Can only backdoor normal servers");
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalServer = server as Server;
|
||||||
|
|
||||||
|
if (normalServer.purchasedByPlayer) {
|
||||||
|
terminal.error(
|
||||||
|
"Cannot use backdoor on your own machines! You are currently connected to your home PC or one of your purchased servers",
|
||||||
|
);
|
||||||
|
} else if (!normalServer.hasAdminRights) {
|
||||||
|
terminal.error("You do not have admin rights for this machine! Cannot backdoor");
|
||||||
|
} else if (normalServer.requiredHackingSkill > player.hacking_skill) {
|
||||||
|
terminal.error(
|
||||||
|
"Your hacking skill is not high enough to use backdoor on this machine. Try analyzing the machine to determine the required hacking skill",
|
||||||
|
);
|
||||||
|
} else if (normalServer instanceof HacknetServer) {
|
||||||
|
terminal.error("Cannot use backdoor on this type of Server");
|
||||||
|
} else {
|
||||||
|
terminal.startBackdoor(player);
|
||||||
|
}
|
||||||
|
}
|
33
src/Terminal/commands/buy.ts
Normal file
33
src/Terminal/commands/buy.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { listAllDarkwebItems, buyDarkwebItem } from "../../DarkWeb/DarkWeb";
|
||||||
|
import { SpecialServerIps } from "../../Server/SpecialServerIps";
|
||||||
|
|
||||||
|
export function buy(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (!SpecialServerIps.hasOwnProperty("Darkweb Server")) {
|
||||||
|
terminal.error(
|
||||||
|
"You need to be able to connect to the Dark Web to use the buy command. (Maybe there's a TOR router you can buy somewhere)",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (args.length != 1) {
|
||||||
|
terminal.print("Incorrect number of arguments. Usage: ");
|
||||||
|
terminal.print("buy -l");
|
||||||
|
terminal.print("buy [item name]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const arg = args[0] + "";
|
||||||
|
if (arg == "-l" || arg == "-1" || arg == "--list") {
|
||||||
|
listAllDarkwebItems();
|
||||||
|
} else {
|
||||||
|
buyDarkwebItem(arg);
|
||||||
|
}
|
||||||
|
}
|
53
src/Terminal/commands/cat.ts
Normal file
53
src/Terminal/commands/cat.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { showMessage } from "../../Message/MessageHelpers";
|
||||||
|
import { Message } from "../../Message/Message";
|
||||||
|
import { showLiterature } from "../../Literature/LiteratureHelpers";
|
||||||
|
|
||||||
|
export function cat(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 1) {
|
||||||
|
terminal.error("Incorrect usage of cat command. Usage: cat [file]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const filename = terminal.getFilepath(args[0] + "");
|
||||||
|
if (!filename.endsWith(".msg") && !filename.endsWith(".lit") && !filename.endsWith(".txt")) {
|
||||||
|
terminal.error(
|
||||||
|
"Only .msg, .txt, and .lit files are viewable with cat (filename must end with .msg, .txt, or .lit)",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filename.endsWith(".msg") || filename.endsWith(".lit")) {
|
||||||
|
for (let i = 0; i < server.messages.length; ++i) {
|
||||||
|
if (filename.endsWith(".lit") && server.messages[i] === filename) {
|
||||||
|
const file = server.messages[i];
|
||||||
|
if (file instanceof Message) throw new Error(".lit file should not be a .msg");
|
||||||
|
showLiterature(file);
|
||||||
|
return;
|
||||||
|
} else if (filename.endsWith(".msg")) {
|
||||||
|
const file = server.messages[i];
|
||||||
|
if (typeof file === "string") throw new Error(".msg file should not be a .lit");
|
||||||
|
if (file.filename === filename) {
|
||||||
|
showMessage(file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (filename.endsWith(".txt")) {
|
||||||
|
const txt = terminal.getTextFile(player, filename);
|
||||||
|
if (txt != null) {
|
||||||
|
txt.show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal.error(`No such file ${filename}`);
|
||||||
|
}
|
48
src/Terminal/commands/cd.ts
Normal file
48
src/Terminal/commands/cd.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
|
||||||
|
import { evaluateDirectoryPath, removeTrailingSlash } from "../DirectoryHelpers";
|
||||||
|
|
||||||
|
export function cd(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length > 1) {
|
||||||
|
terminal.error("Incorrect number of arguments. Usage: cd [dir]");
|
||||||
|
} else {
|
||||||
|
let dir = args.length === 1 ? args[0] + "" : "/";
|
||||||
|
|
||||||
|
let evaledDir: string | null = "";
|
||||||
|
if (dir === "/") {
|
||||||
|
evaledDir = "/";
|
||||||
|
} else {
|
||||||
|
// Ignore trailing slashes
|
||||||
|
dir = removeTrailingSlash(dir);
|
||||||
|
|
||||||
|
evaledDir = evaluateDirectoryPath(dir, terminal.cwd());
|
||||||
|
if (evaledDir === null || evaledDir === "") {
|
||||||
|
terminal.error("Invalid path. Failed to change directories");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const server = player.getCurrentServer();
|
||||||
|
if (
|
||||||
|
!server.scripts.some((script) => script.filename.startsWith(evaledDir + "")) &&
|
||||||
|
!server.textFiles.some((file) => file.fn.startsWith(evaledDir + ""))
|
||||||
|
) {
|
||||||
|
terminal.error("Invalid path. Failed to change directories");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal.setcwd(evaledDir);
|
||||||
|
|
||||||
|
// Reset input to update current directory on UI
|
||||||
|
terminal.resetTerminalInput();
|
||||||
|
}
|
||||||
|
}
|
33
src/Terminal/commands/check.ts
Normal file
33
src/Terminal/commands/check.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { findRunningScript } from "../../Script/ScriptHelpers";
|
||||||
|
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
||||||
|
|
||||||
|
export function check(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length < 1) {
|
||||||
|
terminal.error("Incorrect number of arguments. Usage: check [script] [arg1] [arg2]...");
|
||||||
|
} else {
|
||||||
|
const scriptName = terminal.getFilepath(args[0] + "");
|
||||||
|
// Can only tail script files
|
||||||
|
if (!isScriptFilename(scriptName)) {
|
||||||
|
terminal.error("tail can only be called on .script files (filename must end with .script)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the script exists on this machine
|
||||||
|
const runningScript = findRunningScript(scriptName, args.slice(1), server);
|
||||||
|
if (runningScript == null) {
|
||||||
|
terminal.error("No such script exists");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
runningScript.displayLog();
|
||||||
|
}
|
||||||
|
}
|
18
src/Terminal/commands/clear.ts
Normal file
18
src/Terminal/commands/clear.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
|
||||||
|
export function clear(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 0) {
|
||||||
|
terminal.error("Incorrect usage of clear/cls command. Usage: clear/cls");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$("#terminal tr:not(:last)").remove();
|
||||||
|
}
|
32
src/Terminal/commands/connect.ts
Normal file
32
src/Terminal/commands/connect.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { getServerOnNetwork } from "../../Server/ServerHelpers";
|
||||||
|
|
||||||
|
export function connect(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
// Disconnect from current server in terminal and connect to new one
|
||||||
|
if (args.length !== 1) {
|
||||||
|
terminal.error("Incorrect usage of connect command. Usage: connect [ip/hostname]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ip = args[0] + "";
|
||||||
|
|
||||||
|
for (let i = 0; i < server.serversOnNetwork.length; i++) {
|
||||||
|
const other = getServerOnNetwork(server, i);
|
||||||
|
if (other === null) throw new Error(`Server on network should not be null`);
|
||||||
|
if (other.ip == ip || other.hostname == ip) {
|
||||||
|
terminal.connectToServer(player, ip);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal.error("Host not found");
|
||||||
|
}
|
79
src/Terminal/commands/download.ts
Normal file
79
src/Terminal/commands/download.ts
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
||||||
|
import FileSaver from "file-saver";
|
||||||
|
import JSZip from "jszip";
|
||||||
|
|
||||||
|
export function download(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
try {
|
||||||
|
if (args.length !== 1) {
|
||||||
|
terminal.error("Incorrect usage of download command. Usage: download [script/text file]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const fn = args[0] + "";
|
||||||
|
if (fn === "*" || fn === "*.script" || fn === "*.txt") {
|
||||||
|
// Download all scripts as a zip
|
||||||
|
const zip = new JSZip();
|
||||||
|
if (fn === "*" || fn === "*.script") {
|
||||||
|
for (let i = 0; i < server.scripts.length; ++i) {
|
||||||
|
const file = new Blob([server.scripts[i].code], {
|
||||||
|
type: "text/plain",
|
||||||
|
});
|
||||||
|
zip.file(server.scripts[i].filename + ".js", file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fn === "*" || fn === "*.txt") {
|
||||||
|
for (let i = 0; i < server.textFiles.length; ++i) {
|
||||||
|
const file = new Blob([server.textFiles[i].text], {
|
||||||
|
type: "text/plain",
|
||||||
|
});
|
||||||
|
zip.file(server.textFiles[i].fn, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let zipFn = "";
|
||||||
|
switch (fn) {
|
||||||
|
case "*.script":
|
||||||
|
zipFn = "bitburnerScripts.zip";
|
||||||
|
break;
|
||||||
|
case "*.txt":
|
||||||
|
zipFn = "bitburnerTexts.zip";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
zipFn = "bitburnerFiles.zip";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
zip.generateAsync({ type: "blob" }).then((content: any) => FileSaver.saveAs(content, zipFn));
|
||||||
|
return;
|
||||||
|
} else if (isScriptFilename(fn)) {
|
||||||
|
// Download a single script
|
||||||
|
const script = terminal.getScript(player, fn);
|
||||||
|
if (script != null) {
|
||||||
|
return script.download();
|
||||||
|
}
|
||||||
|
} else if (fn.endsWith(".txt")) {
|
||||||
|
// Download a single text file
|
||||||
|
const txt = terminal.getTextFile(player, fn);
|
||||||
|
if (txt != null) {
|
||||||
|
return txt.download();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
terminal.error(`Cannot download this filetype`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
terminal.error(`${fn} does not exist`);
|
||||||
|
return;
|
||||||
|
} catch (e) {
|
||||||
|
terminal.error(e + "");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
29
src/Terminal/commands/expr.ts
Normal file
29
src/Terminal/commands/expr.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
|
||||||
|
export function expr(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length === 0) {
|
||||||
|
terminal.error("Incorrect usage of expr command. Usage: expr [math expression]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const expr = args.join("");
|
||||||
|
|
||||||
|
// Sanitize the math expression
|
||||||
|
const sanitizedExpr = expr.replace(/s+/g, "").replace(/[^-()\d/*+.]/g, "");
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
result = eval(sanitizedExpr);
|
||||||
|
} catch (e) {
|
||||||
|
terminal.error(`Could not evaluate expression: ${sanitizedExpr}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
terminal.print(result);
|
||||||
|
}
|
29
src/Terminal/commands/free.ts
Normal file
29
src/Terminal/commands/free.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
|
||||||
|
export function free(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 0) {
|
||||||
|
terminal.error("Incorrect usage of free command. Usage: free");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const ram = numeralWrapper.formatRAM(player.getCurrentServer().maxRam);
|
||||||
|
const used = numeralWrapper.formatRAM(player.getCurrentServer().ramUsed);
|
||||||
|
const avail = numeralWrapper.formatRAM(player.getCurrentServer().maxRam - player.getCurrentServer().ramUsed);
|
||||||
|
const maxLength = Math.max(ram.length, Math.max(used.length, avail.length));
|
||||||
|
const usedPercent = numeralWrapper.formatPercentage(
|
||||||
|
player.getCurrentServer().ramUsed / player.getCurrentServer().maxRam,
|
||||||
|
);
|
||||||
|
|
||||||
|
terminal.print(`Total: ${" ".repeat(maxLength - ram.length)}${ram}`);
|
||||||
|
terminal.print(`Used: ${" ".repeat(maxLength - used.length)}${used} (${usedPercent})`);
|
||||||
|
terminal.print(`Available: ${" ".repeat(maxLength - avail.length)}${avail}`);
|
||||||
|
}
|
44
src/Terminal/commands/hack.ts
Normal file
44
src/Terminal/commands/hack.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { Server } from "../../Server/Server";
|
||||||
|
|
||||||
|
export function hack(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 0) {
|
||||||
|
terminal.error("Incorrect usage of hack command. Usage: hack");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(server instanceof Server)) {
|
||||||
|
terminal.error(
|
||||||
|
"Cannot hack your own machines! You are currently connected to your home PC or one of your purchased servers",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const normalServer = server as Server;
|
||||||
|
// Hack the current PC (usually for money)
|
||||||
|
// You can't hack your home pc or servers you purchased
|
||||||
|
if (normalServer.purchasedByPlayer) {
|
||||||
|
terminal.error(
|
||||||
|
"Cannot hack your own machines! You are currently connected to your home PC or one of your purchased servers",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!normalServer.hasAdminRights) {
|
||||||
|
terminal.error("You do not have admin rights for this machine! Cannot hack");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (normalServer.requiredHackingSkill > player.hacking_skill) {
|
||||||
|
terminal.error(
|
||||||
|
"Your hacking skill is not high enough to attempt hacking this machine. Try analyzing the machine to determine the required hacking skill",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
terminal.startHack(player);
|
||||||
|
}
|
29
src/Terminal/commands/help.ts
Normal file
29
src/Terminal/commands/help.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { TerminalHelpText, HelpTexts } from "../HelpText";
|
||||||
|
|
||||||
|
export function help(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 0 && args.length !== 1) {
|
||||||
|
terminal.error("Incorrect usage of help command. Usage: help");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (args.length === 0) {
|
||||||
|
terminal.print(TerminalHelpText);
|
||||||
|
} else {
|
||||||
|
const cmd = args[0];
|
||||||
|
const txt = HelpTexts[cmd];
|
||||||
|
if (txt == null) {
|
||||||
|
terminal.error("No help topics match '" + cmd + "'");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
terminal.print(txt);
|
||||||
|
}
|
||||||
|
}
|
23
src/Terminal/commands/home.ts
Normal file
23
src/Terminal/commands/home.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
|
||||||
|
export function home(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 0) {
|
||||||
|
terminal.error("Incorrect usage of home command. Usage: home");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
player.getCurrentServer().isConnectedTo = false;
|
||||||
|
player.currentServer = player.getHomeComputer().ip;
|
||||||
|
player.getCurrentServer().isConnectedTo = true;
|
||||||
|
terminal.print("Connected to home");
|
||||||
|
terminal.setcwd("/");
|
||||||
|
terminal.resetTerminalInput();
|
||||||
|
}
|
18
src/Terminal/commands/hostname.ts
Normal file
18
src/Terminal/commands/hostname.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
|
||||||
|
export function hostname(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 0) {
|
||||||
|
terminal.error("Incorrect usage of hostname command. Usage: hostname");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
terminal.print(player.getCurrentServer().hostname);
|
||||||
|
}
|
18
src/Terminal/commands/ifconfig.ts
Normal file
18
src/Terminal/commands/ifconfig.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
|
||||||
|
export function ifconfig(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 0) {
|
||||||
|
terminal.error("Incorrect usage of ifconfig command. Usage: ifconfig");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
terminal.print(player.getCurrentServer().ip);
|
||||||
|
}
|
44
src/Terminal/commands/kill.ts
Normal file
44
src/Terminal/commands/kill.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { killWorkerScript } from "../../Netscript/killWorkerScript";
|
||||||
|
|
||||||
|
export function kill(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
try {
|
||||||
|
if (args.length < 1) {
|
||||||
|
terminal.error("Incorrect usage of kill command. Usage: kill [scriptname] [arg1] [arg2]...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kill by PID
|
||||||
|
if (typeof args[0] === "number") {
|
||||||
|
const pid = args[0];
|
||||||
|
const res = killWorkerScript(pid);
|
||||||
|
if (res) {
|
||||||
|
terminal.print(`Killing script with PID ${pid}`);
|
||||||
|
} else {
|
||||||
|
terminal.print(`Failed to kill script with PID ${pid}. No such script exists`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const scriptName = terminal.getFilepath(args[0]);
|
||||||
|
const runningScript = server.getRunningScript(scriptName, args.slice(1));
|
||||||
|
if (runningScript == null) {
|
||||||
|
terminal.error("No such script is running. Nothing to kill");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
killWorkerScript(runningScript, server.ip, false);
|
||||||
|
terminal.print(`Killing ${scriptName}`);
|
||||||
|
} catch (e) {
|
||||||
|
terminal.error(e + "");
|
||||||
|
}
|
||||||
|
}
|
14
src/Terminal/commands/killall.ts
Normal file
14
src/Terminal/commands/killall.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { killWorkerScript } from "../../Netscript/killWorkerScript";
|
||||||
|
import { WorkerScriptStartStopEventEmitter } from "../../Netscript/WorkerScriptStartStopEventEmitter";
|
||||||
|
|
||||||
|
export function killall(terminal: ITerminal, engine: IEngine, player: IPlayer, server: BaseServer): void {
|
||||||
|
for (let i = server.runningScripts.length - 1; i >= 0; --i) {
|
||||||
|
killWorkerScript(server.runningScripts[i], server.ip, false);
|
||||||
|
}
|
||||||
|
WorkerScriptStartStopEventEmitter.emitEvent();
|
||||||
|
terminal.print("Killing all running scripts");
|
||||||
|
}
|
149
src/Terminal/commands/ls.tsx
Normal file
149
src/Terminal/commands/ls.tsx
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { Message } from "../../Message/Message";
|
||||||
|
import { getFirstParentDirectory, isValidDirectoryPath, evaluateDirectoryPath } from "../../Terminal/DirectoryHelpers";
|
||||||
|
|
||||||
|
export function ls(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
const numArgs = args.length;
|
||||||
|
function incorrectUsage(): void {
|
||||||
|
terminal.error("Incorrect usage of ls command. Usage: ls [dir] [| grep pattern]");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numArgs > 5 || numArgs === 3) {
|
||||||
|
return incorrectUsage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grep
|
||||||
|
let filter = ""; // Grep
|
||||||
|
|
||||||
|
// Directory path
|
||||||
|
let prefix = terminal.cwd();
|
||||||
|
if (!prefix.endsWith("/")) {
|
||||||
|
prefix += "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are 4+ arguments, then the last 3 must be for grep
|
||||||
|
if (numArgs >= 4) {
|
||||||
|
if (args[numArgs - 1] !== "grep" || args[numArgs - 2] !== "|") {
|
||||||
|
return incorrectUsage();
|
||||||
|
}
|
||||||
|
filter = args[numArgs] + "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the second argument is not a pipe, then it must be for listing a directory
|
||||||
|
if (numArgs >= 2 && args[0] !== "|") {
|
||||||
|
const newPath = evaluateDirectoryPath(args[0] + "", terminal.cwd());
|
||||||
|
prefix = newPath ? newPath : "";
|
||||||
|
if (prefix != null) {
|
||||||
|
if (!prefix.endsWith("/")) {
|
||||||
|
prefix += "/";
|
||||||
|
}
|
||||||
|
if (!isValidDirectoryPath(prefix)) {
|
||||||
|
return incorrectUsage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Root directory, which is the same as no 'prefix' at all
|
||||||
|
if (prefix === "/") {
|
||||||
|
prefix = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display all programs and scripts
|
||||||
|
const allPrograms: string[] = [];
|
||||||
|
const allScripts: string[] = [];
|
||||||
|
const allTextFiles: string[] = [];
|
||||||
|
const allContracts: string[] = [];
|
||||||
|
const allMessages: string[] = [];
|
||||||
|
const folders: string[] = [];
|
||||||
|
|
||||||
|
function handleFn(fn: string, dest: string[]): void {
|
||||||
|
let parsedFn = fn;
|
||||||
|
if (prefix) {
|
||||||
|
if (!fn.startsWith(prefix)) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
parsedFn = fn.slice(prefix.length, fn.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter && !parsedFn.includes(filter)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the fn includes a forward slash, it must be in a subdirectory.
|
||||||
|
// Therefore, we only list the "first" directory in its path
|
||||||
|
if (parsedFn.includes("/")) {
|
||||||
|
const firstParentDir = getFirstParentDirectory(parsedFn);
|
||||||
|
if (filter && !firstParentDir.includes(filter)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!folders.includes(firstParentDir)) {
|
||||||
|
folders.push(firstParentDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest.push(parsedFn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all of the programs and scripts on the machine into one temporary array
|
||||||
|
const s = player.getCurrentServer();
|
||||||
|
for (const program of s.programs) handleFn(program, allPrograms);
|
||||||
|
for (const script of s.scripts) handleFn(script.filename, allScripts);
|
||||||
|
for (const txt of s.textFiles) handleFn(txt.fn, allTextFiles);
|
||||||
|
for (const contract of s.contracts) handleFn(contract.fn, allContracts);
|
||||||
|
for (const msgOrLit of s.messages)
|
||||||
|
msgOrLit instanceof Message ? handleFn(msgOrLit.filename, allMessages) : handleFn(msgOrLit, allMessages);
|
||||||
|
|
||||||
|
// Sort the files/folders alphabetically then print each
|
||||||
|
allPrograms.sort();
|
||||||
|
allScripts.sort();
|
||||||
|
allTextFiles.sort();
|
||||||
|
allContracts.sort();
|
||||||
|
allMessages.sort();
|
||||||
|
folders.sort();
|
||||||
|
|
||||||
|
function postSegments(segments: string[], config: any): void {
|
||||||
|
const maxLength = Math.max(...segments.map((s) => s.length)) + 1;
|
||||||
|
const filesPerRow = Math.floor(80 / maxLength);
|
||||||
|
for (let i = 0; i < segments.length; i++) {
|
||||||
|
let row = "";
|
||||||
|
for (let col = 0; col < filesPerRow; col++) {
|
||||||
|
if (!(i < segments.length)) break;
|
||||||
|
row += segments[i];
|
||||||
|
row += " ".repeat(maxLength * (col + 1) - row.length);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
i--;
|
||||||
|
terminal.print(row, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = { color: "#0000FF" };
|
||||||
|
const groups = [
|
||||||
|
{ segments: folders, config: config },
|
||||||
|
{ segments: allMessages },
|
||||||
|
{ segments: allTextFiles },
|
||||||
|
{ segments: allPrograms },
|
||||||
|
{ segments: allContracts },
|
||||||
|
{ segments: allScripts },
|
||||||
|
].filter((g) => g.segments.length > 0);
|
||||||
|
for (let i = 0; i < groups.length; i++) {
|
||||||
|
if (i !== 0) {
|
||||||
|
terminal.print("");
|
||||||
|
terminal.print("");
|
||||||
|
}
|
||||||
|
postSegments(groups[i].segments, groups[i].config);
|
||||||
|
}
|
||||||
|
}
|
7
src/Terminal/commands/lscpu.ts
Normal file
7
src/Terminal/commands/lscpu.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
|
||||||
|
export function lscpu(terminal: ITerminal, engine: IEngine, player: IPlayer): void {
|
||||||
|
terminal.print(player.getCurrentServer().cpuCores + " Core(s)");
|
||||||
|
}
|
44
src/Terminal/commands/mem.ts
Normal file
44
src/Terminal/commands/mem.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
|
||||||
|
export function mem(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
try {
|
||||||
|
if (args.length !== 1 && args.length !== 3) {
|
||||||
|
terminal.error("Incorrect usage of mem command. usage: mem [scriptname] [-t] [number threads]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const scriptName = args[0] + "";
|
||||||
|
let numThreads = 1;
|
||||||
|
if (args.length === 3 && args[1] === "-t") {
|
||||||
|
numThreads = Math.round(parseInt(args[2] + ""));
|
||||||
|
if (isNaN(numThreads) || numThreads < 1) {
|
||||||
|
terminal.error("Invalid number of threads specified. Number of threads must be greater than 1");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const script = terminal.getScript(player, scriptName);
|
||||||
|
if (script == null) {
|
||||||
|
terminal.error("No such script exists!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ramUsage = script.ramUsage * numThreads;
|
||||||
|
|
||||||
|
terminal.print(
|
||||||
|
`This script requires ${numeralWrapper.formatRAM(ramUsage)} of RAM to run for ${numThreads} thread(s)`,
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
terminal.error(e + "");
|
||||||
|
}
|
||||||
|
}
|
91
src/Terminal/commands/mv.ts
Normal file
91
src/Terminal/commands/mv.ts
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
||||||
|
import { TextFile } from "../../TextFile";
|
||||||
|
import { Script } from "../../Script/Script";
|
||||||
|
|
||||||
|
export function mv(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 2) {
|
||||||
|
terminal.error(`Incorrect number of arguments. Usage: mv [src] [dest]`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const source = args[0] + "";
|
||||||
|
const dest = args[1] + "";
|
||||||
|
|
||||||
|
if (!isScriptFilename(source) && !source.endsWith(".txt")) {
|
||||||
|
terminal.error(`'mv' can only be used on scripts and text files (.txt)`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const srcFile = terminal.getFile(player, source);
|
||||||
|
if (srcFile == null) {
|
||||||
|
terminal.error(`Source file ${source} does not exist`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sourcePath = terminal.getFilepath(source);
|
||||||
|
const destPath = terminal.getFilepath(dest);
|
||||||
|
|
||||||
|
const destFile = terminal.getFile(player, dest);
|
||||||
|
|
||||||
|
// 'mv' command only works on scripts and txt files.
|
||||||
|
// Also, you can't convert between different file types
|
||||||
|
if (isScriptFilename(source)) {
|
||||||
|
const script = srcFile as Script;
|
||||||
|
if (!isScriptFilename(dest)) {
|
||||||
|
terminal.error(`Source and destination files must have the same type`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command doesnt work if script is running
|
||||||
|
if (server.isRunning(sourcePath)) {
|
||||||
|
terminal.error(`Cannot use 'mv' on a script that is running`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destFile != null) {
|
||||||
|
// Already exists, will be overwritten, so we'll delete it
|
||||||
|
const status = server.removeFile(destPath);
|
||||||
|
if (!status.res) {
|
||||||
|
terminal.error(`Something went wrong...please contact game dev (probably a bug)`);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
terminal.print("Warning: The destination file was overwritten");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
script.filename = destPath;
|
||||||
|
} else if (srcFile instanceof TextFile) {
|
||||||
|
const textFile = srcFile as TextFile;
|
||||||
|
if (!dest.endsWith(".txt")) {
|
||||||
|
terminal.error(`Source and destination files must have the same type`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destFile != null) {
|
||||||
|
// Already exists, will be overwritten, so we'll delete it
|
||||||
|
const status = server.removeFile(destPath);
|
||||||
|
if (!status.res) {
|
||||||
|
terminal.error(`Something went wrong...please contact game dev (probably a bug)`);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
terminal.print("Warning: The destination file was overwritten");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
textFile.fn = destPath;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
terminal.error(e + "");
|
||||||
|
}
|
||||||
|
}
|
57
src/Terminal/commands/nano.ts
Normal file
57
src/Terminal/commands/nano.ts
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
||||||
|
import { createFconf } from "../../Fconf/Fconf";
|
||||||
|
|
||||||
|
export function nano(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 1) {
|
||||||
|
terminal.error("Incorrect usage of nano command. Usage: nano [scriptname]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const filename = args[0] + "";
|
||||||
|
if (filename === ".fconf") {
|
||||||
|
const text = createFconf();
|
||||||
|
engine.loadScriptEditorContent(filename, text);
|
||||||
|
return;
|
||||||
|
} else if (isScriptFilename(filename)) {
|
||||||
|
const filepath = terminal.getFilepath(filename);
|
||||||
|
const script = terminal.getScript(player, filename);
|
||||||
|
if (script == null) {
|
||||||
|
let code = "";
|
||||||
|
if (filename.endsWith(".ns") || filename.endsWith(".js")) {
|
||||||
|
code = `export async function main(ns) {
|
||||||
|
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
engine.loadScriptEditorContent(filepath, code);
|
||||||
|
} else {
|
||||||
|
engine.loadScriptEditorContent(filepath, script.code);
|
||||||
|
}
|
||||||
|
} else if (filename.endsWith(".txt")) {
|
||||||
|
const filepath = terminal.getFilepath(filename);
|
||||||
|
const txt = terminal.getTextFile(player, filename);
|
||||||
|
if (txt == null) {
|
||||||
|
engine.loadScriptEditorContent(filepath);
|
||||||
|
} else {
|
||||||
|
engine.loadScriptEditorContent(filepath, txt.text);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
terminal.error(
|
||||||
|
"Invalid file. Only scripts (.script, .ns, .js), text files (.txt), or .fconf can be edited with nano",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
terminal.error(e + "");
|
||||||
|
}
|
||||||
|
}
|
25
src/Terminal/commands/ps.ts
Normal file
25
src/Terminal/commands/ps.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
|
||||||
|
export function ps(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 0) {
|
||||||
|
terminal.error("Incorrect usage of ps command. Usage: ps");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < server.runningScripts.length; i++) {
|
||||||
|
const rsObj = server.runningScripts[i];
|
||||||
|
let res = `(PID - ${rsObj.pid}) ${rsObj.filename}`;
|
||||||
|
for (let j = 0; j < rsObj.args.length; ++j) {
|
||||||
|
res += " " + rsObj.args[j].toString();
|
||||||
|
}
|
||||||
|
terminal.print(res);
|
||||||
|
}
|
||||||
|
}
|
38
src/Terminal/commands/rm.ts
Normal file
38
src/Terminal/commands/rm.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { IReturnStatus } from "../../types";
|
||||||
|
|
||||||
|
export function rm(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 1) {
|
||||||
|
terminal.error("Incorrect number of arguments. Usage: rm [program/script]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check programs
|
||||||
|
let delTarget;
|
||||||
|
let status: IReturnStatus = {
|
||||||
|
res: true,
|
||||||
|
msg: "",
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
delTarget = terminal.getFilepath(args[0] + "");
|
||||||
|
status = server.removeFile(delTarget);
|
||||||
|
} catch (err) {
|
||||||
|
status = {
|
||||||
|
res: false,
|
||||||
|
msg: "No such file exists",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!status.res && status.msg) {
|
||||||
|
terminal.error(status.msg);
|
||||||
|
}
|
||||||
|
}
|
40
src/Terminal/commands/run.ts
Normal file
40
src/Terminal/commands/run.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
||||||
|
import { runScript } from "./runScript";
|
||||||
|
import { runProgram } from "./runProgram";
|
||||||
|
|
||||||
|
export function run(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
// Run a program or a script
|
||||||
|
if (args.length < 1) {
|
||||||
|
terminal.error("Incorrect number of arguments. Usage: run [program/script] [-t] [num threads] [arg1] [arg2]...");
|
||||||
|
} else {
|
||||||
|
const executableName = args[0] + "";
|
||||||
|
|
||||||
|
// Secret Music player!
|
||||||
|
// if (executableName === "musicplayer") {
|
||||||
|
// post(
|
||||||
|
// '<iframe src="https://open.spotify.com/embed/user/danielyxie/playlist/1ORnnL6YNvXOracUaUV2kh" width="300" height="380" frameborder="0" allowtransparency="true"></iframe>',
|
||||||
|
// false,
|
||||||
|
// );
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Check if its a script or just a program/executable
|
||||||
|
if (isScriptFilename(executableName)) {
|
||||||
|
runScript(terminal, engine, player, server, args);
|
||||||
|
} else if (executableName.endsWith(".cct")) {
|
||||||
|
terminal.runContract(player, executableName);
|
||||||
|
} else {
|
||||||
|
runProgram(terminal, engine, player, server, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
src/Terminal/commands/runProgram.ts
Normal file
44
src/Terminal/commands/runProgram.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { Programs } from "../../Programs/Programs";
|
||||||
|
|
||||||
|
export function runProgram(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if you have the program on your computer. If you do, execute it, otherwise
|
||||||
|
// display an error message
|
||||||
|
const programName = args[0] + "";
|
||||||
|
|
||||||
|
if (!player.hasProgram(programName)) {
|
||||||
|
terminal.error("No such executable on home computer (Only programs that exist on your home computer can be run)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.length < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const program of Object.values(Programs)) {
|
||||||
|
if (program.name === programName) {
|
||||||
|
program.run(
|
||||||
|
terminal,
|
||||||
|
player,
|
||||||
|
server,
|
||||||
|
args.slice(1).map((arg) => arg + ""),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal.print("Invalid executable. Cannot be run");
|
||||||
|
}
|
93
src/Terminal/commands/runScript.ts
Normal file
93
src/Terminal/commands/runScript.ts
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { logBoxCreate } from "../../../utils/LogBox";
|
||||||
|
import { startWorkerScript } from "../../NetscriptWorker";
|
||||||
|
import { RunningScript } from "../../Script/RunningScript";
|
||||||
|
import { findRunningScript } from "../../Script/ScriptHelpers";
|
||||||
|
import * as libarg from "arg";
|
||||||
|
|
||||||
|
export function runScript(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
commandArgs: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (commandArgs.length < 1) {
|
||||||
|
terminal.error(
|
||||||
|
`Bug encountered with Terminal.runScript(). Command array has a length of less than 1: ${commandArgs}`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const scriptName = terminal.getFilepath(commandArgs[0] + "");
|
||||||
|
|
||||||
|
const runArgs = { "--tail": Boolean, "-t": Number };
|
||||||
|
const flags = libarg(runArgs, {
|
||||||
|
permissive: true,
|
||||||
|
argv: commandArgs.slice(1),
|
||||||
|
});
|
||||||
|
const threadFlag = Math.round(parseFloat(flags["-t"]));
|
||||||
|
const tailFlag = flags["--tail"] === true;
|
||||||
|
if (flags["-t"] !== undefined && (threadFlag < 0 || isNaN(threadFlag))) {
|
||||||
|
terminal.error("Invalid number of threads specified. Number of threads must be greater than 0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const numThreads = !isNaN(threadFlag) && threadFlag > 0 ? threadFlag : 1;
|
||||||
|
const args = flags["_"];
|
||||||
|
|
||||||
|
// Check if this script is already running
|
||||||
|
if (findRunningScript(scriptName, args, server) != null) {
|
||||||
|
terminal.print("ERROR: This script is already running. Cannot run multiple instances");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the script exists and if it does run it
|
||||||
|
for (let i = 0; i < server.scripts.length; i++) {
|
||||||
|
if (server.scripts[i].filename !== scriptName) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Check for admin rights and that there is enough RAM availble to run
|
||||||
|
const script = server.scripts[i];
|
||||||
|
const ramUsage = script.ramUsage * numThreads;
|
||||||
|
const ramAvailable = server.maxRam - server.ramUsed;
|
||||||
|
|
||||||
|
if (!server.hasAdminRights) {
|
||||||
|
terminal.print("Need root access to run script");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ramUsage > ramAvailable) {
|
||||||
|
terminal.print(
|
||||||
|
"This machine does not have enough RAM to run this script with " +
|
||||||
|
numThreads +
|
||||||
|
" threads. Script requires " +
|
||||||
|
ramUsage +
|
||||||
|
"GB of RAM",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Able to run script
|
||||||
|
const runningScript = new RunningScript(script, args);
|
||||||
|
runningScript.threads = numThreads;
|
||||||
|
|
||||||
|
const success = startWorkerScript(runningScript, server);
|
||||||
|
if (!success) {
|
||||||
|
terminal.error(`Failed to start script`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal.print(
|
||||||
|
`Running script with ${numThreads} thread(s), pid ${runningScript.pid} and args: ${JSON.stringify(args)}.`,
|
||||||
|
);
|
||||||
|
if (tailFlag) {
|
||||||
|
logBoxCreate(runningScript);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal.print("ERROR: No such script");
|
||||||
|
}
|
46
src/Terminal/commands/scan.ts
Normal file
46
src/Terminal/commands/scan.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { getServerOnNetwork } from "../../Server/ServerHelpers";
|
||||||
|
|
||||||
|
export function scan(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 0) {
|
||||||
|
terminal.error("Incorrect usage of netstat/scan command. Usage: netstat/scan");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Displays available network connections using TCP
|
||||||
|
const currServ = player.getCurrentServer();
|
||||||
|
const servers = currServ.serversOnNetwork.map((_, i) => {
|
||||||
|
const server = getServerOnNetwork(currServ, i);
|
||||||
|
if (server === null) throw new Error("Server should not be null");
|
||||||
|
return {
|
||||||
|
hostname: server.hostname,
|
||||||
|
ip: server.ip,
|
||||||
|
hasRoot: server.hasAdminRights ? "Y" : "N",
|
||||||
|
};
|
||||||
|
});
|
||||||
|
servers.unshift({
|
||||||
|
hostname: "Hostname",
|
||||||
|
ip: "IP",
|
||||||
|
hasRoot: "Root Access",
|
||||||
|
});
|
||||||
|
const maxHostname = Math.max(...servers.map((s) => s.hostname.length));
|
||||||
|
const maxIP = Math.max(...servers.map((s) => s.ip.length));
|
||||||
|
for (const server of servers) {
|
||||||
|
if (!server) continue;
|
||||||
|
let entry = server.hostname;
|
||||||
|
entry += " ".repeat(maxHostname - server.hostname.length + 1);
|
||||||
|
entry += server.ip;
|
||||||
|
entry += " ".repeat(maxIP - server.ip.length + 1);
|
||||||
|
entry += server.hasRoot;
|
||||||
|
terminal.print(entry);
|
||||||
|
}
|
||||||
|
}
|
45
src/Terminal/commands/scananalyze.ts
Normal file
45
src/Terminal/commands/scananalyze.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { Programs } from "../../Programs/Programs";
|
||||||
|
|
||||||
|
export function scananalyze(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length === 0) {
|
||||||
|
terminal.executeScanAnalyzeCommand(player, 1);
|
||||||
|
} else {
|
||||||
|
// # of args must be 2 or 3
|
||||||
|
if (args.length > 2) {
|
||||||
|
terminal.error("Incorrect usage of scan-analyze command. usage: scan-analyze [depth]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let all = false;
|
||||||
|
if (args.length === 2 && args[1] === "-a") {
|
||||||
|
all = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const depth = parseInt(args[0] + "");
|
||||||
|
|
||||||
|
if (isNaN(depth) || depth < 0) {
|
||||||
|
terminal.error("Incorrect usage of scan-analyze command. depth argument must be positive numeric");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (depth > 3 && !player.hasProgram(Programs.DeepscanV1.name) && !player.hasProgram(Programs.DeepscanV2.name)) {
|
||||||
|
terminal.error("You cannot scan-analyze with that high of a depth. Maximum depth is 3");
|
||||||
|
return;
|
||||||
|
} else if (depth > 5 && !player.hasProgram(Programs.DeepscanV2.name)) {
|
||||||
|
terminal.error("You cannot scan-analyze with that high of a depth. Maximum depth is 5");
|
||||||
|
return;
|
||||||
|
} else if (depth > 10) {
|
||||||
|
terminal.error("You cannot scan-analyze with that high of a depth. Maximum depth is 10");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
terminal.executeScanAnalyzeCommand(player, depth, all);
|
||||||
|
}
|
||||||
|
}
|
112
src/Terminal/commands/scp.ts
Normal file
112
src/Terminal/commands/scp.ts
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { Message } from "../../Message/Message";
|
||||||
|
import { getServer } from "../../Server/ServerHelpers";
|
||||||
|
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
||||||
|
|
||||||
|
export function scp(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
try {
|
||||||
|
if (args.length !== 2) {
|
||||||
|
terminal.error("Incorrect usage of scp command. Usage: scp [file] [destination hostname/ip]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const scriptname = terminal.getFilepath(args[0] + "");
|
||||||
|
if (!scriptname.endsWith(".lit") && !isScriptFilename(scriptname) && !scriptname.endsWith(".txt")) {
|
||||||
|
terminal.error("scp only works for scripts, text files (.txt), and literature files (.lit)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const destServer = getServer(args[1] + "");
|
||||||
|
if (destServer == null) {
|
||||||
|
terminal.error(`Invalid destination. ${args[1]} not found`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scp for lit files
|
||||||
|
if (scriptname.endsWith(".lit")) {
|
||||||
|
let found = false;
|
||||||
|
for (let i = 0; i < server.messages.length; ++i) {
|
||||||
|
if (!(server.messages[i] instanceof Message) && server.messages[i] == scriptname) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
return terminal.error("No such file exists!");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < destServer.messages.length; ++i) {
|
||||||
|
if (destServer.messages[i] === scriptname) {
|
||||||
|
terminal.print(scriptname + " copied over to " + destServer.hostname);
|
||||||
|
return; // Already exists
|
||||||
|
}
|
||||||
|
}
|
||||||
|
destServer.messages.push(scriptname);
|
||||||
|
return terminal.print(scriptname + " copied over to " + destServer.hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scp for txt files
|
||||||
|
if (scriptname.endsWith(".txt")) {
|
||||||
|
let txtFile = null;
|
||||||
|
for (let i = 0; i < server.textFiles.length; ++i) {
|
||||||
|
if (server.textFiles[i].fn === scriptname) {
|
||||||
|
txtFile = server.textFiles[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (txtFile === null) {
|
||||||
|
return terminal.error("No such file exists!");
|
||||||
|
}
|
||||||
|
|
||||||
|
const tRes = destServer.writeToTextFile(txtFile.fn, txtFile.text);
|
||||||
|
if (!tRes.success) {
|
||||||
|
terminal.error("scp failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tRes.overwritten) {
|
||||||
|
terminal.print(`WARNING: ${scriptname} already exists on ${destServer.hostname} and will be overwriten`);
|
||||||
|
terminal.print(`${scriptname} overwritten on ${destServer.hostname}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
terminal.print(`${scriptname} copied over to ${destServer.hostname}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current script
|
||||||
|
let sourceScript = null;
|
||||||
|
for (let i = 0; i < server.scripts.length; ++i) {
|
||||||
|
if (scriptname == server.scripts[i].filename) {
|
||||||
|
sourceScript = server.scripts[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sourceScript == null) {
|
||||||
|
terminal.error("scp() failed. No such script exists");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sRes = destServer.writeToScriptFile(scriptname, sourceScript.code);
|
||||||
|
if (!sRes.success) {
|
||||||
|
terminal.error(`scp failed`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sRes.overwritten) {
|
||||||
|
terminal.print(`WARNING: ${scriptname} already exists on ${destServer.hostname} and will be overwritten`);
|
||||||
|
terminal.print(`${scriptname} overwritten on ${destServer.hostname}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
terminal.print(`${scriptname} copied over to ${destServer.hostname}`);
|
||||||
|
} catch (e) {
|
||||||
|
terminal.error(e + "");
|
||||||
|
}
|
||||||
|
}
|
23
src/Terminal/commands/sudov.ts
Normal file
23
src/Terminal/commands/sudov.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
|
||||||
|
export function sudov(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 0) {
|
||||||
|
terminal.error("Incorrect number of arguments. Usage: sudov");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server.hasAdminRights) {
|
||||||
|
terminal.print("You have ROOT access to this machine");
|
||||||
|
} else {
|
||||||
|
terminal.print("You do NOT have root access to this machine");
|
||||||
|
}
|
||||||
|
}
|
81
src/Terminal/commands/tail.ts
Normal file
81
src/Terminal/commands/tail.ts
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { logBoxCreate } from "../../../utils/LogBox";
|
||||||
|
import { findRunningScriptByPid } from "../../Script/ScriptHelpers";
|
||||||
|
import { compareArrays } from "../../../utils/helpers/compareArrays";
|
||||||
|
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
||||||
|
|
||||||
|
export function tail(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
commandArray: (string | number)[],
|
||||||
|
): void {
|
||||||
|
try {
|
||||||
|
if (commandArray.length < 1) {
|
||||||
|
terminal.error("Incorrect number of arguments. Usage: tail [script] [arg1] [arg2]...");
|
||||||
|
} else if (typeof commandArray[0] === "string") {
|
||||||
|
const scriptName = terminal.getFilepath(commandArray[0]);
|
||||||
|
if (!isScriptFilename(scriptName)) {
|
||||||
|
terminal.error("tail can only be called on .script, .ns, .js files, or by pid");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get script arguments
|
||||||
|
const args = [];
|
||||||
|
for (let i = 1; i < commandArray.length; ++i) {
|
||||||
|
args.push(commandArray[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// go over all the running scripts. If there's a perfect
|
||||||
|
// match, use it!
|
||||||
|
for (let i = 0; i < server.runningScripts.length; ++i) {
|
||||||
|
if (server.runningScripts[i].filename === scriptName && compareArrays(server.runningScripts[i].args, args)) {
|
||||||
|
logBoxCreate(server.runningScripts[i]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find all scripts that are potential candidates.
|
||||||
|
const candidates = [];
|
||||||
|
for (let i = 0; i < server.runningScripts.length; ++i) {
|
||||||
|
// only scripts that have more arguments (equal arguments is already caught)
|
||||||
|
if (server.runningScripts[i].args.length < args.length) continue;
|
||||||
|
// make a smaller copy of the args.
|
||||||
|
const args2 = server.runningScripts[i].args.slice(0, args.length);
|
||||||
|
if (server.runningScripts[i].filename === scriptName && compareArrays(args2, args)) {
|
||||||
|
candidates.push(server.runningScripts[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's only 1 possible choice, use that.
|
||||||
|
if (candidates.length === 1) {
|
||||||
|
logBoxCreate(candidates[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise lists all possible conflicting choices.
|
||||||
|
if (candidates.length > 1) {
|
||||||
|
terminal.error("Found several potential candidates:");
|
||||||
|
for (const candidate of candidates) terminal.error(`${candidate.filename} ${candidate.args.join(" ")}`);
|
||||||
|
terminal.error("Script arguments need to be specified.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there's no candidate then we just don't know.
|
||||||
|
terminal.error("No such script exists.");
|
||||||
|
} else {
|
||||||
|
const runningScript = findRunningScriptByPid(commandArray[0], server);
|
||||||
|
if (runningScript == null) {
|
||||||
|
terminal.error("No such script exists");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logBoxCreate(runningScript);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
terminal.error(e + "");
|
||||||
|
}
|
||||||
|
}
|
60
src/Terminal/commands/theme.ts
Normal file
60
src/Terminal/commands/theme.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { FconfSettings } from "../../Fconf/FconfSettings";
|
||||||
|
|
||||||
|
export function theme(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 1 && args.length !== 3) {
|
||||||
|
terminal.error("Incorrect number of arguments.");
|
||||||
|
terminal.error(
|
||||||
|
"Usage: theme [default|muted|solarized] | #[background color hex] #[text color hex] #[highlight color hex]",
|
||||||
|
);
|
||||||
|
} else if (args.length === 1) {
|
||||||
|
const themeName = args[0];
|
||||||
|
if (themeName == "default") {
|
||||||
|
document.body.style.setProperty("--my-highlight-color", "#ffffff");
|
||||||
|
document.body.style.setProperty("--my-font-color", "#66ff33");
|
||||||
|
document.body.style.setProperty("--my-background-color", "#000000");
|
||||||
|
document.body.style.setProperty("--my-prompt-color", "#f92672");
|
||||||
|
} else if (themeName == "muted") {
|
||||||
|
document.body.style.setProperty("--my-highlight-color", "#ffffff");
|
||||||
|
document.body.style.setProperty("--my-font-color", "#66ff33");
|
||||||
|
document.body.style.setProperty("--my-background-color", "#252527");
|
||||||
|
} else if (themeName == "solarized") {
|
||||||
|
document.body.style.setProperty("--my-highlight-color", "#6c71c4");
|
||||||
|
document.body.style.setProperty("--my-font-color", "#839496");
|
||||||
|
document.body.style.setProperty("--my-background-color", "#002b36");
|
||||||
|
} else {
|
||||||
|
return terminal.error("Theme not found");
|
||||||
|
}
|
||||||
|
FconfSettings.THEME_HIGHLIGHT_COLOR = document.body.style.getPropertyValue("--my-highlight-color");
|
||||||
|
FconfSettings.THEME_FONT_COLOR = document.body.style.getPropertyValue("--my-font-color");
|
||||||
|
FconfSettings.THEME_BACKGROUND_COLOR = document.body.style.getPropertyValue("--my-background-color");
|
||||||
|
FconfSettings.THEME_PROMPT_COLOR = document.body.style.getPropertyValue("--my-prompt-color");
|
||||||
|
} else {
|
||||||
|
const inputBackgroundHex = args[0] + "";
|
||||||
|
const inputTextHex = args[1] + "";
|
||||||
|
const inputHighlightHex = args[2] + "";
|
||||||
|
if (
|
||||||
|
/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(inputBackgroundHex) &&
|
||||||
|
/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(inputTextHex) &&
|
||||||
|
/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(inputHighlightHex)
|
||||||
|
) {
|
||||||
|
document.body.style.setProperty("--my-highlight-color", inputHighlightHex);
|
||||||
|
document.body.style.setProperty("--my-font-color", inputTextHex);
|
||||||
|
document.body.style.setProperty("--my-background-color", inputBackgroundHex);
|
||||||
|
FconfSettings.THEME_HIGHLIGHT_COLOR = document.body.style.getPropertyValue("--my-highlight-color");
|
||||||
|
FconfSettings.THEME_FONT_COLOR = document.body.style.getPropertyValue("--my-font-color");
|
||||||
|
FconfSettings.THEME_BACKGROUND_COLOR = document.body.style.getPropertyValue("--my-background-color");
|
||||||
|
} else {
|
||||||
|
return terminal.error("Invalid Hex Input for theme");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
63
src/Terminal/commands/top.ts
Normal file
63
src/Terminal/commands/top.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { getRamUsageFromRunningScript } from "../../Script/RunningScriptHelpers";
|
||||||
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
|
||||||
|
export function top(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 0) {
|
||||||
|
terminal.error("Incorrect usage of top command. Usage: top");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Headers
|
||||||
|
const scriptWidth = 40;
|
||||||
|
const pidWidth = 10;
|
||||||
|
const threadsWidth = 16;
|
||||||
|
|
||||||
|
const scriptTxt = "Script";
|
||||||
|
const pidTxt = "PID";
|
||||||
|
const threadsTxt = "Threads";
|
||||||
|
const ramTxt = "RAM Usage";
|
||||||
|
|
||||||
|
const spacesAfterScriptTxt = " ".repeat(scriptWidth - scriptTxt.length);
|
||||||
|
const spacesAfterPidTxt = " ".repeat(pidWidth - pidTxt.length);
|
||||||
|
const spacesAfterThreadsTxt = " ".repeat(threadsWidth - threadsTxt.length);
|
||||||
|
|
||||||
|
const headers = `${scriptTxt}${spacesAfterScriptTxt}${pidTxt}${spacesAfterPidTxt}${threadsTxt}${spacesAfterThreadsTxt}${ramTxt}`;
|
||||||
|
|
||||||
|
terminal.print(headers);
|
||||||
|
|
||||||
|
const currRunningScripts = server.runningScripts;
|
||||||
|
// Iterate through scripts on current server
|
||||||
|
for (let i = 0; i < currRunningScripts.length; i++) {
|
||||||
|
const script = currRunningScripts[i];
|
||||||
|
|
||||||
|
// Calculate name padding
|
||||||
|
const numSpacesScript = Math.max(0, scriptWidth - script.filename.length);
|
||||||
|
const spacesScript = " ".repeat(numSpacesScript);
|
||||||
|
|
||||||
|
// Calculate PID padding
|
||||||
|
const numSpacesPid = Math.max(0, pidWidth - (script.pid + "").length);
|
||||||
|
const spacesPid = " ".repeat(numSpacesPid);
|
||||||
|
|
||||||
|
// Calculate thread padding
|
||||||
|
const numSpacesThread = Math.max(0, threadsWidth - (script.threads + "").length);
|
||||||
|
const spacesThread = " ".repeat(numSpacesThread);
|
||||||
|
|
||||||
|
// Calculate and transform RAM usage
|
||||||
|
const ramUsage = numeralWrapper.formatRAM(getRamUsageFromRunningScript(script) * script.threads);
|
||||||
|
|
||||||
|
const entry = [script.filename, spacesScript, script.pid, spacesPid, script.threads, spacesThread, ramUsage].join(
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
terminal.print(entry);
|
||||||
|
}
|
||||||
|
}
|
24
src/Terminal/commands/unalias.ts
Normal file
24
src/Terminal/commands/unalias.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { removeAlias } from "../../Alias";
|
||||||
|
|
||||||
|
export function unalias(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 1) {
|
||||||
|
terminal.error("Incorrect usage of unalias name. Usage: unalias [alias]");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (removeAlias(args[0] + "")) {
|
||||||
|
terminal.print(`Removed alias ${args[0]}`);
|
||||||
|
} else {
|
||||||
|
terminal.error(`No such alias exists: ${args[0]}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
45
src/Terminal/commands/wget.ts
Normal file
45
src/Terminal/commands/wget.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { ITerminal } from "../ITerminal";
|
||||||
|
import { IEngine } from "../../IEngine";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
|
import { isScriptFilename } from "../../Script/ScriptHelpersTS";
|
||||||
|
|
||||||
|
export function wget(
|
||||||
|
terminal: ITerminal,
|
||||||
|
engine: IEngine,
|
||||||
|
player: IPlayer,
|
||||||
|
server: BaseServer,
|
||||||
|
args: (string | number)[],
|
||||||
|
): void {
|
||||||
|
if (args.length !== 2) {
|
||||||
|
terminal.error("Incorrect usage of wget command. Usage: wget [url] [target file]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = args[0] + "";
|
||||||
|
const target = terminal.getFilepath(args[1] + "");
|
||||||
|
if (!isScriptFilename(target) && !target.endsWith(".txt")) {
|
||||||
|
return terminal.print(`wget failed: Invalid target file. Target file must be script or text file`);
|
||||||
|
}
|
||||||
|
$.get(
|
||||||
|
url,
|
||||||
|
function (data: any) {
|
||||||
|
let res;
|
||||||
|
if (isScriptFilename(target)) {
|
||||||
|
res = server.writeToScriptFile(target, data);
|
||||||
|
} else {
|
||||||
|
res = server.writeToTextFile(target, data);
|
||||||
|
}
|
||||||
|
if (!res.success) {
|
||||||
|
return terminal.print("wget failed");
|
||||||
|
}
|
||||||
|
if (res.overwritten) {
|
||||||
|
return terminal.print(`wget successfully retrieved content and overwrote ${target}`);
|
||||||
|
}
|
||||||
|
return terminal.print(`wget successfully retrieved content to new file ${target}`);
|
||||||
|
},
|
||||||
|
"text",
|
||||||
|
).fail(function (e) {
|
||||||
|
return terminal.error("wget failed: " + JSON.stringify(e));
|
||||||
|
});
|
||||||
|
}
|
1
src/ThirdParty/arg.d.ts
vendored
Normal file
1
src/ThirdParty/arg.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
declare module "arg";
|
@ -58,7 +58,6 @@ import { Terminal, postVersion } from "./Terminal";
|
|||||||
import { TutorialRoot } from "./Tutorial/ui/TutorialRoot";
|
import { TutorialRoot } from "./Tutorial/ui/TutorialRoot";
|
||||||
import { Sleeve } from "./PersonObjects/Sleeve/Sleeve";
|
import { Sleeve } from "./PersonObjects/Sleeve/Sleeve";
|
||||||
|
|
||||||
import { createStatusText } from "./ui/createStatusText";
|
|
||||||
import { CharacterInfo } from "./ui/CharacterInfo";
|
import { CharacterInfo } from "./ui/CharacterInfo";
|
||||||
import { Page, routing } from "./ui/navigationTracking";
|
import { Page, routing } from "./ui/navigationTracking";
|
||||||
import { Money } from "./ui/React/Money";
|
import { Money } from "./ui/React/Money";
|
||||||
@ -68,8 +67,6 @@ import { Reputation } from "./ui/React/Reputation";
|
|||||||
import { ActiveScriptsRoot } from "./ui/ActiveScripts/Root";
|
import { ActiveScriptsRoot } from "./ui/ActiveScripts/Root";
|
||||||
import { MainMenuLinks } from "./ui/MainMenu/Links";
|
import { MainMenuLinks } from "./ui/MainMenu/Links";
|
||||||
|
|
||||||
import { createPopup } from "./ui/React/createPopup";
|
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../utils/DialogBox";
|
import { dialogBoxCreate } from "../utils/DialogBox";
|
||||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||||
import { removeLoadingScreen } from "../utils/uiHelpers/removeLoadingScreen";
|
import { removeLoadingScreen } from "../utils/uiHelpers/removeLoadingScreen";
|
||||||
|
Loading…
Reference in New Issue
Block a user