Merge branch 'danielyxie:dev' into sleeve

This commit is contained in:
Mughur 2022-08-26 00:35:05 +03:00 committed by GitHub
commit e361866ab8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 102 additions and 125 deletions

@ -1465,47 +1465,42 @@ const base: InternalAPI<NS> = {
},
write:
(ctx: NetscriptContext) =>
(_port: unknown, _data: unknown = "", _mode: unknown = "a"): void => {
const port = helpers.string(ctx, "port", _port);
(_filename: unknown, _data: unknown = "", _mode: unknown = "a"): void => {
let fn = helpers.string(ctx, "handle", _filename);
const data = helpers.string(ctx, "data", _data);
const mode = helpers.string(ctx, "mode", _mode);
if (isString(port)) {
// Write to script or text file
let fn = port;
if (!isValidFilePath(fn)) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid filepath: ${fn}`);
if (!isValidFilePath(fn)) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid filepath: ${fn}`);
if (fn.lastIndexOf("/") === 0) fn = removeLeadingSlash(fn);
if (fn.lastIndexOf("/") === 0) fn = removeLeadingSlash(fn);
const server = helpers.getServer(ctx, ctx.workerScript.hostname);
const server = helpers.getServer(ctx, ctx.workerScript.hostname);
if (isScriptFilename(fn)) {
// Write to script
let script = ctx.workerScript.getScriptOnServer(fn, server);
if (script == null) {
// Create a new script
script = new Script(Player, fn, String(data), server.hostname, server.scripts);
server.scripts.push(script);
return script.updateRamUsage(Player, server.scripts);
}
mode === "w" ? (script.code = String(data)) : (script.code += data);
if (isScriptFilename(fn)) {
// Write to script
let script = ctx.workerScript.getScriptOnServer(fn, server);
if (script == null) {
// Create a new script
script = new Script(Player, fn, String(data), server.hostname, server.scripts);
server.scripts.push(script);
return script.updateRamUsage(Player, server.scripts);
} else {
// Write to text file
const txtFile = getTextFile(fn, server);
if (txtFile == null) {
createTextFile(fn, String(data), server);
return;
}
if (mode === "w") {
txtFile.write(String(data));
} else {
txtFile.append(String(data));
}
}
return;
mode === "w" ? (script.code = String(data)) : (script.code += data);
return script.updateRamUsage(Player, server.scripts);
} else {
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid argument: ${port}`);
// Write to text file
if (!fn.endsWith(".txt")) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid filename: ${fn}`);
const txtFile = getTextFile(fn, server);
if (txtFile == null) {
createTextFile(fn, String(data), server);
return;
}
if (mode === "w") {
txtFile.write(String(data));
} else {
txtFile.append(String(data));
}
}
return;
},
tryWritePort:
(ctx: NetscriptContext) =>
@ -1545,33 +1540,27 @@ const base: InternalAPI<NS> = {
},
read:
(ctx: NetscriptContext) =>
(_port: unknown): string => {
const port = helpers.string(ctx, "port", _port);
if (isString(port)) {
// Read from script or text file
const fn = port;
const server = GetServer(ctx.workerScript.hostname);
if (server == null) {
throw helpers.makeRuntimeErrorMsg(ctx, "Error getting Server. This is a bug. Report to dev.");
}
if (isScriptFilename(fn)) {
// Read from script
const script = ctx.workerScript.getScriptOnServer(fn, server);
if (script == null) {
return "";
}
return script.code;
} else {
// Read from text file
const txtFile = getTextFile(fn, server);
if (txtFile !== null) {
return txtFile.text;
} else {
return "";
}
(_filename: unknown): string => {
const fn = helpers.string(ctx, "filename", _filename);
const server = GetServer(ctx.workerScript.hostname);
if (server == null) {
throw helpers.makeRuntimeErrorMsg(ctx, "Error getting Server. This is a bug. Report to dev.");
}
if (isScriptFilename(fn)) {
// Read from script
const script = ctx.workerScript.getScriptOnServer(fn, server);
if (script == null) {
return "";
}
return script.code;
} else {
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid argument: ${port}`);
// Read from text file
const txtFile = getTextFile(fn, server);
if (txtFile !== null) {
return txtFile.text;
} else {
return "";
}
}
},
peek:

@ -4,7 +4,7 @@ import { ScriptArg } from "../Netscript/ScriptArg";
import { NetscriptContext } from "../Netscript/APIWrapper";
type FlagType = StringConstructor | NumberConstructor | BooleanConstructor | StringConstructor[];
type FlagsRet = { [key: string]: ScriptArg };
type FlagsRet = { [key: string]: ScriptArg | string[] };
export function Flags(ctx: NetscriptContext | string[]): (data: unknown) => FlagsRet {
const vargs = Array.isArray(ctx) ? ctx : ctx.workerScript.args;
return (schema: unknown): FlagsRet => {

@ -1514,7 +1514,7 @@ export interface Singularity {
* @param universityName - Name of university. You must be in the correct city for whatever university you specify.
* @param courseName - Name of course.
* @param focus - Acquire player focus on this class. Optional. Defaults to true.
* @returns True if actions is successfully started, false otherwise.
* @returns True if action is successfully started, false otherwise.
*/
universityCourse(universityName: string, courseName: string, focus?: boolean): boolean;
@ -2369,7 +2369,7 @@ export interface Hacknet {
*
* Returns the number of Hacknet Nodes you own.
*
* @returns number of hacknet nodes.
* @returns Number of hacknet nodes.
*/
numNodes(): number;
@ -2378,7 +2378,7 @@ export interface Hacknet {
* @remarks
* RAM cost: 0 GB
*
* @returns maximum number of hacknet nodes.
* @returns Maximum number of hacknet nodes.
*/
maxNumNodes(): number;
@ -2453,13 +2453,13 @@ export interface Hacknet {
* So this is equivalent to multiplying the Nodes RAM by 2 n.
*
* Returns true if the Hacknet Nodes RAM is successfully upgraded n times
* or if it is upgraded some positive number of times and the Node reaches it max RAM.
* or if it is upgraded some positive number of times and the Node reaches its max RAM.
*
* Returns false otherwise.
*
* @param index - Index/Identifier of Hacknet Node.
* @param n - Number of times to upgrade RAM. Must be positive. Rounded to nearest integer.
* @returns True if the Hacknet Nodes ram is successfully upgraded, false otherwise.
* @returns True if the Hacknet Nodes RAM is successfully upgraded, false otherwise.
*/
upgradeRam(index: number, n: number): boolean;
@ -2497,7 +2497,7 @@ export interface Hacknet {
*
* @param index - Index/Identifier of Hacknet Node.
* @param n - Number of cache levels to purchase. Must be positive. Rounded to nearest integer.
* @returns True if the Hacknet Nodes cores are successfully purchased, false otherwise.
* @returns True if the Hacknet Nodes cache level is successfully upgraded, false otherwise.
*/
upgradeCache(index: number, n: number): boolean;
@ -2525,11 +2525,11 @@ export interface Hacknet {
* Returns the cost of upgrading the RAM of the specified Hacknet Node n times.
*
* If an invalid value for n is provided, then this function returns 0.
* If the specified Hacknet Node is already at max level, then Infinity is returned.
* If the specified Hacknet Node already has max RAM, then Infinity is returned.
*
* @param index - Index/Identifier of Hacknet Node.
* @param n - Number of times to upgrade RAM. Must be positive. Rounded to nearest integer.
* @returns Cost of upgrading the specified Hacknet Node's ram.
* @returns Cost of upgrading the specified Hacknet Node's RAM.
*/
getRamUpgradeCost(index: number, n: number): number;
@ -2654,7 +2654,7 @@ export interface Hacknet {
* @param upgTarget - Object to which upgrade applies. Required for certain upgrades.
* @param count - Number of upgrades to buy at once. Defaults to 1 if not specified.
* For compatability reasons, upgTarget must be specified, even if it is not used, in order to specify count.
* @returns True if the upgrade is successfully purchased, and false otherwise..
* @returns True if the upgrade is successfully purchased, and false otherwise.
*/
spendHashes(upgName: string, upgTarget?: string, count?: number): boolean;
@ -3218,7 +3218,7 @@ export interface CodingContract {
*
* @param answer - Solution for the contract.
* @param filename - Filename of the contract.
* @param host - Host of the server containing the contract. Optional. Defaults to current server if not provided.
* @param host - Hostname of the server containing the contract. Optional. Defaults to current server if not provided.
* @param opts - Optional parameters for configuring function behavior.
* @returns True if the solution was correct, false otherwise. If the returnReward option is configured, then the function will instead return a string. If the contract is successfully solved, the string will contain a description of the contracts reward. Otherwise, it will be an empty string.
*/
@ -3238,7 +3238,7 @@ export interface CodingContract {
* (e.g. Find Largest Prime Factor, Total Ways to Sum, etc.)
*
* @param filename - Filename of the contract.
* @param host - Host of the server containing the contract. Optional. Defaults to current server if not provided.
* @param host - Hostname of the server containing the contract. Optional. Defaults to current server if not provided.
* @returns Name describing the type of problem posed by the Coding Contract.
*/
getContractType(filename: string, host?: string): string;
@ -3251,7 +3251,7 @@ export interface CodingContract {
* Get the full text description for the problem posed by the Coding Contract.
*
* @param filename - Filename of the contract.
* @param host - Host of the server containing the contract. Optional. Defaults to current server if not provided.
* @param host - Hostname of the server containing the contract. Optional. Defaults to current server if not provided.
* @returns Contracts text description.
*/
getDescription(filename: string, host?: string): string;
@ -3263,24 +3263,24 @@ export interface CodingContract {
*
* Get the data associated with the specific Coding Contract.
* Note that this is not the same as the contracts description.
* This is just the data that the contract wants you to act on in order to solve
* This is just the data that the contract wants you to act on in order to solve the contract.
*
* @param filename - Filename of the contract.
* @param host - Host of the server containing the contract. Optional. Defaults to current server if not provided.
* @returns The specified contracts data, data type depends on contract type.;
* @returns The specified contracts data, data type depends on contract type.
*/
getData(filename: string, host?: string): CodingContractData;
/**
* Get the number of attempt remaining.
* Get the number of attempts remaining.
* @remarks
* RAM cost: 2 GB
*
* Get the number of tries remaining on the contract before it self-destructs.
*
* @param filename - Filename of the contract.
* @param host - Host of the server containing the contract. Optional. Defaults to current server if not provided.
* @returns How many attempts are remaining for the contract;
* @param host - Hostname of the server containing the contract. Optional. Defaults to current server if not provided.
* @returns How many attempts are remaining for the contract.
*/
getNumTriesRemaining(filename: string, host?: string): number;
}
@ -5413,25 +5413,25 @@ export interface NS {
* ```ts
* // NS2:
* //Copies foo.lit from the helios server to the home computer:
* await ns.scp("foo.lit", "home", "helios" );
* ns.scp("foo.lit", "home", "helios" );
*
* //Tries to copy three files from rothman-uni to home computer:
* files = ["foo1.lit", "foo2.script", "foo3.script"];
* await ns.scp(files, "home", "rothman-uni");
* ns.scp(files, "home", "rothman-uni");
* ```
* @example
* ```ts
* //ns2, copies files from home to a target server
* const server = ns.args[0];
* const files = ["hack.js","weaken.js","grow.js"];
* await ns.scp(files, server, "home");
* ns.scp(files, server, "home");
* ```
* @param files - Filename or an array of filenames of script/literature files to copy.
* @param source - Host of the source server, which is the server from which the file will be copied. This argument is optional and if its omitted the source will be the current server.
* @param destination - Host of the destination server, which is the server to which the file will be copied.
* @returns True if the script/literature file is successfully copied over and false otherwise. If the files argument is an array then this function will return true if at least one of the files in the array is successfully copied.
* @param source - Host of the source server, which is the server from which the file will be copied. This argument is optional and if its omitted the source will be the current server.
* @returns True if the file is successfully copied over and false otherwise. If the files argument is an array then this function will return false if any of the operations failed.
*/
scp(files: string | string[], destination: string, source?: string): Promise<boolean>;
scp(files: string | string[], destination: string, source?: string): boolean;
/**
* List files on a server.
@ -5971,20 +5971,20 @@ export interface NS {
* @remarks
* RAM cost: 0 GB
*
* This function can be used to write data to a text file (.txt).
* This function can be used to write data to a text file (.txt) or a script (.js or .script).
*
* This function will write data to that text file. If the specified text file does not exist,
* This function will write data to that file. If the specified file does not exist,
* then it will be created. The third argument mode, defines how the data will be written to
* the text file. If *mode is set to w, then the data is written in write mode which means
* that it will overwrite all existing data on the text file. If mode is set to any other value
* the file. If *mode is set to w, then the data is written in write mode which means
* that it will overwrite all existing data on the file. If mode is set to any other value
* then the data will be written in append mode which means that the data will be added at the
* end of the text file.
* end of the file.
*
* @param handle - Filename of the text file that will be written to.
* @param filename - Name of the file to be written to.
* @param data - Data to write.
* @param mode - Defines the write mode. Only valid when writing to text files.
* @param mode - Defines the write mode.
*/
write(handle: string, data?: string[] | number | string, mode?: "w" | "a"): Promise<void>;
write(filename: string, data?: string[] | number | string, mode?: "w" | "a"): void;
/**
* Attempt to write to a port.
@ -6006,15 +6006,15 @@ export interface NS {
* @remarks
* RAM cost: 0 GB
*
* This function is used to read data from a text file (.txt).
* This function is used to read data from a text file (.txt) or script (.script, .js).
*
* This function will return the data in the specified text
* file. If the text file does not exist, an empty string will be returned.
* This function will return the data in the specified file.
* If the file does not exist, an empty string will be returned.
*
* @param handle - Filename to read from.
* @param filename - Name of the file to be read.
* @returns Data in the specified text file.
*/
read(handle: string): PortData;
read(filename: string): string;
/**
* Get a copy of the data from a port without popping it.
@ -6531,7 +6531,7 @@ export interface NS {
* // {"_":[],"delay":0,"server":"foodnstuff","exclude":[],"help":true}
* ```
*/
flags(schema: [string, string | number | boolean | string[]][]): { [key: string]: ScriptArg };
flags(schema: [string, string | number | boolean | string[]][]): { [key: string]: ScriptArg | string[] };
/**
* Share your computer with your factions.
@ -7358,5 +7358,5 @@ interface AutocompleteData {
servers: string[];
scripts: string[];
txts: string[];
flags(schema: [string, string | number | boolean | string[]][]): { [key: string]: ScriptArg };
flags(schema: [string, string | number | boolean | string[]][]): { [key: string]: ScriptArg | string[] };
}

@ -3,7 +3,6 @@ import React from "react";
import makeStyles from "@mui/styles/makeStyles";
import createStyles from "@mui/styles/createStyles";
import { Theme } from "@mui/material/styles";
import _ from "lodash";
// This particular eslint-disable is correct.
// In this super specific weird case we in fact do want a regex on an ANSII character.
@ -93,20 +92,9 @@ export const ANSIITypography = React.memo((props: IProps): React.ReactElement =>
}
return (
<Typography classes={{ root: lineClass(classes, props.color) }} paragraph={false}>
{parts.map((part, index) => {
const spanStyle = ansiCodeStyle(part.code);
if (!_.isEmpty(spanStyle)) {
// Only wrap parts with spans if the calculated spanStyle is non-empty...
return (
<Typography key={index} paragraph={false} component="span" sx={spanStyle}>
{part.text}
</Typography>
);
} else {
// ... otherwise yield the unmodified, unwrapped part.
return part.text;
}
})}
{parts.map((part) => (
<span style={ansiCodeStyle(part.code)}>{part.text}</span>
))}
</Typography>
);
});
@ -129,14 +117,14 @@ function ansiCodeStyle(code: string | null): Record<string, any> {
7: "#ffffff",
};
const COLOR_MAP_DARK: Record<number, string> = {
0: "#000000",
1: "#800000",
2: "#008000",
3: "#808000",
4: "#000080",
5: "#800080",
6: "#008080",
7: "#c0c0c0",
8: "#000000",
9: "#800000",
10: "#008000",
11: "#808000",
12: "#000080",
13: "#800080",
14: "#008080",
15: "#c0c0c0",
};
const ansi2rgb = (code: number): string => {
@ -170,13 +158,13 @@ function ansiCodeStyle(code: string | null): Record<string, any> {
return "initial";
};
type styleKey = "fontWeight" | "textDecoration" | "color" | "backgroundColor" | "display";
type styleKey = "fontWeight" | "textDecoration" | "color" | "backgroundColor" | "padding";
const style: {
fontWeight?: string;
textDecoration?: string;
color?: string;
backgroundColor?: string;
display?: string;
padding?: string;
} = {};
if (code === null || code === "0") {
@ -227,10 +215,10 @@ function ansiCodeStyle(code: string | null): Record<string, any> {
nextStyleKey = "backgroundColor";
}
});
// If a background color is set, render this as an inline block element (instead of inline)
// so that the background between lines (at least those that don't wrap) is uninterrupted.
if (style.backgroundColor !== undefined) {
style.display = "inline-block";
// If a background color is set, add slight padding to increase the background fill area.
// This was previously display:inline-block, but that has display errors when line breaks are used.
if (style.backgroundColor) {
style.padding = "0px 1px";
}
return style;
}