mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-23 22:52:29 +01:00
Add setting UI for port/reconnect, swap wrong API handlers
This commit is contained in:
parent
d20f621b47
commit
5fc67c328b
46
src/GameOptions/ui/ConnectionBauble.tsx
Normal file
46
src/GameOptions/ui/ConnectionBauble.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import React from "react";
|
||||
|
||||
interface baubleState {
|
||||
connection: boolean;
|
||||
callback: () => boolean;
|
||||
}
|
||||
|
||||
interface baubleProps {
|
||||
callback: () => boolean;
|
||||
}
|
||||
|
||||
export class ConnectionBauble extends React.Component<baubleProps> {
|
||||
timerID: NodeJS.Timer;
|
||||
state: baubleState;
|
||||
|
||||
constructor(props: baubleProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
connection: false,
|
||||
callback: props.callback
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() : void {
|
||||
this.timerID = setInterval(
|
||||
() => this.tick(),
|
||||
1000
|
||||
);
|
||||
}
|
||||
|
||||
componentWillUnmount() : void {
|
||||
clearInterval(this.timerID);
|
||||
}
|
||||
|
||||
tick() : void {
|
||||
this.setState({
|
||||
connection: this.state.callback()
|
||||
});
|
||||
}
|
||||
|
||||
render() : string {
|
||||
return (
|
||||
this.state.connection? "Connected" : "Disconnected"
|
||||
);
|
||||
}
|
||||
}
|
@ -1,12 +1,15 @@
|
||||
import { MenuItem, Select, SelectChangeEvent, TextField, Tooltip, Typography } from "@mui/material";
|
||||
import { MenuItem, Select, SelectChangeEvent, TextField, Tooltip, Typography, Box } from "@mui/material";
|
||||
import React, { useState } from "react";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { isRemoteFileApiConnectionLive, newRemoteFileApiConnection } from "../../RemoteFileAPI/RemoteFileAPI";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { OptionSwitch } from "../../ui/React/OptionSwitch";
|
||||
import { formatTime } from "../../utils/helpers/formatTime";
|
||||
import { GameOptionsTab } from "../GameOptionsTab";
|
||||
import { GameOptionsPage } from "./GameOptionsPage";
|
||||
import { OptionsSlider } from "./OptionsSlider";
|
||||
import Button from "@mui/material/Button";
|
||||
import { ConnectionBauble } from "./ConnectionBauble";
|
||||
|
||||
interface IProps {
|
||||
currentTab: GameOptionsTab;
|
||||
@ -21,6 +24,7 @@ export const CurrentOptionsPage = (props: IProps): React.ReactElement => {
|
||||
const [terminalSize, setTerminalSize] = useState(Settings.MaxTerminalCapacity);
|
||||
const [autosaveInterval, setAutosaveInterval] = useState(Settings.AutosaveInterval);
|
||||
const [timestampFormat, setTimestampFormat] = useState(Settings.TimestampsFormat);
|
||||
const [remoteFileApiPort, setRemoteFileApiPort] = useState(Settings.RemoteFileApiPort);
|
||||
const [locale, setLocale] = useState(Settings.Locale);
|
||||
|
||||
function handleExecTimeChange(
|
||||
@ -81,6 +85,11 @@ export const CurrentOptionsPage = (props: IProps): React.ReactElement => {
|
||||
Settings.TimestampsFormat = event.target.value;
|
||||
}
|
||||
|
||||
function handleRemoteFileApiPortChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
setRemoteFileApiPort(Number(event.target.value) as number);
|
||||
Settings.RemoteFileApiPort = Number(event.target.value);
|
||||
}
|
||||
|
||||
const pages = {
|
||||
[GameOptionsTab.SYSTEM]: (
|
||||
<GameOptionsPage title="System">
|
||||
@ -361,6 +370,35 @@ export const CurrentOptionsPage = (props: IProps): React.ReactElement => {
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<Tooltip title={
|
||||
<Typography>
|
||||
This port number is used to connect to a Remote File API port,
|
||||
please ensure that it matches with the port the Remote File API server is publishing on (12525 by default).
|
||||
Click the reconnect button to try and re-establish connection.
|
||||
The little colored bauble shows whether the connection is live or not.
|
||||
</Typography>
|
||||
}>
|
||||
<TextField
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<Typography
|
||||
color={remoteFileApiPort > 0 && remoteFileApiPort <= 65535? "success" : "error"}
|
||||
>
|
||||
Remote File API port:
|
||||
</Typography>
|
||||
),
|
||||
endAdornment: (
|
||||
<Box>
|
||||
<Button onClick={newRemoteFileApiConnection}>Reconnect</Button>
|
||||
<ConnectionBauble callback={isRemoteFileApiConnectionLive}/>
|
||||
</Box>
|
||||
),
|
||||
}}
|
||||
value={remoteFileApiPort}
|
||||
onChange={handleRemoteFileApiPortChange}
|
||||
placeholder="12525"
|
||||
/>
|
||||
</Tooltip>
|
||||
</GameOptionsPage>
|
||||
),
|
||||
};
|
||||
|
@ -77,26 +77,12 @@ export const RFARequestHandler: Record<string, (message: RFAMessage) => void | R
|
||||
return new RFAMessage({ result: "OK", id: msg.id });
|
||||
},
|
||||
|
||||
getFileNames: function (msg: RFAMessage): RFAMessage {
|
||||
getFileNames: function (msg: RFAMessage): RFAMessage {
|
||||
if (!isFileServer(msg.params)) return error("getFileNames message misses parameters", msg);
|
||||
|
||||
const server = GetServer(msg.params.server);
|
||||
if (server == null) return error("Server hostname invalid", msg);
|
||||
|
||||
const fileList: FileContent[] = [
|
||||
...server.textFiles.map((txt): FileContent => { return { filename: txt.filename, content: txt.text } }),
|
||||
...server.scripts.map((scr): FileContent => { return { filename: scr.filename, content: scr.code } })
|
||||
];
|
||||
|
||||
return new RFAMessage({ result: JSON.stringify(fileList), id: msg.id });
|
||||
},
|
||||
|
||||
getAllFiles: function (msg: RFAMessage): RFAMessage {
|
||||
if (!isFileServer(msg.params)) return error("getAllFiles message misses parameters", msg);
|
||||
|
||||
const server = GetServer(msg.params.server);
|
||||
if (server == null) return error("Server hostname invalid", msg);
|
||||
|
||||
const fileNameList: string[] = [
|
||||
...server.textFiles.map((txt): string => txt.filename),
|
||||
...server.scripts.map((scr): string => scr.filename)
|
||||
@ -105,6 +91,20 @@ export const RFARequestHandler: Record<string, (message: RFAMessage) => void | R
|
||||
return new RFAMessage({ result: JSON.stringify(fileNameList), id: msg.id });
|
||||
},
|
||||
|
||||
getAllFiles: function (msg: RFAMessage): RFAMessage {
|
||||
if (!isFileServer(msg.params)) return error("getAllFiles message misses parameters", msg);
|
||||
|
||||
const server = GetServer(msg.params.server);
|
||||
if (server == null) return error("Server hostname invalid", msg);
|
||||
|
||||
const fileList: FileContent[] = [
|
||||
...server.textFiles.map((txt): FileContent => { return { filename: txt.filename, content: txt.text } }),
|
||||
...server.scripts.map((scr): FileContent => { return { filename: scr.filename, content: scr.code } })
|
||||
];
|
||||
|
||||
return new RFAMessage({ result: JSON.stringify(fileList), id: msg.id });
|
||||
},
|
||||
|
||||
calculateRam: function (msg: RFAMessage): RFAMessage {
|
||||
if (!isFileLocation(msg.params)) return error("calculateRam message misses parameters", msg);
|
||||
const fileData: FileLocation = msg.params;
|
||||
|
@ -13,36 +13,18 @@ export class Remote {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public stopConnection() : void {
|
||||
this.connection?.close();
|
||||
}
|
||||
|
||||
public startConnection() : void {
|
||||
this.startConnectionRecurse(1, 5);
|
||||
}
|
||||
|
||||
handleCloseEvent():void {
|
||||
delete this.connection;
|
||||
RFALogger.log("Connection closed.");
|
||||
}
|
||||
|
||||
startConnectionRecurse(retryN : number, retryMax : number) : void {
|
||||
RFALogger.log("Trying to connect.");
|
||||
this.connection = new WebSocket(this.protocol + "://" + this.ipaddr + ":" + this.port);
|
||||
|
||||
this.connection.addEventListener("error", (e:Event) => {
|
||||
if(!this.connection) return;
|
||||
|
||||
// When having trouble connecting, try again.
|
||||
if (this.connection.readyState === 3) {
|
||||
RFALogger.log(`Connection lost, retrying (try #${retryN}).`);
|
||||
if (retryN <= retryMax) this.startConnectionRecurse(retryN + 1, retryMax);
|
||||
return;
|
||||
}
|
||||
|
||||
// Else handle the error normally
|
||||
RFALogger.error(e);
|
||||
});
|
||||
|
||||
this.connection.addEventListener("error", (e:Event) => RFALogger.error(e));
|
||||
this.connection.addEventListener("message", handleMessageEvent);
|
||||
this.connection.addEventListener("open", () => RFALogger.log("Connection established: ", this.ipaddr, ":", this.port));
|
||||
this.connection.addEventListener("close", this.handleCloseEvent);
|
||||
this.connection.addEventListener("close", () => RFALogger.log("Connection closed"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,19 @@
|
||||
import { Settings } from "../Settings/Settings";
|
||||
import { Remote } from "./Remote";
|
||||
|
||||
class RemoteFileAPI {
|
||||
server : Remote;
|
||||
|
||||
constructor(){
|
||||
this.server = new Remote("localhost", 12525);
|
||||
return;
|
||||
}
|
||||
let server: Remote;
|
||||
|
||||
enable() : void {
|
||||
this.server.startConnection();
|
||||
export function newRemoteFileApiConnection() : void {
|
||||
if(server == undefined)
|
||||
server = new Remote("localhost", Settings.RemoteFileApiPort);
|
||||
else {
|
||||
server.stopConnection();
|
||||
server = new Remote("localhost", Settings.RemoteFileApiPort);
|
||||
server.startConnection();
|
||||
}
|
||||
}
|
||||
|
||||
export const RFA = new RemoteFileAPI;
|
||||
export function isRemoteFileApiConnectionLive() : boolean {
|
||||
return server.connection != undefined && server.connection.readyState == 1;
|
||||
}
|
||||
|
@ -84,6 +84,11 @@ interface IDefaultSettings {
|
||||
*/
|
||||
MaxTerminalCapacity: number;
|
||||
|
||||
/**
|
||||
* Port the Remote File API client will try to connect to.
|
||||
*/
|
||||
RemoteFileApiPort: number;
|
||||
|
||||
/**
|
||||
* Save the game when you save any file.
|
||||
*/
|
||||
@ -206,6 +211,7 @@ export const defaultSettings: IDefaultSettings = {
|
||||
MaxLogCapacity: 50,
|
||||
MaxPortCapacity: 50,
|
||||
MaxTerminalCapacity: 500,
|
||||
RemoteFileApiPort: 12525,
|
||||
SaveGameOnFileSave: true,
|
||||
SuppressBuyAugmentationConfirmation: false,
|
||||
SuppressFactionInvites: false,
|
||||
@ -248,6 +254,7 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
|
||||
MaxTerminalCapacity: defaultSettings.MaxTerminalCapacity,
|
||||
OwnedAugmentationsOrder: OwnedAugmentationsOrderSetting.AcquirementTime,
|
||||
PurchaseAugmentationsOrder: PurchaseAugmentationsOrderSetting.Default,
|
||||
RemoteFileApiPort: defaultSettings.RemoteFileApiPort,
|
||||
SaveGameOnFileSave: defaultSettings.SaveGameOnFileSave,
|
||||
SuppressBuyAugmentationConfirmation: defaultSettings.SuppressBuyAugmentationConfirmation,
|
||||
SuppressFactionInvites: defaultSettings.SuppressFactionInvites,
|
||||
|
@ -5,7 +5,7 @@ import { TTheme as Theme, ThemeEvents, refreshTheme } from "./Themes/ui/Theme";
|
||||
import { LoadingScreen } from "./ui/LoadingScreen";
|
||||
import { initElectron } from "./Electron";
|
||||
|
||||
import { RFA } from "./RemoteFileAPI/RemoteFileAPI";
|
||||
import { newRemoteFileApiConnection } from "./RemoteFileAPI/RemoteFileAPI";
|
||||
|
||||
initElectron();
|
||||
globalThis["React"] = React;
|
||||
@ -17,8 +17,7 @@ ReactDOM.render(
|
||||
document.getElementById("root"),
|
||||
);
|
||||
|
||||
console.log("[RFA] Fix this hack ASAP");
|
||||
RFA.enable();
|
||||
newRemoteFileApiConnection();
|
||||
|
||||
function rerender(): void {
|
||||
refreshTheme();
|
||||
|
Loading…
Reference in New Issue
Block a user