merge base

This commit is contained in:
phyzical 2022-04-15 14:25:13 +08:00
commit 8db74f343a
19 changed files with 232 additions and 98 deletions

@ -1,5 +1,14 @@
# DELETE THIS AFTER READING
# PR title
Formatted as such:
SECTION: FIX #xzyw PLAYER DESCRIPTION
SECTION is something like "API", "UI", "MISC", "STANEK", "CORPORATION"
FIX #xyzw is the issue number, if any
PLAYER DESCRIPTION is what you'd tell a non-contributor to convey what is changed.
# Documentation
- DO NOT CHANGE any markdown/\*.md, these files are autogenerated from NetscriptDefinitions.d.ts and will be overwritten
@ -10,5 +19,4 @@
- Include how it was tested
- Include screenshot / gif (if possible)
Make sure you run `npm run format` and `npm run lint` before pushing.

@ -1,5 +1,7 @@
# Bitburner
[![Join Discord](https://img.shields.io/discord/415207508303544321)](https://discord.gg/TFc3hKD)
[![Build Status](https://github.com/danielyxie/bitburner/actions/workflows/ci.yml/badge.svg?branch=dev)](https://github.com/danielyxie/bitburner/actions/workflows/ci.yml)
Bitburner is a programming-based [incremental game](https://en.wikipedia.org/wiki/Incremental_game)

11
lore/bitnodes-general.txt Normal file

@ -0,0 +1,11 @@
BitNodes are advanced simulations used to contain humanity by the Enders. It is
unknown how or why they operate, but what is clear is that the World Daemon is
extremely important to the operation of a BitNode. It is possible for the daemon
to be hacked, which results in the entire simulation going offline and the
failure of automatic attempts to reboot the node. The Daemon has a physical
presence, as indicated by the Bladeburners' ability to destroy it via force.
Also, hydroflame (irl) has stated that the glitch in Ishima is the physical
location of the World Daemon in a node. When the player destroys a BitNode, it is
currently unknown what becomes of it, or the people trapped within. However, based
on the way jump3r and Deadalus help the player to destroy it, doing so is somehow
aligned with their goals.

5
lore/enders.txt Normal file

@ -0,0 +1,5 @@
The "Enders", as dubbed by the humans who know of them, are a humanoid alien race
with extremely advanced technology. "Many decades ago", they invaded Earth, leading
to war between the humans and enders, but the enders were far too powerful for the
humans to win against. When the enders had won, they, for reasons unknown, kept some
number of humans alive, and in some way contained the humans within BitNodes.

24
package-lock.json generated

@ -5046,9 +5046,9 @@
}
},
"node_modules/async": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
"integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
"version": "2.6.4",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
"integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
"dev": true,
"dependencies": {
"lodash": "^4.17.14"
@ -10199,9 +10199,9 @@
}
},
"node_modules/getos/node_modules/async": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.1.tgz",
"integrity": "sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg==",
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz",
"integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==",
"dev": true
},
"node_modules/getpass": {
@ -26245,9 +26245,9 @@
"dev": true
},
"async": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
"integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
"version": "2.6.4",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
"integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
"dev": true,
"requires": {
"lodash": "^4.17.14"
@ -30405,9 +30405,9 @@
},
"dependencies": {
"async": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.1.tgz",
"integrity": "sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg==",
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz",
"integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==",
"dev": true
}
}

@ -134,6 +134,7 @@
"allbuild": "npm run build && npm run electron && git add --all && git commit -m \"allbuild commit $(git rev-parse --short HEAD)\" && git push -f -u origin dev",
"preversion": "npm install && npm run test",
"version": "sh ./tools/build-release.sh && git add --all",
"postversion": "git push -u origin dev && git push --tags"
"postversion": "git push -u origin dev && git push --tags",
"changelog": "node tools/fetch-changelog/index.js --from=$(cat last_changelog_hash) > changelog.md"
}
}

@ -6,6 +6,7 @@ import { WHRNG } from "../../Casino/RNG";
import React from "react";
import { FactionNames } from "../../Faction/data/FactionNames";
import { CityName } from "../../Locations/data/CityNames";
import { CONSTANTS } from "../../Constants";
function getRandomBonus(): any {
const bonuses = [
@ -2049,6 +2050,7 @@ export const initChurchOfTheMachineGodAugmentations = (): Augmentation[] => [
];
export function initNeuroFluxGovernor(): Augmentation {
const donationBonus = CONSTANTS.Donations / 1e6 / 100; // 1 millionth of a percent per donation
return new Augmentation({
name: AugmentationNames.NeuroFluxGovernor,
repCost: 500,
@ -2061,35 +2063,35 @@ export function initNeuroFluxGovernor(): Augmentation {
stats: (
<>
This special augmentation can be leveled up infinitely. Each level of this augmentation increases MOST
multipliers by 1%, stacking multiplicatively.
multipliers by 1% (+{donationBonus * 100}% boosted by real life blood donations), stacking multiplicatively.
</>
),
hacking_chance_mult: 1.01,
hacking_speed_mult: 1.01,
hacking_money_mult: 1.01,
hacking_grow_mult: 1.01,
hacking_mult: 1.01,
strength_mult: 1.01,
defense_mult: 1.01,
dexterity_mult: 1.01,
agility_mult: 1.01,
charisma_mult: 1.01,
hacking_exp_mult: 1.01,
strength_exp_mult: 1.01,
defense_exp_mult: 1.01,
dexterity_exp_mult: 1.01,
agility_exp_mult: 1.01,
charisma_exp_mult: 1.01,
company_rep_mult: 1.01,
faction_rep_mult: 1.01,
crime_money_mult: 1.01,
crime_success_mult: 1.01,
hacknet_node_money_mult: 1.01,
hacknet_node_purchase_cost_mult: 0.99,
hacknet_node_ram_cost_mult: 0.99,
hacknet_node_core_cost_mult: 0.99,
hacknet_node_level_cost_mult: 0.99,
work_money_mult: 1.01,
hacking_chance_mult: 1.01 + donationBonus,
hacking_speed_mult: 1.01 + donationBonus,
hacking_money_mult: 1.01 + donationBonus,
hacking_grow_mult: 1.01 + donationBonus,
hacking_mult: 1.01 + donationBonus,
strength_mult: 1.01 + donationBonus,
defense_mult: 1.01 + donationBonus,
dexterity_mult: 1.01 + donationBonus,
agility_mult: 1.01 + donationBonus,
charisma_mult: 1.01 + donationBonus,
hacking_exp_mult: 1.01 + donationBonus,
strength_exp_mult: 1.01 + donationBonus,
defense_exp_mult: 1.01 + donationBonus,
dexterity_exp_mult: 1.01 + donationBonus,
agility_exp_mult: 1.01 + donationBonus,
charisma_exp_mult: 1.01 + donationBonus,
company_rep_mult: 1.01 + donationBonus,
faction_rep_mult: 1.01 + donationBonus,
crime_money_mult: 1.01 + donationBonus,
crime_success_mult: 1.01 + donationBonus,
hacknet_node_money_mult: 1.01 + donationBonus,
hacknet_node_purchase_cost_mult: 1 / (1.01 + donationBonus),
hacknet_node_ram_cost_mult: 1 / (1.01 + donationBonus),
hacknet_node_core_cost_mult: 1 / (1.01 + donationBonus),
hacknet_node_level_cost_mult: 1 / (1.01 + donationBonus),
work_money_mult: 1.01 + donationBonus,
factions: Object.values(FactionNames).filter(
(factionName) =>
![FactionNames.Infiltrators, FactionNames.Bladeburners, FactionNames.ChurchOfTheMachineGod].includes(

@ -114,6 +114,7 @@ export const CONSTANTS: {
AugmentationGraftingTimeBase: number;
EntropyEffect: number;
TotalNumBitNodes: number;
Donations: number; // number of blood/plasma/palette donation the dev have verified., boosts NFG
LatestUpdate: string;
} = {
VersionString: "1.6.4",
@ -286,6 +287,8 @@ export const CONSTANTS: {
// BitNode/Source-File related stuff
TotalNumBitNodes: 24,
Donations: 2,
LatestUpdate: `
v1.6.3 - 2022-04-01 Few stanek fixes
----------------------------

@ -40,8 +40,9 @@ export class ActiveFragment {
// These 2 variables converts 'this' local coordinates to world to other local.
const dx: number = other.x - this.x;
const dy: number = other.y - this.y;
for (let j = 0; j < thisFragment.shape.length; j++) {
for (let i = 0; i < thisFragment.shape[j].length; i++) {
const fragSize = Math.max(thisFragment.shape.length, thisFragment.shape[0].length);
for (let j = 0; j < fragSize; j++) {
for (let i = 0; i < fragSize; i++) {
if (thisFragment.fullAt(i, j, this.rotation) && otherFragment.fullAt(i - dx, j - dy, other.rotation))
return true;
}

@ -183,7 +183,7 @@ const Messages: Record<MessageFilenames, Message> = {
"like us. Because they can't hide from us. Because they can't fight shadows " +
"and ideas with bullets. <br><br>" +
"Join us, and people will fear you, too. <br><br>" +
"Find and install the backdoor on our server. Then, we will contact you again." +
"Find and install the backdoor on our server, avmnite-02h. Then, we will contact you again." +
`<br><br>-${FactionNames.NiteSec}`,
),

@ -59,17 +59,20 @@ export function NetscriptExtra(player: IPlayer, workerScript: WorkerScript, help
player.giveExploit(Exploit.RealityAlteration);
}
},
rainbow: function (guess: unknown): void {
async function tryGuess(): Promise<void> {
const verified = await bcrypt.compare(
rainbow: function (guess: unknown): boolean {
function tryGuess(): boolean {
// eslint-disable-next-line no-sync
const verified = bcrypt.compareSync(
helper.string("rainbow", "guess", guess),
"$2a$10$aertxDEkgor8baVtQDZsLuMwwGYmkRM/ohcA6FjmmzIHQeTCsrCcO",
);
if (verified) {
player.giveExploit(Exploit.INeedARainbow);
return true;
}
return false;
}
tryGuess();
return tryGuess();
},
};
}

@ -38,6 +38,7 @@ import {
calculateAscensionPointsGain,
} from "../Gang/formulas/formulas";
import { favorToRep as calculateFavorToRep, repToFavor as calculateRepToFavor } from "../Faction/formulas/favor";
import { repFromDonation } from "../Faction/formulas/donation";
export function NetscriptFormulas(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): IFormulas {
const checkFormulasAccess = function (func: string): void {
@ -57,6 +58,11 @@ export function NetscriptFormulas(player: IPlayer, workerScript: WorkerScript, h
checkFormulasAccess("reputation.calculateRepToFavor");
return calculateRepToFavor(rep);
},
repFromDonation: function (_amount: unknown, player: any): number {
const amount = helper.number("repFromDonation", "amount", _amount);
checkFormulasAccess("reputation.repFromDonation");
return repFromDonation(amount, player);
},
},
skills: {
calculateSkill: function (_exp: unknown, _mult: unknown = 1): number {

@ -23,7 +23,6 @@ import { findCrime } from "../Crime/CrimeHelpers";
import { CompanyPosition } from "../Company/CompanyPosition";
import { CompanyPositions } from "../Company/CompanyPositions";
import { DarkWebItems } from "../DarkWeb/DarkWebItems";
import { AllGangs } from "../Gang/AllGangs";
import { CityName } from "../Locations/data/CityNames";
import { LocationName } from "../Locations/data/LocationNames";
import { Router } from "../ui/GameRoot";
@ -49,6 +48,7 @@ import { FactionInfos } from "../Faction/FactionInfo";
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
import { BlackOperationNames } from "../Bladeburner/data/BlackOperationNames";
import { enterBitNode } from "../RedPill";
import { FactionNames } from "../Faction/data/FactionNames";
export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript): InternalAPI<ISingularity> {
const getAugmentation = function (_ctx: NetscriptContext, name: string): Augmentation {
@ -1047,11 +1047,14 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
const facName = _ctx.helper.string("facName", _facName);
const type = _ctx.helper.string("type", _type);
const focus = _ctx.helper.boolean(_focus);
getFaction(_ctx, facName);
const faction = getFaction(_ctx, facName);
// if the player is in a gang and the target faction is any of the gang faction, fail
if (player.inGang() && AllGangs[facName] !== undefined) {
workerScript.log("workForFaction", () => `Faction '${facName}' does not offer work at the moment.`);
if (player.inGang() && faction.name === player.getGangFaction().name) {
workerScript.log(
"workForFaction",
() => `You can't work for '${facName}' because youre managing a gang for it`,
);
return false;
}
@ -1066,21 +1069,18 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
workerScript.log("workForFaction", () => txt);
}
const fac = Factions[facName];
// Arrays listing factions that allow each time of work
switch (type.toLowerCase()) {
case "hacking":
case "hacking contracts":
case "hackingcontracts":
if (!FactionInfos[fac.name].offerHackingWork) {
if (!FactionInfos[faction.name].offerHackingWork) {
workerScript.log(
"workForFaction",
() => `Faction '${fac.name}' do not need help with hacking contracts.`,
() => `Faction '${faction.name}' do not need help with hacking contracts.`,
);
return false;
}
player.startFactionHackWork(fac);
player.startFactionHackWork(faction);
if (focus) {
player.startFocusing();
Router.toWork();
@ -1088,16 +1088,19 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
player.stopFocusing();
Router.toTerminal();
}
workerScript.log("workForFaction", () => `Started carrying out hacking contracts for '${fac.name}'`);
workerScript.log("workForFaction", () => `Started carrying out hacking contracts for '${faction.name}'`);
return true;
case "field":
case "fieldwork":
case "field work":
if (!FactionInfos[fac.name].offerFieldWork) {
workerScript.log("workForFaction", () => `Faction '${fac.name}' do not need help with field missions.`);
if (!FactionInfos[faction.name].offerFieldWork) {
workerScript.log(
"workForFaction",
() => `Faction '${faction.name}' do not need help with field missions.`,
);
return false;
}
player.startFactionFieldWork(fac);
player.startFactionFieldWork(faction);
if (focus) {
player.startFocusing();
Router.toWork();
@ -1105,16 +1108,19 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
player.stopFocusing();
Router.toTerminal();
}
workerScript.log("workForFaction", () => `Started carrying out field missions for '${fac.name}'`);
workerScript.log("workForFaction", () => `Started carrying out field missions for '${faction.name}'`);
return true;
case "security":
case "securitywork":
case "security work":
if (!FactionInfos[fac.name].offerSecurityWork) {
workerScript.log("workForFaction", () => `Faction '${fac.name}' do not need help with security work.`);
if (!FactionInfos[faction.name].offerSecurityWork) {
workerScript.log(
"workForFaction",
() => `Faction '${faction.name}' do not need help with security work.`,
);
return false;
}
player.startFactionSecurityWork(fac);
player.startFactionSecurityWork(faction);
if (focus) {
player.startFocusing();
Router.toWork();
@ -1122,7 +1128,7 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
player.stopFocusing();
Router.toTerminal();
}
workerScript.log("workForFaction", () => `Started carrying out security work for '${fac.name}'`);
workerScript.log("workForFaction", () => `Started carrying out security work for '${faction.name}'`);
return true;
default:
workerScript.log("workForFaction", () => `Invalid work type: '${type}`);
@ -1168,6 +1174,13 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
);
return false;
}
if (faction.name === FactionNames.ChurchOfTheMachineGod || faction.name === FactionNames.Bladeburners) {
workerScript.log(
"donateToFaction",
() => `You can't donate to '${facName}' because they do not accept donations`,
);
return false;
}
if (typeof amt !== "number" || amt <= 0 || isNaN(amt)) {
workerScript.log("donateToFaction", () => `Invalid donation amount: '${amt}'.`);
return false;

@ -16,6 +16,7 @@ import {
SleeveSkills,
SleeveTask,
} from "../ScriptEditor/NetscriptDefinitions";
import { checkEnum } from "../utils/helpers/checkEnum";
export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): ISleeve {
const checkSleeveAPIAccess = function (func: string): void {
@ -99,7 +100,11 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
const cityName = helper.string("travel", "cityName", _cityName);
checkSleeveAPIAccess("travel");
checkSleeveNumber("travel", sleeveNumber);
return player.sleeves[sleeveNumber].travel(player, cityName as CityName);
if (checkEnum(CityName, cityName)) {
return player.sleeves[sleeveNumber].travel(player, cityName);
} else {
throw helper.makeRuntimeErrorMsg("sleeve.setToCompanyWork", `Invalid city name: '${cityName}'.`);
}
},
setToCompanyWork: function (_sleeveNumber: unknown, acompanyName: unknown): boolean {
updateRam("setToCompanyWork");

@ -37,6 +37,7 @@ import { ISkillProgress } from "../formulas/skill";
import { PlayerAchievement } from "../../Achievements/Achievements";
import { cyrb53 } from "../../utils/StringHelperFunctions";
import { getRandomInt } from "../../utils/helpers/getRandomInt";
import { CONSTANTS } from "../../Constants";
export class PlayerObject implements IPlayer {
// Class members
@ -361,7 +362,7 @@ export class PlayerObject implements IPlayer {
this.faction_rep_mult = 1;
//Money
this.money = 1000;
this.money = 1000 + CONSTANTS.Donations;
//Location information
this.city = CityName.Sector12;

@ -105,7 +105,7 @@ export function prestigeAugmentation(this: PlayerObject): void {
this.agility_exp = 0;
this.charisma_exp = 0;
this.money = 1000;
this.money = 1000 + CONSTANTS.Donations;
this.city = CityName.Sector12;
this.location = LocationName.TravelAgency;

@ -3873,6 +3873,13 @@ interface ReputationFormulas {
* @returns The calculated faction favor.
*/
calculateRepToFavor(rep: number): number;
/**
* Calculate how much rep would be gained.
* @param amount - Amount of money donated
* @param player - Player info from {@link NS.getPlayer | getPlayer}
*/
repFromDonation(amount: number, player: Player): number;
}
/**

@ -9,6 +9,8 @@ import { evaluateDirectoryPath, getFirstParentDirectory, isValidDirectoryPath }
import { IRouter } from "../../ui/Router";
import { ITerminal } from "../ITerminal";
import * as libarg from "arg";
import { showLiterature } from "../../Literature/LiteratureHelpers";
import { MessageFilenames, showMessage } from "../../Message/MessageHelpers";
export function ls(
terminal: ITerminal,
@ -121,13 +123,13 @@ export function ls(
allMessages.sort();
folders.sort();
interface ClickableScriptRowProps {
interface ClickableRowProps {
row: string;
prefix: string;
hostname: string;
}
function ClickableScriptRow({ row, prefix, hostname }: ClickableScriptRowProps): React.ReactElement {
function ClickableScriptRow({ row, prefix, hostname }: ClickableRowProps): React.ReactElement {
const classes = makeStyles((theme: Theme) =>
createStyles({
scriptLinksWrap: {
@ -160,18 +162,82 @@ export function ls(
return (
<span className={classes.scriptLinksWrap}>
{rowSplitArray.map((rowItem) => (
<span>
<span key={rowItem[0]} className={classes.scriptLink} onClick={() => onScriptLinkClick(rowItem[0])}>
<span key={"script_" + rowItem[0]}>
<span className={classes.scriptLink} onClick={() => onScriptLinkClick(rowItem[0])}>
{rowItem[0]}
</span>
<span key={"s" + rowItem[0]}>{rowItem[1]}</span>
<span>{rowItem[1]}</span>
</span>
))}
</span>
);
}
function postSegments(segments: string[], flags: any, style?: any, linked?: boolean): void {
function ClickableMessageRow({ row, prefix, hostname }: ClickableRowProps): React.ReactElement {
const classes = makeStyles((theme: Theme) =>
createStyles({
linksWrap: {
display: "inline-flex",
color: theme.palette.primary.main,
},
link: {
cursor: "pointer",
textDecorationLine: "underline",
paddingRight: "1.15em",
"&:last-child": { padding: 0 },
},
}),
)();
const rowSplit = row.split("~");
let rowSplitArray = rowSplit.map((x) => [x.trim(), x.replace(x.trim(), "")]);
rowSplitArray = rowSplitArray.filter((x) => !!x[0]);
function onMessageLinkClick(filename: string): void {
if (player.getCurrentServer().hostname !== hostname) {
return terminal.error(`File is not on this server, connect to ${hostname} and try again`);
}
if (filename.startsWith("/")) filename = filename.slice(1);
const filepath = terminal.getFilepath(`${prefix}${filename}`);
if (filepath.endsWith(".lit")) {
showLiterature(filepath);
} else if (filepath.endsWith(".msg")) {
showMessage(filepath as MessageFilenames);
}
}
return (
<span className={classes.linksWrap}>
{rowSplitArray.map((rowItem) => (
<span key={"text_" + rowItem[0]}>
<span className={classes.link} onClick={() => onMessageLinkClick(rowItem[0])}>
{rowItem[0]}
</span>
<span>{rowItem[1]}</span>
</span>
))}
</span>
);
}
enum FileType {
Folder,
Message,
TextFile,
Program,
Contract,
Script,
}
interface FileGroup {
type: FileType;
segments: string[];
}
function postSegments(group: FileGroup, flags: any): void {
const segments = group.segments;
const linked = group.type === FileType.Script || group.type === FileType.Message;
const maxLength = Math.max(...segments.map((s) => s.length)) + 1;
const filesPerRow = flags["-l"] === true ? 1 : Math.ceil(80 / maxLength);
for (let i = 0; i < segments.length; i++) {
@ -186,25 +252,32 @@ export function ls(
i++;
}
i--;
if (!style) {
terminal.print(row);
} else if (linked) {
terminal.printRaw(<ClickableScriptRow row={row} prefix={prefix} hostname={server.hostname} />);
} else {
terminal.printRaw(<span style={style}>{row}</span>);
switch (group.type) {
case FileType.Folder:
terminal.printRaw(<span style={{ color: "cyan" }}>{row}</span>);
break;
case FileType.Script:
terminal.printRaw(<ClickableScriptRow row={row} prefix={prefix} hostname={server.hostname} />);
break;
case FileType.Message:
terminal.printRaw(<ClickableMessageRow row={row} prefix={prefix} hostname={server.hostname} />);
break;
default:
terminal.print(row);
}
}
}
const groups = [
{ segments: folders, style: { color: "cyan" } },
{ segments: allMessages },
{ segments: allTextFiles },
{ segments: allPrograms },
{ segments: allContracts },
{ segments: allScripts, style: { color: "yellow", fontStyle: "bold" }, linked: true },
const groups: FileGroup[] = [
{ type: FileType.Folder, segments: folders },
{ type: FileType.Message, segments: allMessages },
{ type: FileType.TextFile, segments: allTextFiles },
{ type: FileType.Program, segments: allPrograms },
{ type: FileType.Contract, segments: allContracts },
{ type: FileType.Script, segments: allScripts },
].filter((g) => g.segments.length > 0);
for (let i = 0; i < groups.length; i++) {
postSegments(groups[i].segments, flags, groups[i].style, groups[i].linked);
for (const group of groups) {
postSegments(group, flags);
}
}

@ -6,7 +6,6 @@ import { getRamCost, RamCostConstants } from "../../../src/Netscript/RamCostGene
import { Environment } from "../../../src/Netscript/Environment";
import { RunningScript } from "../../../src/Script/RunningScript";
import { Script } from "../../../src/Script/Script";
import { SourceFileFlags } from "../../../src/SourceFile/SourceFileFlags";
jest.mock(`!!raw-loader!../NetscriptDefinitions.d.ts`, () => "", {
virtual: true,
@ -169,12 +168,6 @@ describe("Netscript Dynamic RAM Calculation/Generation Tests", function () {
testEquality(workerScript.dynamicRamUsage, runningScript.ramUsage);
}
beforeEach(function () {
for (let i = 0; i < SourceFileFlags.length; ++i) {
SourceFileFlags[i] = 3;
}
});
describe("Basic Functions", function () {
it("hack()", async function () {
const f = ["hack"];