+
;
diff --git a/src/client/render/gl/RenderSettings.ts b/src/client/render/gl/RenderSettings.ts
index 628f0ea322..4d2af1bedb 100644
--- a/src/client/render/gl/RenderSettings.ts
+++ b/src/client/render/gl/RenderSettings.ts
@@ -1,3 +1,4 @@
+import { GraphicsOverrides } from "./GraphicsOverrides";
import defaults from "./render-settings.json";
export interface RenderSettings {
@@ -260,6 +261,23 @@ export function createRenderSettings(): RenderSettings {
return JSON.parse(JSON.stringify(defaults)) as RenderSettings;
}
+/**
+ * Generate a fresh RenderSettings by layering user overrides on top of the
+ * render-settings.json defaults. Pure — does not mutate any input.
+ */
+export function generateRenderSettings(
+ overrides: GraphicsOverrides,
+): RenderSettings {
+ const settings = createRenderSettings();
+ if (overrides.name?.nameScaleFactor !== undefined) {
+ settings.name.nameScaleFactor = overrides.name.nameScaleFactor;
+ }
+ if (overrides.name?.cullThreshold !== undefined) {
+ settings.name.cullThreshold = overrides.name.cullThreshold;
+ }
+ return settings;
+}
+
/** Dump current settings to a downloadable JSON file. */
export function dumpSettings(settings: RenderSettings): void {
const json = JSON.stringify(settings, null, 2);
diff --git a/src/client/render/gl/index.ts b/src/client/render/gl/index.ts
index 3f30aab33e..45c8ed4971 100644
--- a/src/client/render/gl/index.ts
+++ b/src/client/render/gl/index.ts
@@ -9,8 +9,14 @@ export type {
RadialMenuSelectEvent,
} from "./Events";
export { GameView } from "./GameView";
+export { GraphicsOverridesSchema } from "./GraphicsOverrides";
+export type { GraphicsOverrides } from "./GraphicsOverrides";
export type { SpawnCenter } from "./passes/SpawnOverlayPass";
-export { createRenderSettings, dumpSettings } from "./RenderSettings";
+export {
+ createRenderSettings,
+ dumpSettings,
+ generateRenderSettings,
+} from "./RenderSettings";
export type { RenderSettings } from "./RenderSettings";
export { deepAssign, deepDiff } from "./SettingsUtils";
export { buildTerrainRGBA, getPaletteSize } from "./utils/ColorUtils";
diff --git a/src/core/game/UserSettings.ts b/src/core/game/UserSettings.ts
index ffdcc07287..133747b172 100644
--- a/src/core/game/UserSettings.ts
+++ b/src/core/game/UserSettings.ts
@@ -1,3 +1,7 @@
+import {
+ GraphicsOverrides,
+ GraphicsOverridesSchema,
+} from "../../client/render/gl/GraphicsOverrides";
import { Cosmetics } from "../CosmeticSchemas";
import { PlayerPattern } from "../Schemas";
@@ -53,6 +57,7 @@ export const COLOR_KEY = "settings.territoryColor";
export const DARK_MODE_KEY = "settings.darkMode";
export const PERFORMANCE_OVERLAY_KEY = "settings.performanceOverlay";
export const KEYBINDS_KEY = "settings.keybinds";
+export const GRAPHICS_KEY = "settings.graphics";
export class UserSettings {
private static cache = new Map();
@@ -354,6 +359,23 @@ export class UserSettings {
this.setFloat("settings.attackRatio", value);
}
+ // Returns {} if missing, unparseable, or fails schema validation.
+ graphicsOverrides(): GraphicsOverrides {
+ const raw = this.getString(GRAPHICS_KEY, "");
+ if (!raw) return {};
+ try {
+ const parsed = GraphicsOverridesSchema.safeParse(JSON.parse(raw));
+ if (parsed.success) return parsed.data;
+ } catch {
+ // fall through
+ }
+ return {};
+ }
+
+ setGraphicsOverrides(value: GraphicsOverrides): void {
+ this.setString(GRAPHICS_KEY, JSON.stringify(value));
+ }
+
// In case localStorage was manually edited to be invalid, return an empty object
parsedUserKeybinds(): Record {
const raw = this.getString(KEYBINDS_KEY, "{}");