diff --git a/Dockerfile b/Dockerfile
index ee22342..49d1c20 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -59,8 +59,6 @@ EXPOSE 3000
ENV PORT 3000
-RUN yarn add @beam-australia/react-env
-
ENTRYPOINT yarn react-env --env APP_ENV
-CMD ["node", "server.js"]
\ No newline at end of file
+CMD yarn start
\ No newline at end of file
diff --git a/src/pages/overlayold.js b/src/pages/overlayold.js
deleted file mode 100644
index ece5337..0000000
--- a/src/pages/overlayold.js
+++ /dev/null
@@ -1,517 +0,0 @@
-import { Link, Spinner } from "@nextui-org/react";
-import { NextSeo } from "next-seo";
-import { Component } from "react";
-import PlayerStats from "../components/PlayerStats";
-import ScoreStats from "../components/ScoreStats";
-import SongInfo from "../components/SongInfo";
-import LeaderboardType from "../consts/LeaderboardType";
-import Utils from "../utils/utils";
-
-import styles from "../styles/overlay.module.css";
-
-export default class Overlay extends Component {
- #_beatSaverURL = "";
-
- constructor(props) {
- super(props);
-
- this.cutData = [];
- this.cutData.SaberA = {
- count: [0, 0, 0],
- totalScore: [0, 0, 0],
- };
- this.cutData.SaberB = {
- count: [0, 0, 0],
- totalScore: [0, 0, 0],
- };
-
- this._mounted = false;
- this.state = {
- hasError: false,
-
- // Steam ID
- id: undefined,
-
- // Values from the query parameters
- loadingPlayerData: true,
- isConnectedToSocket: false,
- isValidSteamId: false,
- websiteType: "ScoreSaber",
- showPlayerStats: true,
- showScore: false,
- showSongInfo: false,
- shouldReplacePlayerInfoWithScore: false,
-
- // Internal
- loadedDuringSong: false,
- socket: undefined,
- data: undefined,
- beatSaverData: undefined,
- songInfo: undefined,
- mapStarCount: undefined,
-
- // UI elements
- isPlayerInfoVisible: false,
- isVisible: false,
-
- // Score data
- paused: true,
- failed: false,
- currentSongTime: 0,
- currentScore: 0,
- percentage: "100.00%",
- SaberA: {
- cutDistanceScore: 0.0,
- averagePreSwing: 0.0,
- averagePostSwing: 0.0,
- },
- SaberB: {
- cutDistanceScore: 0.0,
- averagePreSwing: 0.0,
- averagePostSwing: 0.0,
- },
- };
- this.setupTimer();
- }
-
- async componentDidMount() {
- if (this._mounted === true) {
- return;
- }
- this._mounted = true;
-
- if (this.state.hasError) {
- // Reload the page if there has been an error
- console.log("There has been an error and the page was reloaded.");
- return Router.reload(window.location.pathname);
- }
-
- console.log("Initializing...");
- this.#_beatSaverURL =
- document.location.origin + "/api/beatsaver/map?hash=%s";
- const urlSearchParams = new URLSearchParams(window.location.search);
- const params = Object.fromEntries(urlSearchParams.entries());
-
- // Check what website the player wants to use
- if (params.beatleader === "true" || params.beatLeader === "true") {
- this.setState({ websiteType: "BeatLeader" });
- }
-
- const id = params.id;
- if (!id) {
- // Check if the id param is valid
- this.setState({ isValidSteamId: false, loadingPlayerData: false });
- return;
- }
-
- // Checks if the steam id is valid
- const isValid = await this.validateSteamId(id);
- if (!isValid) {
- this.setState({ isValidSteamId: false, loadingPlayerData: false });
- return;
- }
- this.setState({ id: id, isValidSteamId: true });
-
- // Check if the player wants to disable their stats (pp, global pos, etc)
- if (params.showPlayerStats === "false" || params.playerstats === "false") {
- this.setState({ showPlayerStats: false });
- }
-
- if (this.state.showPlayerStats == true || params.playerstats == "true") {
- setTimeout(async () => {
- await this.updateData(id);
- }, 10); // 10ms
- this.setState({ isPlayerInfoVisible: true });
- }
-
- let shouldConnectSocket = false;
-
- // Check if the player wants to show their current score information
- if (params.showScoreInfo === "true" || params.scoreinfo === "true") {
- this.setState({ showScore: true });
- shouldConnectSocket = true;
- }
-
- if (params.shouldReplacePlayerInfoWithScore === "true") {
- this.setState({ shouldReplacePlayerInfoWithScore: true });
- }
-
- // Check if the player wants to show the current song
- if (params.showSongInfo === "true" || params.songinfo === "true") {
- this.setState({ showSongInfo: true });
- shouldConnectSocket = true;
- }
-
- if (shouldConnectSocket) {
- if (this.state.isConnectedToSocket) return;
- this.connectSocket(params.socketaddress);
- }
- }
-
- // Handle Errors
- static getDerivedStateFromError(error) {
- return this.setState({ hasError: true });
- }
- componentDidCatch(error, errorInfo) {
- console.log({ error, errorInfo });
- }
- // ---
-
- // I'd love if HTTP Status just gave this data lmao
- // HttpSiraStatus(https://github.com/denpadokei/HttpSiraStatus) does give this data.
- isCurrentSongTimeProvided = false;
- // we don't need to reset this to false because it is highly unlikely for a player to swap mods within a browser session
-
- /**
- * Setup the timer for the song time
- */
- setupTimer() {
- setInterval(() => {
- if (this.isCurrentSongTimeProvided) {
- return;
- }
- if (!this.state.paused && this.state.beatSaverData !== undefined) {
- this.setState({ currentSongTime: this.state.currentSongTime + 1 });
- }
- }, 1000);
- }
-
- /**
- * Update the current song time
- *
- * @param {[]} data The song data
- */
- handleCurrentSongTime(data) {
- try {
- const time = data.status.performance.currentSongTime;
- if (time !== undefined && time != null) {
- this.isCurrentSongTimeProvided = true;
- this.setState({ currentSongTime: time });
- }
- } catch (e) {
- // do nothing
- }
- }
-
- /**
- * Fetch and update the data from the respective platform
- *
- * @param {string} id The steam id of the player
- * @returns
- */
- async updateData(id) {
- const data = await fetch(
- Utils.getWebsiteApi(this.state.websiteType).ApiUrl.PlayerData.replace(
- "%s",
- id
- ),
- {
- headers: {
- "X-Requested-With": "BeatSaber Overlay",
- },
- }
- );
- try {
- const json = await data.json();
- this.setState({
- loadingPlayerData: false,
- id: id,
- data: json,
- });
- } catch (e) {
- // Catch error and use last known data
- console.error(e);
- }
- }
-
- /**
- * Checks if the given steam id is valid or not
- *
- * @param {id} The Steam ID of the player to validate
- */
- async validateSteamId(id) {
- if (id.length !== 17) {
- return false;
- }
- const data = await fetch(`/api/validateid?steamid=${id}`);
- const json = await data.json();
- return json.message === "Valid";
- }
-
- /**
- * Setup the HTTP Status connection
- */
- connectSocket(socketAddress) {
- socketAddress =
- (socketAddress === undefined
- ? "ws://localhost"
- : `ws://${socketAddress}`) + ":6557/socket";
- if (this.state.isConnectedToSocket) return;
-
- if (this.state.isVisible) {
- this.resetData(false);
- }
-
- console.log(`Connecting to ${socketAddress}`);
- const socket = new WebSocket(socketAddress);
- socket.addEventListener("open", () => {
- console.log(`Connected to ${socketAddress}`);
- this.setState({ isConnectedToSocket: true });
- });
- socket.addEventListener("close", () => {
- console.log(
- "Attempting to re-connect to the HTTP Status socket in 60 seconds."
- );
- this.resetData(false);
- this.setState({ isConnectedToSocket: false });
- setTimeout(() => this.connectSocket(), 60_000);
- });
- socket.addEventListener("message", (message) => {
- const json = JSON.parse(message.data);
- this.handleCurrentSongTime(json);
- if (!this.handlers[json.event]) {
- console.log("Unhandled message from HTTP Status. (" + json.event + ")");
- return;
- }
- this.handlers[json.event](json || []);
- });
- this.setState({ socket: socket });
- }
-
- /**
- * Set the current songs beat saver url in {@link #_beatSaverURL}
- *
- * @param {[]} songData
- */
- async setBeatSaver(songData) {
- console.log("Updating BeatSaver info");
- const data = await fetch(
- this.#_beatSaverURL.replace("%s", songData.levelId)
- );
- const json = await data.json();
- this.setState({ beatSaverData: json });
-
- const { characteristic, levelId, difficulty } = songData;
- let mapHash = levelId.replace("custom_level_", "");
- let mapStars = undefined;
- if (this.state.websiteType === "BeatLeader") {
- mapStars = await LeaderboardType.BeatLeader.getMapStarCount(
- mapHash,
- difficulty.replace("+", "Plus"),
- characteristic
- );
- }
- if (this.state.websiteType === "ScoreSaber") {
- mapStars = await LeaderboardType.ScoreSaber.getMapStarCount(
- mapHash,
- difficulty.replace("+", "Plus"),
- characteristic
- );
- }
- this.setState({ mapStarCount: mapStars });
- }
-
- /**
- * Cleanup the data and get ready for the next song
- *
- * @param {boolean} visible Whether to show info other than the player stats
- */
- async resetData(visible, loadedDuringSong = false) {
- if (this.state.showPlayerStats == true) {
- setTimeout(async () => {
- await this.updateData(this.state.id);
- }, 1000); // 1 second
- }
-
- if (visible && this.state.shouldReplacePlayerInfoWithScore) {
- this.setState({ isPlayerInfoVisible: false });
- } else {
- this.setState({ isPlayerInfoVisible: true });
- }
-
- this.cutData = [];
- this.cutData.SaberA = {
- count: [0, 0, 0],
- totalScore: [0, 0, 0],
- };
- this.cutData.SaberB = {
- count: [0, 0, 0],
- totalScore: [0, 0, 0],
- };
- this.setState({
- SaberA: {
- cutDistanceScore: 0.0,
- averagePreSwing: 0.0,
- averagePostSwing: 0.0,
- },
- SaberB: {
- cutDistanceScore: 0.0,
- averagePreSwing: 0.0,
- averagePostSwing: 0.0,
- },
- songInfo: undefined,
- beatSaverData: undefined,
- currentSongTime: 0,
- currentScore: 0,
- percentage: "100.00%",
- isVisible: visible,
- loadedDuringSong: loadedDuringSong,
- mapStarCount: undefined,
- });
- }
-
- // The HTTP Status handlers
- handlers = {
- hello: (data) => {
- console.log("Hello from HTTP Status!");
- if (
- data.status &&
- data.status.beatmap &&
- this.state.songData === undefined
- ) {
- console.log("Going into level during song, resetting data.");
- this.resetData(true, true);
- this.setState({ songData: data, paused: false });
- if (this.state.showScore || this.state.showSongInfo) {
- this.setBeatSaver(data.status.beatmap);
- }
- }
- },
- scoreChanged: (data) => {
- const { status } = data;
- const { score, relativeScore } = status.performance;
- let finalScore = score;
- if (finalScore == 0) {
- finalScore = this.state.currentScore;
- }
- const percent = relativeScore * 100;
- this.setState({
- currentScore: finalScore,
- percentage: percent.toFixed(2) + "%",
- });
- },
- noteFullyCut: (data) => {
- const { noteCut } = data;
-
- let beforeCutScore = 0.0;
- let afterCutScore = 0.0;
- let cutDistanceScore = 0.0;
-
- const cutDataSaber = this.cutData[noteCut.saberType];
- cutDataSaber.count[0]++;
- cutDataSaber.count[1]++;
- cutDataSaber.count[2]++;
- cutDataSaber.totalScore[0] += noteCut.beforeCutScore;
- cutDataSaber.totalScore[1] += noteCut.afterCutScore;
- cutDataSaber.totalScore[2] += noteCut.cutDistanceScore;
- beforeCutScore = cutDataSaber.totalScore[0] / cutDataSaber.count[0];
- afterCutScore = cutDataSaber.totalScore[1] / cutDataSaber.count[1];
- cutDistanceScore = cutDataSaber.totalScore[2] / cutDataSaber.count[2];
-
- const cutData = this.state[noteCut.saberType];
- cutData.averagePreSwing = beforeCutScore;
- cutData.averagePostSwing = afterCutScore;
- cutData.cutDistanceScore = cutDistanceScore;
- this.setState({ [noteCut.saberType]: cutData });
- },
- songStart: (data) => {
- console.log("Going into level, resetting data.");
- this.resetData(true);
- this.setState({ songData: data, paused: false });
- if (this.state.showScore || this.state.showSongInfo) {
- this.setBeatSaver(data.status.beatmap);
- }
- },
- finished: () => {
- this.resetData(false);
- },
- softFail: () => {
- this.setState({ failed: true });
- },
- pause: () => {
- this.setState({ paused: true });
- },
- resume: () => {
- this.setState({ paused: false });
- },
- menu: () => {
- this.resetData(false);
- },
- noteCut: () => {},
- noteMissed: () => {},
- noteSpawned: () => {},
- bombMissed: () => {},
- beatmapEvent: () => {},
- energyChanged: () => {},
- obstacleEnter: () => {},
- obstacleExit: () => {},
- };
-
- render() {
- const {
- isValidSteamId,
- data,
- websiteType,
- showPlayerStats,
- loadingPlayerData,
- isPlayerInfoVisible,
- shouldReplacePlayerInfoWithScore,
- id,
- } = this.state;
-
- if (loadingPlayerData) {
- return