From 5d26f4fa5628b449ab6984ab6120bbc8e15c64f2 Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Mon, 11 Nov 2024 22:41:38 +0700 Subject: [PATCH] GANG: Show error popup when there are errors (#1763) * GANG: Show error popup when there are errors * Only show error once when it's in a hot code path --- src/Gang/Gang.ts | 5 +--- src/engine.tsx | 7 ++++-- src/utils/helpers/exceptionAlert.tsx | 36 +++++++++++++++++++++++----- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/Gang/Gang.ts b/src/Gang/Gang.ts index 45589a1df1..c30e4b89b7 100644 --- a/src/Gang/Gang.ts +++ b/src/Gang/Gang.ts @@ -97,9 +97,6 @@ export class Gang { /** Main process function called by the engine loop every game cycle */ process(numCycles = 1): void { - if (isNaN(numCycles)) { - console.error(`NaN passed into Gang.process(): ${numCycles}`); - } this.storedCycles += numCycles; if (this.storedCycles < GangConstants.minCyclesToProcess) return; @@ -112,7 +109,7 @@ export class Gang { this.processTerritoryAndPowerGains(cycles); this.storedCycles -= cycles; } catch (e: unknown) { - console.error("Exception caught when processing Gang", e); + exceptionAlert(e, true); } // Handle "nextUpdate" resolver after this update diff --git a/src/engine.tsx b/src/engine.tsx index 93eb35a40d..b49d026a80 100644 --- a/src/engine.tsx +++ b/src/engine.tsx @@ -170,7 +170,10 @@ const Engine: { decrementAllCounters: function (numCycles = 1) { for (const [counterName, counter] of Object.entries(Engine.Counters)) { - if (counter === undefined) throw new Error("counter should not be undefined"); + if (counter === undefined) { + exceptionAlert(new Error(`counter value is undefined. counterName: ${counterName}.`), true); + continue; + } Engine.Counters[counterName] = counter - numCycles; } }, @@ -207,7 +210,7 @@ const Engine: { try { Player.bladeburner.process(); } catch (e) { - exceptionAlert(e); + exceptionAlert(e, true); } } Engine.Counters.mechanicProcess = 5; diff --git a/src/utils/helpers/exceptionAlert.tsx b/src/utils/helpers/exceptionAlert.tsx index 3cd8d9c0c2..1352dd9b0f 100644 --- a/src/utils/helpers/exceptionAlert.tsx +++ b/src/utils/helpers/exceptionAlert.tsx @@ -2,19 +2,43 @@ import React from "react"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; import Typography from "@mui/material/Typography"; import { getErrorMetadata } from "../ErrorHelper"; +import { cyrb53 } from "../StringHelperFunctions"; -export function exceptionAlert(e: unknown): void { - console.error(e); - const errorMetadata = getErrorMetadata(e); +const errorSet = new Set(); + +/** + * Show the error in a popup: + * - Indicate that this is a bug and should be reported to developers. + * - Automatically include debug information (e.g., stack trace, commit id, user agent). + * + * @param error Error + * @param showOnlyOnce Set to true if you want to show the error only once, even when it happens many times. Default: false. + * @returns + */ +export function exceptionAlert(error: unknown, showOnlyOnce = false): void { + console.error(error); + const errorAsString = String(error); + const errorStackTrace = error instanceof Error ? error.stack : undefined; + if (showOnlyOnce) { + // Calculate the "id" of the error. + const errorId = cyrb53(errorAsString + errorStackTrace); + // Check if we showed it + if (errorSet.has(errorId)) { + return; + } else { + errorSet.add(errorId); + } + } + const errorMetadata = getErrorMetadata(error); dialogBoxCreate( <> - Caught an exception: {String(e)} + Caught an exception: {errorAsString}

- {e instanceof Error && ( + {errorStackTrace && ( - Stack: {e.stack?.toString()} + Stack: {errorStackTrace} )} Commit: {errorMetadata.version.commitHash}