mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-29 20:37:05 +02:00
FILES: Path rework & typesafety (#479)
* Added new types for various file paths, all in the Paths folder. * TypeSafety and other helper functions related to these types * Added basic globbing support with * and ?. Currently only implemented for Script/Text, on nano and download terminal commands * Enforcing the new types throughout the codebase, plus whatever rewrites happened along the way * Server.textFiles is now a map * TextFile no longer uses a fn property, now it is filename * Added a shared ContentFile interface for shared functionality between TextFile and Script. * related to ContentFile change above, the player is now allowed to move a text file to a script file and vice versa. * File paths no longer conditionally start with slashes, and all directory names other than root have ending slashes. The player is still able to provide paths starting with / but this now indicates that the player is specifying an absolute path instead of one relative to root. * Singularized the MessageFilename and LiteratureName enums * Because they now only accept correct types, server.writeToXFile functions now always succeed (the only reasons they could fail before were invalid filepath). * Fix several issues with tab completion, which included pretty much a complete rewrite * Changed the autocomplete display options so there's less chance it clips outside the display area. * Turned CompletedProgramName into an enum. * Got rid of programsMetadata, and programs and DarkWebItems are now initialized immediately instead of relying on initializers called from the engine. * For any executable (program, cct, or script file) pathing can be used directly to execute without using the run command (previously the command had to start with ./ and it wasn't actually using pathing).
This commit is contained in:
+20
-59
@@ -1,29 +1,27 @@
|
||||
import { dialogBoxCreate } from "./ui/React/DialogBox";
|
||||
import { BaseServer } from "./Server/BaseServer";
|
||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, constructorsForReviver } from "./utils/JSONReviver";
|
||||
import { removeLeadingSlash, isInRootDirectory } from "./Terminal/DirectoryHelpers";
|
||||
import { TextFilePath } from "./Paths/TextFilePath";
|
||||
import { ContentFile } from "./Paths/ContentFile";
|
||||
|
||||
/** Represents a plain text file that is typically stored on a server. */
|
||||
export class TextFile {
|
||||
export class TextFile implements ContentFile {
|
||||
/** The full file name. */
|
||||
fn: string;
|
||||
filename: TextFilePath;
|
||||
|
||||
/** The content of the file. */
|
||||
text: string;
|
||||
|
||||
//TODO 2.3: Why are we using getter/setter for fn as filename? Rename parameter as more-readable "filename"
|
||||
/** The full file name. */
|
||||
get filename(): string {
|
||||
return this.fn;
|
||||
// Shared interface on Script and TextFile for accessing content
|
||||
get content() {
|
||||
return this.text;
|
||||
}
|
||||
set content(text: string) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
/** The full file name. */
|
||||
set filename(value: string) {
|
||||
this.fn = value;
|
||||
}
|
||||
|
||||
constructor(fn = "", txt = "") {
|
||||
this.fn = (fn.endsWith(".txt") ? fn : `${fn}.txt`).replace(/\s+/g, "");
|
||||
constructor(filename = "default.txt" as TextFilePath, txt = "") {
|
||||
this.filename = filename;
|
||||
this.text = txt;
|
||||
}
|
||||
|
||||
@@ -38,7 +36,7 @@ export class TextFile {
|
||||
const a: HTMLAnchorElement = document.createElement("a");
|
||||
const url: string = URL.createObjectURL(file);
|
||||
a.href = url;
|
||||
a.download = this.fn;
|
||||
a.download = this.filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
setTimeout(() => {
|
||||
@@ -54,7 +52,7 @@ export class TextFile {
|
||||
|
||||
/** Shows the content to the user via the game's dialog box. */
|
||||
show(): void {
|
||||
dialogBoxCreate(`${this.fn}\n\n${this.text}`);
|
||||
dialogBoxCreate(`${this.filename}\n\n${this.text}`);
|
||||
}
|
||||
|
||||
/** Serialize the current file to a JSON save state. */
|
||||
@@ -67,6 +65,12 @@ export class TextFile {
|
||||
this.text = txt;
|
||||
}
|
||||
|
||||
deleteFromServer(server: BaseServer): boolean {
|
||||
if (!server.textFiles.has(this.filename)) return false;
|
||||
server.textFiles.delete(this.filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Initializes a TextFile from a JSON save state. */
|
||||
static fromJSON(value: IReviverValue): TextFile {
|
||||
return Generic_fromJSON(TextFile, value.data);
|
||||
@@ -74,46 +78,3 @@ export class TextFile {
|
||||
}
|
||||
|
||||
constructorsForReviver.TextFile = TextFile;
|
||||
|
||||
/**
|
||||
* Retrieve the file object for the filename on the specified server.
|
||||
* @param fn The file name to look for
|
||||
* @param server The server object to look in
|
||||
* @returns The file object, or null if it couldn't find it.
|
||||
*/
|
||||
export function getTextFile(fn: string, server: BaseServer): TextFile | null {
|
||||
let filename: string = !fn.endsWith(".txt") ? `${fn}.txt` : fn;
|
||||
|
||||
if (isInRootDirectory(filename)) {
|
||||
filename = removeLeadingSlash(filename);
|
||||
}
|
||||
|
||||
for (const file of server.textFiles) {
|
||||
if (file.fn === filename) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a TextFile on the target server.
|
||||
* @param fn The file name to create.
|
||||
* @param txt The contents of the file.
|
||||
* @param server The server that the file should be created on.
|
||||
* @returns The instance of the file.
|
||||
*/
|
||||
export function createTextFile(fn: string, txt: string, server: BaseServer): TextFile | undefined {
|
||||
if (getTextFile(fn, server) !== null) {
|
||||
// This should probably be a `throw`...
|
||||
/* tslint:disable-next-line:no-console */
|
||||
console.error(`A file named "${fn}" already exists on server ${server.hostname}.`);
|
||||
|
||||
return undefined;
|
||||
}
|
||||
const file: TextFile = new TextFile(fn, txt);
|
||||
server.textFiles.push(file);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user