mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-19 06:03:50 +01:00
Improve wrong arg user message and add ui.windowSize
This commit is contained in:
parent
a2fad677d3
commit
c9a0998cc1
@ -67,11 +67,33 @@ export const helpers = {
|
|||||||
failOnHacknetServer,
|
failOnHacknetServer,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const userFriendlyString = (v: unknown): string => {
|
||||||
|
const clip = (s: string): string => {
|
||||||
|
if (s.length > 15) return s.slice(0, 12) + "...";
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
if (typeof v === "number") return String(v);
|
||||||
|
if (typeof v === "string") {
|
||||||
|
if (v === "") return "empty string";
|
||||||
|
return `'${clip(v)}'`;
|
||||||
|
}
|
||||||
|
const json = JSON.stringify(v);
|
||||||
|
if (!json) return "???";
|
||||||
|
return `'${clip(json)}'`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const debugType = (v: unknown): string => {
|
||||||
|
if (v === null) return `Is null.`;
|
||||||
|
if (v === undefined) return "Is undefined.";
|
||||||
|
if (typeof v === "function") return "Is a function.";
|
||||||
|
return `Is of type '${typeof v}', value: ${userFriendlyString(v)}`;
|
||||||
|
};
|
||||||
|
|
||||||
/** Convert a provided value v for argument argName to string. If it wasn't originally a string or number, throw. */
|
/** Convert a provided value v for argument argName to string. If it wasn't originally a string or number, throw. */
|
||||||
function string(ctx: NetscriptContext, argName: string, v: unknown): string {
|
function string(ctx: NetscriptContext, argName: string, v: unknown): string {
|
||||||
if (typeof v === "string") return v;
|
if (typeof v === "string") return v;
|
||||||
if (typeof v === "number") return v + ""; // cast to string;
|
if (typeof v === "number") return v + ""; // cast to string;
|
||||||
throw makeRuntimeErrorMsg(ctx, `'${argName}' should be a string.`);
|
throw makeRuntimeErrorMsg(ctx, `'${argName}' should be a string. ${debugType(v)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Convert provided value v for argument argName to number. Throw if could not convert to a non-NaN number. */
|
/** Convert provided value v for argument argName to number. Throw if could not convert to a non-NaN number. */
|
||||||
@ -83,7 +105,7 @@ function number(ctx: NetscriptContext, argName: string, v: unknown): number {
|
|||||||
if (isNaN(v)) throw makeRuntimeErrorMsg(ctx, `'${argName}' is NaN.`);
|
if (isNaN(v)) throw makeRuntimeErrorMsg(ctx, `'${argName}' is NaN.`);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
throw makeRuntimeErrorMsg(ctx, `'${argName}' should be a number.`);
|
throw makeRuntimeErrorMsg(ctx, `'${argName}' should be a number. ${debugType(v)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns args back if it is a ScriptArg[]. Throws an error if it is not. */
|
/** Returns args back if it is a ScriptArg[]. Throws an error if it is not. */
|
||||||
|
@ -335,6 +335,7 @@ const ui = {
|
|||||||
resetStyles: 0,
|
resetStyles: 0,
|
||||||
getGameInfo: 0,
|
getGameInfo: 0,
|
||||||
clearTerminal: 0,
|
clearTerminal: 0,
|
||||||
|
windowSize: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Grafting API
|
// Grafting API
|
||||||
@ -531,6 +532,8 @@ const SourceRamCosts = {
|
|||||||
mv: 0,
|
mv: 0,
|
||||||
tail: 0,
|
tail: 0,
|
||||||
toast: 0,
|
toast: 0,
|
||||||
|
moveTail: 0,
|
||||||
|
resizeTail: 0,
|
||||||
closeTail: 0,
|
closeTail: 0,
|
||||||
clearPort: 0,
|
clearPort: 0,
|
||||||
openDevMenu: 0,
|
openDevMenu: 0,
|
||||||
|
@ -38,7 +38,7 @@ import { WorkerScript } from "./Netscript/WorkerScript";
|
|||||||
import { helpers } from "./Netscript/NetscriptHelpers";
|
import { helpers } from "./Netscript/NetscriptHelpers";
|
||||||
import { numeralWrapper } from "./ui/numeralFormat";
|
import { numeralWrapper } from "./ui/numeralFormat";
|
||||||
import { convertTimeMsToTimeElapsedString } from "./utils/StringHelperFunctions";
|
import { convertTimeMsToTimeElapsedString } from "./utils/StringHelperFunctions";
|
||||||
import { LogBoxEvents, LogBoxCloserEvents } from "./ui/React/LogBoxManager";
|
import { LogBoxEvents, LogBoxCloserEvents, LogBoxPositionEvents, LogBoxSizeEvents } from "./ui/React/LogBoxManager";
|
||||||
import { arrayToString } from "./utils/helpers/arrayToString";
|
import { arrayToString } from "./utils/helpers/arrayToString";
|
||||||
import { isString } from "./utils/helpers/isString";
|
import { isString } from "./utils/helpers/isString";
|
||||||
import { NetscriptGang } from "./NetscriptFunctions/Gang";
|
import { NetscriptGang } from "./NetscriptFunctions/Gang";
|
||||||
@ -536,7 +536,22 @@ const base: InternalAPI<NS> = {
|
|||||||
|
|
||||||
LogBoxEvents.emit(runningScriptObj);
|
LogBoxEvents.emit(runningScriptObj);
|
||||||
},
|
},
|
||||||
|
moveTail:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_x: unknown, _y: unknown, _pid: unknown = ctx.workerScript.scriptRef.pid) => {
|
||||||
|
const x = helpers.number(ctx, "x", _x);
|
||||||
|
const y = helpers.number(ctx, "y", _y);
|
||||||
|
const pid = helpers.number(ctx, "pid", _pid);
|
||||||
|
LogBoxPositionEvents.emit({ pid, data: { x, y } });
|
||||||
|
},
|
||||||
|
resizeTail:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_w: unknown, _h: unknown, _pid: unknown = ctx.workerScript.scriptRef.pid) => {
|
||||||
|
const w = helpers.number(ctx, "w", _w);
|
||||||
|
const h = helpers.number(ctx, "h", _h);
|
||||||
|
const pid = helpers.number(ctx, "pid", _pid);
|
||||||
|
LogBoxSizeEvents.emit({ pid, data: { w, h } });
|
||||||
|
},
|
||||||
closeTail:
|
closeTail:
|
||||||
(ctx: NetscriptContext) =>
|
(ctx: NetscriptContext) =>
|
||||||
(_pid: unknown = ctx.workerScript.scriptRef.pid): void => {
|
(_pid: unknown = ctx.workerScript.scriptRef.pid): void => {
|
||||||
|
@ -16,6 +16,9 @@ import { helpers } from "../Netscript/NetscriptHelpers";
|
|||||||
|
|
||||||
export function NetscriptUserInterface(): InternalAPI<IUserInterface> {
|
export function NetscriptUserInterface(): InternalAPI<IUserInterface> {
|
||||||
return {
|
return {
|
||||||
|
windowSize: () => (): [number, number] => {
|
||||||
|
return [window.innerWidth, window.innerHeight];
|
||||||
|
},
|
||||||
getTheme: () => (): UserInterfaceTheme => {
|
getTheme: () => (): UserInterfaceTheme => {
|
||||||
return { ...Settings.theme };
|
return { ...Settings.theme };
|
||||||
},
|
},
|
||||||
|
35
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
35
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@ -4356,6 +4356,15 @@ interface Infiltration {
|
|||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
interface UserInterface {
|
interface UserInterface {
|
||||||
|
/**
|
||||||
|
* Get the current window size
|
||||||
|
* @remarks
|
||||||
|
* RAM cost: 0 GB
|
||||||
|
*
|
||||||
|
* @returns An array of 2 value containing the window width and height.
|
||||||
|
*/
|
||||||
|
windowSize(): [number, number];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current theme
|
* Get the current theme
|
||||||
* @remarks
|
* @remarks
|
||||||
@ -5014,6 +5023,32 @@ export interface NS {
|
|||||||
*/
|
*/
|
||||||
tail(fn?: FilenameOrPID, host?: string, ...args: (string | number | boolean)[]): void;
|
tail(fn?: FilenameOrPID, host?: string, ...args: (string | number | boolean)[]): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move a tail window
|
||||||
|
* @remarks
|
||||||
|
* RAM cost: 0 GB
|
||||||
|
*
|
||||||
|
* Moves a tail window. Coordinates are in screenspace pixels (top left is 0,0)
|
||||||
|
*
|
||||||
|
* @param x - x coordinate.
|
||||||
|
* @param y - y coordinate.
|
||||||
|
* @param pid - Optional. PID of the script having its tail moved. If omitted, the current script is used.
|
||||||
|
*/
|
||||||
|
moveTail(x: number, y: number, pid?: number): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize a tail window
|
||||||
|
* @remarks
|
||||||
|
* RAM cost: 0 GB
|
||||||
|
*
|
||||||
|
* Resize a tail window. Size are in pixel
|
||||||
|
*
|
||||||
|
* @param width - width of the window.
|
||||||
|
* @param height - height of the window.
|
||||||
|
* @param pid - Optional. PID of the script having its tail resized. If omitted, the current script is used.
|
||||||
|
*/
|
||||||
|
resizeTail(width: number, height: number, pid?: number): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the tail window of a script.
|
* Close the tail window of a script.
|
||||||
* @remarks
|
* @remarks
|
||||||
|
@ -7,7 +7,7 @@ import Box from "@mui/material/Box";
|
|||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import Paper from "@mui/material/Paper";
|
import Paper from "@mui/material/Paper";
|
||||||
import Draggable, { DraggableEvent } from "react-draggable";
|
import Draggable, { DraggableEvent } from "react-draggable";
|
||||||
import { ResizableBox } from "react-resizable";
|
import { ResizableBox, ResizeCallbackData } from "react-resizable";
|
||||||
import makeStyles from "@mui/styles/makeStyles";
|
import makeStyles from "@mui/styles/makeStyles";
|
||||||
import createStyles from "@mui/styles/createStyles";
|
import createStyles from "@mui/styles/createStyles";
|
||||||
import ArrowForwardIosIcon from "@mui/icons-material/ArrowForwardIos";
|
import ArrowForwardIosIcon from "@mui/icons-material/ArrowForwardIos";
|
||||||
@ -26,6 +26,25 @@ export const LogBoxEvents = new EventEmitter<[RunningScript]>();
|
|||||||
export const LogBoxCloserEvents = new EventEmitter<[number]>();
|
export const LogBoxCloserEvents = new EventEmitter<[number]>();
|
||||||
export const LogBoxClearEvents = new EventEmitter<[]>();
|
export const LogBoxClearEvents = new EventEmitter<[]>();
|
||||||
|
|
||||||
|
interface LogBoxUIEvent<T> {
|
||||||
|
pid: number;
|
||||||
|
data: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LogBoxPositionData {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LogBoxPositionEvents = new EventEmitter<[LogBoxUIEvent<LogBoxPositionData>]>();
|
||||||
|
|
||||||
|
interface LogBoxResizeData {
|
||||||
|
w: number;
|
||||||
|
h: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LogBoxSizeEvents = new EventEmitter<[LogBoxUIEvent<LogBoxResizeData>]>();
|
||||||
|
|
||||||
interface Log {
|
interface Log {
|
||||||
id: string;
|
id: string;
|
||||||
script: RunningScript;
|
script: RunningScript;
|
||||||
@ -121,11 +140,16 @@ function LogWindow(props: IProps): React.ReactElement {
|
|||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const container = useRef<HTMLDivElement>(null);
|
const container = useRef<HTMLDivElement>(null);
|
||||||
const setRerender = useState(false)[1];
|
const setRerender = useState(false)[1];
|
||||||
|
const [size, setSize] = useState<[number, number]>([500, 500]);
|
||||||
const [minimized, setMinimized] = useState(false);
|
const [minimized, setMinimized] = useState(false);
|
||||||
function rerender(): void {
|
function rerender(): void {
|
||||||
setRerender((old) => !old);
|
setRerender((old) => !old);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onResize = (e: React.SyntheticEvent, { size }: ResizeCallbackData) => {
|
||||||
|
setSize([size.width, size.height]);
|
||||||
|
};
|
||||||
|
|
||||||
// useEffect(
|
// useEffect(
|
||||||
// () =>
|
// () =>
|
||||||
// WorkerScriptStartStopEventEmitter.subscribe(() => {
|
// WorkerScriptStartStopEventEmitter.subscribe(() => {
|
||||||
@ -143,6 +167,38 @@ function LogWindow(props: IProps): React.ReactElement {
|
|||||||
// [],
|
// [],
|
||||||
// );
|
// );
|
||||||
|
|
||||||
|
const setPosition = ({ x, y }: LogBoxPositionData) => {
|
||||||
|
const node = rootRef?.current;
|
||||||
|
if (!node) return;
|
||||||
|
const state = node.state as { x: number; y: number };
|
||||||
|
console.log(`before ${state.x} ${state.y}`);
|
||||||
|
state.x = x;
|
||||||
|
state.y = y;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Listen to Logbox positioning events.
|
||||||
|
useEffect(
|
||||||
|
() =>
|
||||||
|
LogBoxPositionEvents.subscribe((e) => {
|
||||||
|
if (e.pid !== props.script.pid) return;
|
||||||
|
setPosition(e.data);
|
||||||
|
}),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Listen to Logbox resizing events.
|
||||||
|
useEffect(
|
||||||
|
() =>
|
||||||
|
LogBoxSizeEvents.subscribe((e) => {
|
||||||
|
if (e.pid !== props.script.pid) return;
|
||||||
|
setSize([e.data.w, e.data.h]);
|
||||||
|
}),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
// initial position if 40%/30%
|
||||||
|
useEffect(() => setPosition({ x: window.innerWidth * 0.4, y: window.innerHeight * 0.3 }), []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
updateLayer();
|
updateLayer();
|
||||||
const id = setInterval(rerender, 1000);
|
const id = setInterval(rerender, 1000);
|
||||||
@ -203,18 +259,18 @@ function LogWindow(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
// And trigger fakeDrag when the window is resized
|
// And trigger fakeDrag when the window is resized
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener("resize", onResize);
|
window.addEventListener("resize", onWindowResize);
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener("resize", onResize);
|
window.removeEventListener("resize", onWindowResize);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const onResize = debounce((): void => {
|
const onWindowResize = debounce((): void => {
|
||||||
const node = draggableRef?.current;
|
const node = draggableRef?.current;
|
||||||
if (!node) return;
|
if (!node) return;
|
||||||
|
|
||||||
if (!isOnScreen(node)) {
|
if (!isOnScreen(node)) {
|
||||||
resetPosition();
|
setPosition({ x: 0, y: 0 });
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
@ -224,15 +280,6 @@ function LogWindow(props: IProps): React.ReactElement {
|
|||||||
return !(bounds.right < 0 || bounds.bottom < 0 || bounds.left > innerWidth || bounds.top > outerWidth);
|
return !(bounds.right < 0 || bounds.bottom < 0 || bounds.left > innerWidth || bounds.top > outerWidth);
|
||||||
};
|
};
|
||||||
|
|
||||||
const resetPosition = (): void => {
|
|
||||||
const node = rootRef?.current;
|
|
||||||
if (!node) return;
|
|
||||||
const state = node.state as { x: number; y: number };
|
|
||||||
state.x = 0;
|
|
||||||
state.y = 0;
|
|
||||||
node.setState(state);
|
|
||||||
};
|
|
||||||
|
|
||||||
const boundToBody = (e: DraggableEvent): void | false => {
|
const boundToBody = (e: DraggableEvent): void | false => {
|
||||||
if (
|
if (
|
||||||
e instanceof MouseEvent &&
|
e instanceof MouseEvent &&
|
||||||
@ -251,8 +298,6 @@ function LogWindow(props: IProps): React.ReactElement {
|
|||||||
sx={{
|
sx={{
|
||||||
flexFlow: "column",
|
flexFlow: "column",
|
||||||
position: "fixed",
|
position: "fixed",
|
||||||
left: "40%",
|
|
||||||
top: "30%",
|
|
||||||
zIndex: 1400,
|
zIndex: 1400,
|
||||||
minWidth: `${minConstraints[0]}px`,
|
minWidth: `${minConstraints[0]}px`,
|
||||||
minHeight: `${minConstraints[1]}px`,
|
minHeight: `${minConstraints[1]}px`,
|
||||||
@ -270,8 +315,9 @@ function LogWindow(props: IProps): React.ReactElement {
|
|||||||
ref={container}
|
ref={container}
|
||||||
>
|
>
|
||||||
<ResizableBox
|
<ResizableBox
|
||||||
height={500}
|
height={size[0]}
|
||||||
width={500}
|
width={size[1]}
|
||||||
|
onResize={onResize}
|
||||||
minConstraints={minConstraints}
|
minConstraints={minConstraints}
|
||||||
handle={
|
handle={
|
||||||
<span
|
<span
|
||||||
@ -323,9 +369,7 @@ function LogWindow(props: IProps): React.ReactElement {
|
|||||||
<span style={{ display: "flex", flexDirection: "column" }}>
|
<span style={{ display: "flex", flexDirection: "column" }}>
|
||||||
{script.logs.map(
|
{script.logs.map(
|
||||||
(line: string, i: number): JSX.Element => (
|
(line: string, i: number): JSX.Element => (
|
||||||
<React.Fragment key={i}>
|
<ANSIITypography key={i} text={line} color={lineColor(line)} />
|
||||||
<ANSIITypography text={line} color={lineColor(line)} />
|
|
||||||
</React.Fragment>
|
|
||||||
),
|
),
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
|
Loading…
Reference in New Issue
Block a user