mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-23 06:32:26 +01:00
Merge branch 'dev' into feat/open-multiple-files-from-cli
This commit is contained in:
commit
c1c7131545
@ -66,6 +66,7 @@
|
||||
| [StockOrder](./bitburner.stockorder.md) | Return value of [getOrders](./bitburner.tix.getorders.md) |
|
||||
| [StockOrderObject](./bitburner.stockorderobject.md) | Value in map of [StockOrder](./bitburner.stockorder.md) |
|
||||
| [TIX](./bitburner.tix.md) | Stock market API |
|
||||
| [UserInterface](./bitburner.userinterface.md) | User Interface API. |
|
||||
| [Warehouse](./bitburner.warehouse.md) | Warehouse for a division in a city |
|
||||
| [WarehouseAPI](./bitburner.warehouseapi.md) | Corporation Warehouse API |
|
||||
|
||||
|
@ -51,6 +51,7 @@ export async function main(ns) {
|
||||
| [sleeve](./bitburner.ns.sleeve.md) | [Sleeve](./bitburner.sleeve.md) | Namespace for sleeve functions. |
|
||||
| [stanek](./bitburner.ns.stanek.md) | [Stanek](./bitburner.stanek.md) | Namespace for stanek functions. RAM cost: 0 GB |
|
||||
| [stock](./bitburner.ns.stock.md) | [TIX](./bitburner.tix.md) | Namespace for stock functions. |
|
||||
| [ui](./bitburner.ns.ui.md) | [UserInterface](./bitburner.userinterface.md) | Namespace for user interface functions. RAM cost: 0 GB |
|
||||
|
||||
## Methods
|
||||
|
||||
|
13
markdown/bitburner.ns.ui.md
Normal file
13
markdown/bitburner.ns.ui.md
Normal file
@ -0,0 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [NS](./bitburner.ns.md) > [ui](./bitburner.ns.ui.md)
|
||||
|
||||
## NS.ui property
|
||||
|
||||
Namespace for user interface functions. RAM cost: 0 GB
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
readonly ui: UserInterface;
|
||||
```
|
23
markdown/bitburner.userinterface.gettheme.md
Normal file
23
markdown/bitburner.userinterface.gettheme.md
Normal file
@ -0,0 +1,23 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [UserInterface](./bitburner.userinterface.md) > [getTheme](./bitburner.userinterface.gettheme.md)
|
||||
|
||||
## UserInterface.getTheme() method
|
||||
|
||||
Get the current theme
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
getTheme(): UserInterfaceTheme;
|
||||
```
|
||||
<b>Returns:</b>
|
||||
|
||||
UserInterfaceTheme
|
||||
|
||||
An object containing the theme's colors
|
||||
|
||||
## Remarks
|
||||
|
||||
RAM cost: cost: 0 GB
|
||||
|
20
markdown/bitburner.userinterface.md
Normal file
20
markdown/bitburner.userinterface.md
Normal file
@ -0,0 +1,20 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [UserInterface](./bitburner.userinterface.md)
|
||||
|
||||
## UserInterface interface
|
||||
|
||||
User Interface API.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
interface UserInterface
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
| Method | Description |
|
||||
| --- | --- |
|
||||
| [getTheme()](./bitburner.userinterface.gettheme.md) | Get the current theme |
|
||||
|
@ -34,6 +34,12 @@ import { getTimestamp } from "../utils/helpers/getTimestamp";
|
||||
import { joinFaction } from "../Faction/FactionHelpers";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
|
||||
interface BlackOpsAttempt {
|
||||
error?: string;
|
||||
isAvailable?: boolean;
|
||||
action?: BlackOperation;
|
||||
}
|
||||
|
||||
export class Bladeburner implements IBladeburner {
|
||||
numHosp = 0;
|
||||
moneyLost = 0;
|
||||
@ -113,6 +119,44 @@ export class Bladeburner implements IBladeburner {
|
||||
return Math.min(1, this.stamina / (0.5 * this.maxStamina));
|
||||
}
|
||||
|
||||
|
||||
canAttemptBlackOp(actionId: IActionIdentifier): BlackOpsAttempt {
|
||||
// Safety measure - don't repeat BlackOps that are already done
|
||||
if (this.blackops[actionId.name] != null) {
|
||||
return { error: "Tried to start a Black Operation that had already been completed" }
|
||||
}
|
||||
|
||||
const action = this.getActionObject(actionId);
|
||||
if (!(action instanceof BlackOperation)) throw new Error(`Action should be BlackOperation but isn't`);
|
||||
if (action == null) throw new Error("Failed to get BlackOperation object for: " + actionId.name);
|
||||
|
||||
if (action.reqdRank > this.rank) {
|
||||
return { error: "Tried to start a Black Operation without the rank requirement" };
|
||||
}
|
||||
|
||||
// Can't start a BlackOp if you haven't done the one before it
|
||||
const blackops = [];
|
||||
for (const nm in BlackOperations) {
|
||||
if (BlackOperations.hasOwnProperty(nm)) {
|
||||
blackops.push(nm);
|
||||
}
|
||||
}
|
||||
blackops.sort(function (a, b) {
|
||||
return BlackOperations[a].reqdRank - BlackOperations[b].reqdRank; // Sort black ops in intended order
|
||||
});
|
||||
|
||||
const i = blackops.indexOf(actionId.name);
|
||||
if (i === -1) {
|
||||
return { error: `Invalid Black Op: '${name}'` };
|
||||
}
|
||||
|
||||
if (i > 0 && this.blackops[blackops[i - 1]] == null) {
|
||||
return { error: `Preceding Black Op must be completed before starting '${actionId.name}'.` }
|
||||
}
|
||||
|
||||
return { isAvailable: true, action }
|
||||
}
|
||||
|
||||
startAction(player: IPlayer, actionId: IActionIdentifier): void {
|
||||
if (actionId == null) return;
|
||||
this.action = actionId;
|
||||
@ -156,18 +200,13 @@ export class Bladeburner implements IBladeburner {
|
||||
case ActionTypes["BlackOp"]:
|
||||
case ActionTypes["BlackOperation"]: {
|
||||
try {
|
||||
// Safety measure - don't repeat BlackOps that are already done
|
||||
if (this.blackops[actionId.name] != null) {
|
||||
const testBlackOp = this.canAttemptBlackOp(actionId);
|
||||
if (!testBlackOp.isAvailable) {
|
||||
this.resetAction();
|
||||
this.log("Error: Tried to start a Black Operation that had already been completed");
|
||||
this.log(`Error: ${testBlackOp.error}`);
|
||||
break;
|
||||
}
|
||||
|
||||
const action = this.getActionObject(actionId);
|
||||
if (action == null) {
|
||||
throw new Error("Failed to get BlackOperation object for: " + actionId.name);
|
||||
}
|
||||
this.actionTimeToComplete = action.getActionTime(this);
|
||||
this.actionTimeToComplete = testBlackOp.action.getActionTime(this);
|
||||
} catch (e: any) {
|
||||
exceptionAlert(e);
|
||||
}
|
||||
@ -502,6 +541,7 @@ export class Bladeburner implements IBladeburner {
|
||||
const skill = Skills[skillName];
|
||||
if (skill == null || !(skill instanceof Skill)) {
|
||||
this.postToConsole("Invalid skill name (Note that it is case-sensitive): " + skillName);
|
||||
break;
|
||||
}
|
||||
if (args[1].toLowerCase() === "list") {
|
||||
let level = 0;
|
||||
@ -515,7 +555,11 @@ export class Bladeburner implements IBladeburner {
|
||||
currentLevel = this.skills[skillName];
|
||||
}
|
||||
const pointCost = skill.calculateCost(currentLevel);
|
||||
if (this.skillPoints >= pointCost) {
|
||||
if (skill.maxLvl !== 0 && currentLevel >= skill.maxLvl) {
|
||||
this.postToConsole(
|
||||
`This skill ${skill.name} is already at max level (${currentLevel}/${skill.maxLvl}).`,
|
||||
);
|
||||
} else if (this.skillPoints >= pointCost) {
|
||||
this.skillPoints -= pointCost;
|
||||
this.upgradeSkill(skill);
|
||||
this.log(skill.name + " upgraded to Level " + this.skills[skillName]);
|
||||
@ -2032,44 +2076,9 @@ export class Bladeburner implements IBladeburner {
|
||||
|
||||
// Special logic for Black Ops
|
||||
if (actionId.type === ActionTypes["BlackOp"]) {
|
||||
// Can't start a BlackOp if you don't have the required rank
|
||||
const action = this.getActionObject(actionId);
|
||||
if (action == null) throw new Error(`Action not found ${actionId.type}, ${actionId.name}`);
|
||||
if (!(action instanceof BlackOperation)) throw new Error(`Action should be BlackOperation but isn't`);
|
||||
//const blackOp = (action as BlackOperation);
|
||||
if (action.reqdRank > this.rank) {
|
||||
workerScript.log("bladeburner.startAction", () => `Insufficient rank to start Black Op '${actionId.name}'.`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Can't start a BlackOp if its already been done
|
||||
if (this.blackops[actionId.name] != null) {
|
||||
workerScript.log("bladeburner.startAction", () => `Black Op ${actionId.name} has already been completed.`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Can't start a BlackOp if you haven't done the one before it
|
||||
const blackops = [];
|
||||
for (const nm in BlackOperations) {
|
||||
if (BlackOperations.hasOwnProperty(nm)) {
|
||||
blackops.push(nm);
|
||||
}
|
||||
}
|
||||
blackops.sort(function (a, b) {
|
||||
return BlackOperations[a].reqdRank - BlackOperations[b].reqdRank; // Sort black ops in intended order
|
||||
});
|
||||
|
||||
const i = blackops.indexOf(actionId.name);
|
||||
if (i === -1) {
|
||||
workerScript.log("bladeburner.startAction", () => `Invalid Black Op: '${name}'`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (i > 0 && this.blackops[blackops[i - 1]] == null) {
|
||||
workerScript.log(
|
||||
"bladeburner.startAction",
|
||||
() => `Preceding Black Op must be completed before starting '${actionId.name}'.`,
|
||||
);
|
||||
const canRunOp = this.canAttemptBlackOp(actionId);
|
||||
if (!canRunOp.isAvailable) {
|
||||
workerScript.log("bladeburner.startAction", () => canRunOp.error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,6 @@ interface IProps {
|
||||
|
||||
export function Console(props: IProps): React.ReactElement {
|
||||
const classes = useStyles();
|
||||
const scrollHook = useRef<HTMLDivElement>(null);
|
||||
const [command, setCommand] = useState("");
|
||||
const setRerender = useState(false)[1];
|
||||
|
||||
@ -64,22 +63,14 @@ export function Console(props: IProps): React.ReactElement {
|
||||
|
||||
const [consoleHistoryIndex, setConsoleHistoryIndex] = useState(props.bladeburner.consoleHistory.length);
|
||||
|
||||
// TODO: Figure out how to actually make the scrolling work correctly.
|
||||
function scrollToBottom(): void {
|
||||
if (!scrollHook.current) return;
|
||||
scrollHook.current.scrollTop = scrollHook.current.scrollHeight;
|
||||
}
|
||||
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(rerender, 1000);
|
||||
const id2 = setInterval(scrollToBottom, 100);
|
||||
return () => {
|
||||
clearInterval(id);
|
||||
clearInterval(id2);
|
||||
};
|
||||
}, []);
|
||||
|
||||
@ -113,6 +104,7 @@ export function Console(props: IProps): React.ReactElement {
|
||||
setConsoleHistoryIndex(i);
|
||||
const prevCommand = consoleHistory[i];
|
||||
event.currentTarget.value = prevCommand;
|
||||
setCommand(prevCommand);
|
||||
}
|
||||
|
||||
if (event.keyCode === 40) {
|
||||
@ -134,39 +126,68 @@ export function Console(props: IProps): React.ReactElement {
|
||||
setConsoleHistoryIndex(consoleHistoryIndex + 1);
|
||||
const prevCommand = consoleHistory[consoleHistoryIndex + 1];
|
||||
event.currentTarget.value = prevCommand;
|
||||
setCommand(prevCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Box height={"60vh"} display={"flex"} alignItems={"stretch"} component={Paper}>
|
||||
<Box>
|
||||
<List sx={{ height: "100%", overflow: "auto" }}>
|
||||
{props.bladeburner.consoleLogs.map((log: any, i: number) => (
|
||||
<Line key={i} content={log} />
|
||||
))}
|
||||
<TextField
|
||||
classes={{ root: classes.textfield }}
|
||||
autoFocus
|
||||
tabIndex={1}
|
||||
type="text"
|
||||
value={command}
|
||||
onChange={handleCommandChange}
|
||||
onKeyDown={handleKeyDown}
|
||||
InputProps={{
|
||||
// for players to hook in
|
||||
className: classes.input,
|
||||
startAdornment: (
|
||||
<>
|
||||
<Typography>> </Typography>
|
||||
</>
|
||||
),
|
||||
spellCheck: false,
|
||||
}}
|
||||
/>
|
||||
</List>
|
||||
<div ref={scrollHook}></div>
|
||||
<Paper>
|
||||
<Box sx={{
|
||||
height: '60vh',
|
||||
paddingBottom: '8px',
|
||||
display: 'flex',
|
||||
alignItems: 'stretch',
|
||||
}}>
|
||||
<Box>
|
||||
<Logs entries={[...props.bladeburner.consoleLogs]} />
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<TextField
|
||||
classes={{ root: classes.textfield }}
|
||||
autoFocus
|
||||
tabIndex={1}
|
||||
type="text"
|
||||
value={command}
|
||||
onChange={handleCommandChange}
|
||||
onKeyDown={handleKeyDown}
|
||||
InputProps={{
|
||||
// for players to hook in
|
||||
className: classes.input,
|
||||
startAdornment: (
|
||||
<>
|
||||
<Typography>> </Typography>
|
||||
</>
|
||||
),
|
||||
spellCheck: false,
|
||||
}}
|
||||
/>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
interface ILogProps {
|
||||
entries: string[];
|
||||
}
|
||||
|
||||
function Logs({entries}: ILogProps): React.ReactElement {
|
||||
const scrollHook = useRef<HTMLUListElement>(null);
|
||||
|
||||
// TODO: Text gets shifted up as new entries appear, if the user scrolled up it should attempt to keep the text focused
|
||||
function scrollToBottom(): void {
|
||||
if (!scrollHook.current) return;
|
||||
scrollHook.current.scrollTop = scrollHook.current.scrollHeight;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
scrollToBottom();
|
||||
}, [entries]);
|
||||
|
||||
return (
|
||||
<List sx={{ height: "100%", overflow: "auto", p: 1 }} ref={scrollHook}>
|
||||
{entries && entries.map((log: any, i: number) => (
|
||||
<Line key={i} content={log} />
|
||||
))}
|
||||
</List>
|
||||
);
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
|
||||
<>
|
||||
<br />
|
||||
<Typography variant="h4">Purchased Augmentations</Typography>
|
||||
<Typography>This factions also offers these augmentations but you already own them.</Typography>
|
||||
<Typography>This faction also offers these augmentations but you already own them.</Typography>
|
||||
{owned.map((aug) => purchaseableAugmentation(aug, true))}
|
||||
</>
|
||||
);
|
||||
|
@ -73,7 +73,7 @@ export function TechVendorLocation(props: IProps): React.ReactElement {
|
||||
{purchaseServerButtons}
|
||||
<br />
|
||||
<Typography>
|
||||
<i>"You can order bigger servers via scripts. We don't take custom order in person."</i>
|
||||
<i>"You can order bigger servers via scripts. We don't take custom orders in person."</i>
|
||||
</Typography>
|
||||
<br />
|
||||
<TorButton p={player} rerender={rerender} />
|
||||
|
@ -348,6 +348,10 @@ export const RamCosts: IMap<any> = {
|
||||
remove: RamCostConstants.ScriptStanekDeleteAt,
|
||||
},
|
||||
|
||||
ui: {
|
||||
getTheme: 0,
|
||||
},
|
||||
|
||||
heart: {
|
||||
// Easter egg function
|
||||
break: 0,
|
||||
|
@ -64,7 +64,7 @@ import { NetscriptSleeve } from "./NetscriptFunctions/Sleeve";
|
||||
import { NetscriptExtra } from "./NetscriptFunctions/Extra";
|
||||
import { NetscriptHacknet } from "./NetscriptFunctions/Hacknet";
|
||||
import { NetscriptStanek } from "./NetscriptFunctions/Stanek";
|
||||
|
||||
import { NetscriptUserInterface } from './NetscriptFunctions/UserInterface';
|
||||
import { NetscriptBladeburner } from "./NetscriptFunctions/Bladeburner";
|
||||
import { NetscriptCodingContract } from "./NetscriptFunctions/CodingContract";
|
||||
import { NetscriptCorporation } from "./NetscriptFunctions/Corporation";
|
||||
@ -455,6 +455,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
const formulas = NetscriptFormulas(Player, workerScript, helper);
|
||||
const singularity = NetscriptSingularity(Player, workerScript, helper);
|
||||
const stockmarket = NetscriptStockMarket(Player, workerScript, helper);
|
||||
const ui = NetscriptUserInterface(Player, workerScript, helper);
|
||||
|
||||
const base: INS = {
|
||||
...singularity,
|
||||
@ -465,7 +466,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
sleeve: sleeve,
|
||||
corporation: corporation,
|
||||
stanek: stanek,
|
||||
|
||||
ui: ui,
|
||||
formulas: formulas,
|
||||
stock: stockmarket,
|
||||
args: workerScript.args,
|
||||
|
20
src/NetscriptFunctions/UserInterface.ts
Normal file
20
src/NetscriptFunctions/UserInterface.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
||||
import { UserInterface as IUserInterface, UserInterfaceTheme } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { Settings } from "../Settings/Settings";
|
||||
|
||||
export function NetscriptUserInterface(
|
||||
player: IPlayer,
|
||||
workerScript: WorkerScript,
|
||||
helper: INetscriptHelper,
|
||||
): IUserInterface {
|
||||
return {
|
||||
getTheme: function (): UserInterfaceTheme {
|
||||
helper.updateDynamicRam("getTheme", getRamCost("ui", "getTheme"));
|
||||
return {...Settings.theme};
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -194,6 +194,8 @@ async function parseOnlyRamCalculate(
|
||||
func = workerScript.env.vars.sleeve[ref];
|
||||
} else if (ref in workerScript.env.vars.stock) {
|
||||
func = workerScript.env.vars.stock[ref];
|
||||
} else if (ref in workerScript.env.vars.ui) {
|
||||
func = workerScript.env.vars.ui[ref];
|
||||
} else {
|
||||
func = workerScript.env.vars[ref];
|
||||
}
|
||||
|
68
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
68
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@ -3741,6 +3741,21 @@ interface Stanek {
|
||||
remove(rootX: number, rootY: number): boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* User Interface API.
|
||||
* @public
|
||||
*/
|
||||
interface UserInterface {
|
||||
/**
|
||||
* Get the current theme
|
||||
* @remarks
|
||||
* RAM cost: cost: 0 GB
|
||||
*
|
||||
* @returns An object containing the theme's colors
|
||||
*/
|
||||
getTheme(): UserInterfaceTheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collection of all functions passed to scripts
|
||||
* @public
|
||||
@ -3823,6 +3838,12 @@ export interface NS extends Singularity {
|
||||
*/
|
||||
readonly corporation: Corporation;
|
||||
|
||||
/**
|
||||
* Namespace for user interface functions.
|
||||
* RAM cost: 0 GB
|
||||
*/
|
||||
readonly ui: UserInterface;
|
||||
|
||||
/**
|
||||
* Arguments passed into the script.
|
||||
*
|
||||
@ -5381,6 +5402,11 @@ export interface NS extends Singularity {
|
||||
|
||||
/**
|
||||
* Get information about the player.
|
||||
* @remarks
|
||||
* RAM cost: 0.5 GB
|
||||
*
|
||||
* Returns an object with information on the current player.
|
||||
*
|
||||
* @returns Player info
|
||||
*/
|
||||
getPlayer(): Player;
|
||||
@ -5885,3 +5911,45 @@ interface Division {
|
||||
/** Cities in which this division has expanded */
|
||||
cities: string[];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Interface Theme
|
||||
* @internal
|
||||
*/
|
||||
interface UserInterfaceTheme {
|
||||
[key: string]: string | undefined;
|
||||
primarylight: string;
|
||||
primary: string;
|
||||
primarydark: string;
|
||||
successlight: string;
|
||||
success: string;
|
||||
successdark: string;
|
||||
errorlight: string;
|
||||
error: string;
|
||||
errordark: string;
|
||||
secondarylight: string;
|
||||
secondary: string;
|
||||
secondarydark: string;
|
||||
warninglight: string;
|
||||
warning: string;
|
||||
warningdark: string;
|
||||
infolight: string;
|
||||
info: string;
|
||||
infodark: string;
|
||||
welllight: string;
|
||||
well: string;
|
||||
white: string;
|
||||
black: string;
|
||||
hp: string;
|
||||
money: string;
|
||||
hack: string;
|
||||
combat: string;
|
||||
cha: string;
|
||||
int: string;
|
||||
rep: string;
|
||||
disabled: string;
|
||||
backgroundprimary: string;
|
||||
backgroundsecondary: string;
|
||||
button: string;
|
||||
}
|
||||
|
@ -125,6 +125,25 @@ export function Root(props: IProps): React.ReactElement {
|
||||
vim: props.vim || Settings.MonacoVim,
|
||||
});
|
||||
|
||||
const [dimensions, setDimensions] = useState({
|
||||
height: window.innerHeight,
|
||||
width: window.innerWidth,
|
||||
});
|
||||
useEffect(() => {
|
||||
const debouncedHandleResize = debounce(function handleResize() {
|
||||
setDimensions({
|
||||
height: window.innerHeight,
|
||||
width: window.innerWidth,
|
||||
});
|
||||
}, 250);
|
||||
|
||||
window.addEventListener("resize", debouncedHandleResize);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("resize", debouncedHandleResize);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// Save currentScript
|
||||
window.localStorage.setItem(
|
||||
@ -203,7 +222,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
// Generates a new model for the script
|
||||
function regenerateModel(script: OpenScript): void {
|
||||
if (monacoRef.current !== null) {
|
||||
script.model = monacoRef.current.editor.createModel(script.code, "javascript");
|
||||
script.model = monacoRef.current.editor.createModel(script.code, script.fileName.endsWith(".txt") ? "plaintext" : "javascript");
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,6 +236,10 @@ export function Root(props: IProps): React.ReactElement {
|
||||
);
|
||||
|
||||
async function updateRAM(newCode: string): Promise<void> {
|
||||
if (currentScript != null && currentScript.fileName.endsWith(".txt")) {
|
||||
debouncedSetRAM("");
|
||||
return;
|
||||
}
|
||||
setUpdatingRam(true);
|
||||
const codeCopy = newCode + "";
|
||||
const ramUsage = await calculateRamUsage(codeCopy, props.player.getCurrentServer().scripts);
|
||||
@ -348,7 +371,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
code,
|
||||
props.hostname,
|
||||
new monacoRef.current.Position(0, 0),
|
||||
monacoRef.current.editor.createModel(code, "javascript"),
|
||||
monacoRef.current.editor.createModel(code, filename.endsWith(".txt") ? "plaintext" : "javascript"),
|
||||
);
|
||||
setOpenScripts((oldArray) => [...oldArray, newScript]);
|
||||
setCurrentScript({ ...newScript });
|
||||
@ -642,11 +665,13 @@ export function Root(props: IProps): React.ReactElement {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Make this responsive to window resizes
|
||||
// Toolbars are roughly 108px + vim bar 34px
|
||||
// Get percentage of space that toolbars represent and the rest should be the
|
||||
// editor
|
||||
const editorHeight = 100 - ((108 + (options.vim ? 34 : 0)) / window.innerHeight) * 100;
|
||||
// Toolbars are roughly 112px:
|
||||
// 8px body margin top
|
||||
// 38.5px filename tabs
|
||||
// 5px padding for top of editor
|
||||
// 44px bottom tool bar + 16px margin
|
||||
// + vim bar 34px
|
||||
const editorHeight = dimensions.height - (112 + (options.vim ? 34 : 0));
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -725,7 +750,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
beforeMount={beforeMount}
|
||||
onMount={onMount}
|
||||
loading={<Typography>Loading script editor!</Typography>}
|
||||
height={`${editorHeight}%`}
|
||||
height={`${editorHeight}px`}
|
||||
defaultLanguage="javascript"
|
||||
defaultValue={""}
|
||||
onChange={updateCode}
|
||||
|
@ -11,7 +11,8 @@ import PaletteSharpIcon from "@mui/icons-material/PaletteSharp";
|
||||
import { Color, ColorPicker } from "material-ui-color";
|
||||
import { ThemeEvents } from "./Theme";
|
||||
import { Settings, defaultSettings } from "../../Settings/Settings";
|
||||
import { ITheme, getPredefinedThemes } from "../../Settings/Themes";
|
||||
import { getPredefinedThemes } from "../../Settings/Themes";
|
||||
import { UserInterfaceTheme } from "../../ScriptEditor/NetscriptDefinitions";
|
||||
|
||||
interface IProps {
|
||||
open: boolean;
|
||||
@ -75,7 +76,7 @@ export function ThemeEditorModal(props: IProps): React.ReactElement {
|
||||
</Button>
|
||||
)) || <></>;
|
||||
|
||||
function setTheme(theme: ITheme): void {
|
||||
function setTheme(theme: UserInterfaceTheme): void {
|
||||
setCustomTheme(theme);
|
||||
Object.assign(Settings.theme, theme);
|
||||
ThemeEvents.emit();
|
||||
@ -105,7 +106,7 @@ export function ThemeEditorModal(props: IProps): React.ReactElement {
|
||||
ThemeEvents.emit();
|
||||
}
|
||||
|
||||
function setTemplateTheme(theme: ITheme): void {
|
||||
function setTemplateTheme(theme: UserInterfaceTheme): void {
|
||||
setTheme(theme);
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,8 @@ describe("Netscript Dynamic RAM Calculation/Generation Tests", function () {
|
||||
}
|
||||
|
||||
// Runs a Netscript function and properly catches it if it returns promise
|
||||
function runPotentiallyAsyncFunction(fn) {
|
||||
const res = fn();
|
||||
function runPotentiallyAsyncFunction(fn, ...args) {
|
||||
const res = fn(...args);
|
||||
if (res instanceof Promise) {
|
||||
res.catch(() => undefined);
|
||||
}
|
||||
@ -48,7 +48,7 @@ describe("Netscript Dynamic RAM Calculation/Generation Tests", function () {
|
||||
* @param {string[]} fnDesc - describes the name of the function being tested,
|
||||
* including the namespace(s). e.g. ["gang", "getMemberNames"]
|
||||
*/
|
||||
async function testNonzeroDynamicRamCost(fnDesc) {
|
||||
async function testNonzeroDynamicRamCost(fnDesc, ...args) {
|
||||
if (!Array.isArray(fnDesc)) {
|
||||
throw new Error("Non-array passed to testNonzeroDynamicRamCost()");
|
||||
}
|
||||
@ -61,7 +61,7 @@ describe("Netscript Dynamic RAM Calculation/Generation Tests", function () {
|
||||
|
||||
// We don't need a real WorkerScript
|
||||
const workerScript = {
|
||||
args: [],
|
||||
args: args,
|
||||
code: code,
|
||||
dynamicLoadedFns: {},
|
||||
dynamicRamUsage: RamCostConstants.ScriptBaseRamCost,
|
||||
@ -91,9 +91,9 @@ describe("Netscript Dynamic RAM Calculation/Generation Tests", function () {
|
||||
// actually initialized. Call the fn multiple times to test that repeated calls
|
||||
// do not incur extra RAM costs.
|
||||
try {
|
||||
runPotentiallyAsyncFunction(curr);
|
||||
runPotentiallyAsyncFunction(curr);
|
||||
runPotentiallyAsyncFunction(curr);
|
||||
runPotentiallyAsyncFunction(curr, ...args);
|
||||
runPotentiallyAsyncFunction(curr, ...args);
|
||||
runPotentiallyAsyncFunction(curr, ...args);
|
||||
} catch (e) {}
|
||||
} else {
|
||||
throw new Error(`Invalid function specified: [${fnDesc}]`);
|
||||
@ -434,7 +434,7 @@ describe("Netscript Dynamic RAM Calculation/Generation Tests", function () {
|
||||
|
||||
it("purchaseServer()", async function () {
|
||||
const f = ["purchaseServer"];
|
||||
await testNonzeroDynamicRamCost(f);
|
||||
await testNonzeroDynamicRamCost(f, "abc", '64');
|
||||
});
|
||||
|
||||
it("deleteServer()", async function () {
|
||||
|
Loading…
Reference in New Issue
Block a user