mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-08 16:53:54 +01:00
UI: Better support for custom player React content (#513)
This commit is contained in:
parent
0d55b957f1
commit
87f2ae459d
14
package-lock.json
generated
14
package-lock.json
generated
@ -61,7 +61,7 @@
|
|||||||
"@types/numeral": "^2.0.2",
|
"@types/numeral": "^2.0.2",
|
||||||
"@types/react": "^17.0.52",
|
"@types/react": "^17.0.52",
|
||||||
"@types/react-beautiful-dnd": "^13.1.3",
|
"@types/react-beautiful-dnd": "^13.1.3",
|
||||||
"@types/react-dom": "^17.0.18",
|
"@types/react-dom": "^17.0.20",
|
||||||
"@types/react-resizable": "^3.0.3",
|
"@types/react-resizable": "^3.0.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.48.0",
|
"@typescript-eslint/eslint-plugin": "^5.48.0",
|
||||||
"@typescript-eslint/parser": "^5.48.0",
|
"@typescript-eslint/parser": "^5.48.0",
|
||||||
@ -4472,9 +4472,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/react-dom": {
|
"node_modules/@types/react-dom": {
|
||||||
"version": "17.0.18",
|
"version": "17.0.20",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.18.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.20.tgz",
|
||||||
"integrity": "sha512-rLVtIfbwyur2iFKykP2w0pl/1unw26b5td16d5xMgp7/yjTHomkyxPYChFoCr/FtEX1lN9wY6lFj1qvKdS5kDw==",
|
"integrity": "sha512-4pzIjSxDueZZ90F52mU3aPoogkHIoSIDG+oQ+wQK7Cy2B9S+MvOqY0uEA/qawKz381qrEDkvpwyt8Bm31I8sbA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/react": "^17"
|
"@types/react": "^17"
|
||||||
@ -18963,9 +18963,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@types/react-dom": {
|
"@types/react-dom": {
|
||||||
"version": "17.0.18",
|
"version": "17.0.20",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.18.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.20.tgz",
|
||||||
"integrity": "sha512-rLVtIfbwyur2iFKykP2w0pl/1unw26b5td16d5xMgp7/yjTHomkyxPYChFoCr/FtEX1lN9wY6lFj1qvKdS5kDw==",
|
"integrity": "sha512-4pzIjSxDueZZ90F52mU3aPoogkHIoSIDG+oQ+wQK7Cy2B9S+MvOqY0uEA/qawKz381qrEDkvpwyt8Bm31I8sbA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/react": "^17"
|
"@types/react": "^17"
|
||||||
|
@ -62,7 +62,7 @@
|
|||||||
"@types/numeral": "^2.0.2",
|
"@types/numeral": "^2.0.2",
|
||||||
"@types/react": "^17.0.52",
|
"@types/react": "^17.0.52",
|
||||||
"@types/react-beautiful-dnd": "^13.1.3",
|
"@types/react-beautiful-dnd": "^13.1.3",
|
||||||
"@types/react-dom": "^17.0.18",
|
"@types/react-dom": "^17.0.20",
|
||||||
"@types/react-resizable": "^3.0.3",
|
"@types/react-resizable": "^3.0.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.48.0",
|
"@typescript-eslint/eslint-plugin": "^5.48.0",
|
||||||
"@typescript-eslint/parser": "^5.48.0",
|
"@typescript-eslint/parser": "^5.48.0",
|
||||||
|
@ -548,7 +548,7 @@ export const RamCosts: RamCostTree<NSFull> = {
|
|||||||
alterReality: 0,
|
alterReality: 0,
|
||||||
rainbow: 0,
|
rainbow: 0,
|
||||||
heart: { break: 0 },
|
heart: { break: 0 },
|
||||||
iKnowWhatImDoing: 0,
|
tprintRaw: 0,
|
||||||
printRaw: 0,
|
printRaw: 0,
|
||||||
|
|
||||||
formulas: {
|
formulas: {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type React from "react";
|
import React from "react";
|
||||||
import { Player } from "../Player";
|
import { Player } from "../Player";
|
||||||
import { Exploit } from "../Exploits/Exploit";
|
import { Exploit } from "../Exploits/Exploit";
|
||||||
import * as bcrypt from "bcryptjs";
|
import * as bcrypt from "bcryptjs";
|
||||||
@ -7,6 +7,10 @@ import { InternalAPI } from "../Netscript/APIWrapper";
|
|||||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||||
import { Terminal } from "../Terminal";
|
import { Terminal } from "../Terminal";
|
||||||
import { RamCostConstants } from "../Netscript/RamCostGenerator";
|
import { RamCostConstants } from "../Netscript/RamCostGenerator";
|
||||||
|
import { CustomBoundary } from "../ui/Components/CustomBoundary";
|
||||||
|
|
||||||
|
// Incrementing value for custom element keys
|
||||||
|
let customElementKey = 0;
|
||||||
|
|
||||||
export interface INetscriptExtra {
|
export interface INetscriptExtra {
|
||||||
heart: {
|
heart: {
|
||||||
@ -17,7 +21,7 @@ export interface INetscriptExtra {
|
|||||||
bypass(doc: Document): void;
|
bypass(doc: Document): void;
|
||||||
alterReality(): void;
|
alterReality(): void;
|
||||||
rainbow(guess: string): void;
|
rainbow(guess: string): void;
|
||||||
iKnowWhatImDoing(): void;
|
tprintRaw(value: React.ReactNode): void;
|
||||||
printRaw(value: React.ReactNode): void;
|
printRaw(value: React.ReactNode): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,14 +71,15 @@ export function NetscriptExtra(): InternalAPI<INetscriptExtra> {
|
|||||||
Player.giveExploit(Exploit.INeedARainbow);
|
Player.giveExploit(Exploit.INeedARainbow);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
iKnowWhatImDoing: (ctx) => () => {
|
tprintRaw: () => (value) => {
|
||||||
helpers.log(ctx, () => "Unlocking unsupported feature: window.tprintRaw");
|
Terminal.printRaw(
|
||||||
// @ts-expect-error window has no tprintRaw property defined
|
<CustomBoundary key={`PlayerContent${customElementKey++}`} children={value as React.ReactNode} />,
|
||||||
window.tprintRaw = Terminal.printRaw.bind(Terminal);
|
);
|
||||||
},
|
},
|
||||||
printRaw: (ctx) => (value) => {
|
printRaw: (ctx) => (value) => {
|
||||||
// Using this voids the warranty on your tail log
|
ctx.workerScript.print(
|
||||||
ctx.workerScript.print(value as React.ReactNode);
|
<CustomBoundary key={`PlayerContent${customElementKey++}`} children={value as React.ReactNode} />,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
31
src/ui/Components/CustomBoundary.tsx
Normal file
31
src/ui/Components/CustomBoundary.tsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import React from "react";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
|
||||||
|
interface CustomBoundaryProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
interface CustomBoundaryState {
|
||||||
|
error?: Error;
|
||||||
|
}
|
||||||
|
/** Error boundary for custom content printed by the player using printRaw-like functions.
|
||||||
|
* Error boundaries are required to be class components due to no hook equivalent to componentDidCatch. */
|
||||||
|
export class CustomBoundary extends React.Component<CustomBoundaryProps, CustomBoundaryState> {
|
||||||
|
state: CustomBoundaryState;
|
||||||
|
constructor(props: CustomBoundaryProps) {
|
||||||
|
super(props);
|
||||||
|
this.state = { error: undefined };
|
||||||
|
}
|
||||||
|
componentDidCatch(error: Error): void {
|
||||||
|
this.setState({ error });
|
||||||
|
console.warn("Error in custom react content:");
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
render(): React.ReactNode {
|
||||||
|
if (this.state.error) {
|
||||||
|
// Typography is used because there are no default page styles.
|
||||||
|
// Span is used because it does not conflict with the DOM validation nesting (default Typography element of p is invalid at this location in dom tree)
|
||||||
|
return <Typography component={"span"}>Error in custom react content. See console for details.</Typography>;
|
||||||
|
}
|
||||||
|
return <Typography component={"span"}>{this.props.children}</Typography>;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user