mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-18 12:15:44 +01:00
API: Add API break utilities, and add an API break for bladeburner.getCurrentAction (#1248)
This commit is contained in:
parent
9dc3b22919
commit
574c284321
@ -9,17 +9,15 @@ Get current action.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getCurrentAction(): BladeburnerCurAction;
|
||||
getCurrentAction(): BladeburnerCurAction | null;
|
||||
```
|
||||
**Returns:**
|
||||
|
||||
[BladeburnerCurAction](./bitburner.bladeburnercuraction.md)
|
||||
[BladeburnerCurAction](./bitburner.bladeburnercuraction.md) \| null
|
||||
|
||||
Object that represents the player’s current Bladeburner action.
|
||||
Object that represents the player’s current Bladeburner action, or null if no action is being performed.
|
||||
|
||||
## Remarks
|
||||
|
||||
RAM cost: 1 GB
|
||||
|
||||
Returns an object that represents the player’s current Bladeburner action. If the player is not performing an action, the function will return an object with the ‘type’ property set to “Idle”.
|
||||
|
||||
|
@ -101,8 +101,7 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
},
|
||||
getCurrentAction: (ctx) => () => {
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
// Temporary bad return type to not be an API break (idle should just return null)
|
||||
if (!bladeburner.action) return { type: "Idle", name: "Idle" };
|
||||
if (!bladeburner.action) return null;
|
||||
return { ...bladeburner.action };
|
||||
},
|
||||
getActionTime: (ctx) => (type, name) => {
|
||||
|
@ -42,6 +42,8 @@ import { SaveData } from "./types";
|
||||
import { SaveDataError, canUseBinaryFormat, decodeSaveData, encodeJsonSaveString } from "./utils/SaveDataUtils";
|
||||
import { isBinaryFormat } from "../electron/saveDataBinaryFormat";
|
||||
import { downloadContentAsFile } from "./utils/FileUtils";
|
||||
import { showAPIBreaks } from "./utils/APIBreaks/APIBreak";
|
||||
import { breakInfos261 } from "./utils/APIBreaks/2.6.1";
|
||||
import { handleGetSaveDataError } from "./Netscript/ErrorMessages";
|
||||
|
||||
/* SaveObject.js
|
||||
@ -735,6 +737,9 @@ Error: ${e}`);
|
||||
Object.assign(freshSaveData.stats, stats);
|
||||
loadGo(JSON.stringify(freshSaveData));
|
||||
}
|
||||
if (ver < 39) {
|
||||
showAPIBreaks("2.6.1", ...breakInfos261);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadGame(saveData: SaveData): Promise<boolean> {
|
||||
|
7
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
7
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@ -3070,12 +3070,9 @@ export interface Bladeburner {
|
||||
* @remarks
|
||||
* RAM cost: 1 GB
|
||||
*
|
||||
* Returns an object that represents the player’s current Bladeburner action.
|
||||
* If the player is not performing an action, the function will return an object with the ‘type’ property set to “Idle”.
|
||||
*
|
||||
* @returns Object that represents the player’s current Bladeburner action.
|
||||
* @returns Object that represents the player’s current Bladeburner action, or null if no action is being performed.
|
||||
*/
|
||||
getCurrentAction(): BladeburnerCurAction;
|
||||
getCurrentAction(): BladeburnerCurAction | null;
|
||||
|
||||
/**
|
||||
* Get the time to complete an action.
|
||||
|
29
src/utils/APIBreaks/2.6.1.ts
Normal file
29
src/utils/APIBreaks/2.6.1.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { APIBreakInfo } from "./APIBreak";
|
||||
|
||||
export const breakInfos261: APIBreakInfo[] = [
|
||||
{
|
||||
brokenFunctions: ["ns.bladeburner.getCurrentAction"],
|
||||
info:
|
||||
"ns.bladeburner.getCurrentAction:\n" +
|
||||
'When not performing a bladeburner action, previously returned {type: "Idle", name: ""}, now returns null.\n' +
|
||||
"Because of this change, the null case now needs to be dealt with prior to accessing properties on the return of getCurrentAction, including destructuring.\n" +
|
||||
"Additionally, any existing code for filtering out the Idle case will need to be adjusted.\n\n" +
|
||||
"See https://github.com/bitburner-official/bitburner-src/issues/1249 or PR https://github.com/bitburner-official/bitburner-src/pull/1248 for more details.",
|
||||
},
|
||||
{
|
||||
brokenFunctions: [
|
||||
"ns.bladeburner.getActionCountRemaining",
|
||||
"ns.bladeburner.getActionEstimatedSuccessChance",
|
||||
"ns.bladeburner.getActionTime",
|
||||
],
|
||||
info:
|
||||
"ns.bladeburner.getActionCountRemaining:\n" +
|
||||
'Previously returned -1 when called with type "Idle" and name "". This is no longer valid usage and will result in an error.\n\n' +
|
||||
"ns.bladeburner.getActionEstimatedSuccessChance:\n" +
|
||||
'Previously returned [-1, -1] when called with type "Idle" and name "". This is no longer valid usage and will result in an error.\n\n' +
|
||||
"ns.bladeburner.getActionTime:\n" +
|
||||
'Previously returned -1 when called with type "Idle" and name "". This is no longer valid usage and will result in an error.\n\n' +
|
||||
"See the related changes for ns.bladeburner.getCurrentAction, which were shown earlier in these API break details.\n" +
|
||||
"In most cases, the fixes for ns.bladeburner.getCurrentAction will fix this group of isses as well.",
|
||||
},
|
||||
];
|
91
src/utils/APIBreaks/APIBreak.ts
Normal file
91
src/utils/APIBreaks/APIBreak.ts
Normal file
@ -0,0 +1,91 @@
|
||||
// General reusable tools for API breaks
|
||||
|
||||
import type { ScriptFilePath } from "../../Paths/ScriptFilePath";
|
||||
import type { Script } from "../../Script/Script";
|
||||
import { Player } from "@player";
|
||||
import { GetAllServers } from "../../Server/AllServers";
|
||||
import { resolveTextFilePath } from "../../Paths/TextFilePath";
|
||||
import { dialogBoxCreate as dialogBoxCreateOriginal } from "../../ui/React/DialogBox";
|
||||
import { Terminal } from "../../Terminal";
|
||||
|
||||
// Temporary until fixing alerts manager to store alerts outside of react scope
|
||||
const dialogBoxCreate = (text: string) => setTimeout(() => dialogBoxCreateOriginal(text), 2000);
|
||||
|
||||
/** For a single server, map of script filepath to an array of line numbers where impacted functions were detected */
|
||||
type ScriptImpactMap = Map<ScriptFilePath, number[]>;
|
||||
|
||||
/** For an overall API break, map of server hostnames to an array of impacted scripts */
|
||||
type ImpactMap = Map<string, ScriptImpactMap>;
|
||||
|
||||
export interface APIBreakInfo {
|
||||
/** The API functions impacted by the API break */
|
||||
brokenFunctions: string[];
|
||||
/** Info that should be shown to the player, alongside the list of impacted scripts */
|
||||
info: string;
|
||||
}
|
||||
|
||||
function getImpactedLines(script: Script, brokenFunctions: string[]): number[] | null {
|
||||
const impactedLines: number[] = [];
|
||||
script.content.split("\n").forEach((line, i) => {
|
||||
for (const brokenFunction of brokenFunctions) {
|
||||
if (line.includes(brokenFunction)) return impactedLines.push(i + 1);
|
||||
}
|
||||
});
|
||||
return impactedLines.length ? impactedLines : null;
|
||||
}
|
||||
|
||||
/** Returns a map keyed by all ser */
|
||||
function getImpactMap(brokenFunctions: string[]): ImpactMap | null {
|
||||
const returnMap = new Map<string, ScriptImpactMap>();
|
||||
for (const server of GetAllServers()) {
|
||||
const impactedScripts = new Map<ScriptFilePath, number[]>();
|
||||
for (const [filename, script] of server.scripts) {
|
||||
const impactedLines = getImpactedLines(script, brokenFunctions);
|
||||
if (impactedLines) impactedScripts.set(filename, impactedLines);
|
||||
}
|
||||
if (impactedScripts.size) returnMap.set(server.hostname, impactedScripts);
|
||||
}
|
||||
return returnMap.size ? returnMap : null;
|
||||
}
|
||||
|
||||
/** Show the player a dialog for their API breaks, and save an info file for the player to review later */
|
||||
export function showAPIBreaks(version: string, ...breakInfos: APIBreakInfo[]) {
|
||||
const details = [];
|
||||
for (const breakInfo of breakInfos) {
|
||||
const impactMap = getImpactMap(breakInfo.brokenFunctions);
|
||||
if (!impactMap) continue;
|
||||
details.push(
|
||||
breakInfo.info +
|
||||
`\n\nUsage of the following functions may have been affected:\n${breakInfo.brokenFunctions.join("\n")}\n\n` +
|
||||
[...impactMap]
|
||||
.map(
|
||||
([hostname, scriptImpactMap]) =>
|
||||
`Potentially affected files on server ${hostname} (with line numbers):\n` +
|
||||
[...scriptImpactMap]
|
||||
.map(
|
||||
([filename, lineNumbers]) =>
|
||||
`${filename}: (Line number${lineNumbers.length > 1 ? "s" : ""}: ${lineNumbers.join(", ")})`,
|
||||
)
|
||||
.join("\n"),
|
||||
)
|
||||
.join("\n\n"),
|
||||
);
|
||||
}
|
||||
if (!details.length) return;
|
||||
const textFileName = resolveTextFilePath(`APIBreakInfo-${version}.txt`);
|
||||
if (!textFileName) throw new Error("Version string created an invalid API break file name");
|
||||
Player.getHomeComputer().writeToTextFile(
|
||||
textFileName,
|
||||
`API BREAK INFO FOR ${version}\n\n${details.join("\n\n\n\n")}`,
|
||||
);
|
||||
Terminal.warn(`AN API BREAK FROM VERSION ${version} MAY HAVE AFFECTED SOME OF YOUR SCRIPTS.`);
|
||||
Terminal.warn(`INFORMATION ABOUT THIS POTENTIAL IMPACT HAS BEEN LOGGED IN ${textFileName} ON YOUR HOME COMPUTER.`);
|
||||
dialogBoxCreate(
|
||||
`SOME OF YOUR SCRIPTS HAVE POTENTIALLY BEEN IMPACTED BY AN API BREAK, DUE TO CHANGES IN VERSION ${version}\n\n` +
|
||||
"The following dialog boxes will provide details of the potential impact to your scripts.\n" +
|
||||
`A file with these details has also been saved on your home computer under filename ${textFileName}.`,
|
||||
);
|
||||
details.forEach((detail, i) => {
|
||||
dialogBoxCreate(`API BREAK VERSION ${version} DETAILS ${i + 1} of ${details.length}\n\n${detail}`);
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue
Block a user