From 0d93574e767eed7b3df250a1bfb84a6e5f98d2a7 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 10 Mar 2026 02:17:50 +0000 Subject: [PATCH] feat: add RuntimeConstants service with get/update/reset Co-Authored-By: Claude Opus 4.6 --- .../config/__tests__/runtimeConstants.test.ts | 42 +++++++++++++++ server/src/config/runtimeConstants.ts | 52 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 server/src/config/__tests__/runtimeConstants.test.ts create mode 100644 server/src/config/runtimeConstants.ts diff --git a/server/src/config/__tests__/runtimeConstants.test.ts b/server/src/config/__tests__/runtimeConstants.test.ts new file mode 100644 index 0000000..805e79f --- /dev/null +++ b/server/src/config/__tests__/runtimeConstants.test.ts @@ -0,0 +1,42 @@ +import { describe, it, expect, beforeEach } from 'vitest'; +import { createRuntimeConstants } from '../runtimeConstants.js'; + +describe('RuntimeConstants', () => { + let rc: ReturnType; + + beforeEach(() => { + rc = createRuntimeConstants(); + }); + + it('initializes with default values from shared constants', () => { + const constants = rc.getAll(); + expect(constants.TICK_RATE).toBe(10); + expect(constants.HUNGER_DECAY_PER_TICK).toBe(0.05); + expect(constants.AWARENESS_RADIUS).toBe(5); + }); + + it('updates a single constant', () => { + rc.update('TICK_RATE', 20); + expect(rc.getAll().TICK_RATE).toBe(20); + }); + + it('rejects unknown keys gracefully', () => { + const result = rc.update('NOT_A_KEY' as any, 5); + expect(result).toBe(false); + }); + + it('resets all to defaults', () => { + rc.update('TICK_RATE', 20); + rc.update('HUNGER_DECAY_PER_TICK', 1.0); + rc.resetDefaults(); + const constants = rc.getAll(); + expect(constants.TICK_RATE).toBe(10); + expect(constants.HUNGER_DECAY_PER_TICK).toBe(0.05); + }); + + it('get() returns individual constant value', () => { + expect(rc.get('MOVE_SPEED')).toBe(0.75); + rc.update('MOVE_SPEED', 1.5); + expect(rc.get('MOVE_SPEED')).toBe(1.5); + }); +}); diff --git a/server/src/config/runtimeConstants.ts b/server/src/config/runtimeConstants.ts new file mode 100644 index 0000000..6d627ef --- /dev/null +++ b/server/src/config/runtimeConstants.ts @@ -0,0 +1,52 @@ +import type { TunableConstants, TunableKey } from '@dflike/shared'; +import { + TICK_RATE, BROADCAST_EVERY_N_TICKS, + HUNGER_DECAY_PER_TICK, ENERGY_DECAY_PER_TICK, HUNGER_THRESHOLD, ENERGY_THRESHOLD, NEED_RECOVERY_RATE, + SLEEP_ENERGY_RECOVERY_PER_TICK, SLEEP_HUNGER_DECAY_MULTIPLIER, SLEEP_WAKE_THRESHOLD, SLEEP_VOLUNTARY_ENERGY_THRESHOLD, + PRODUCTIVITY_DECAY_PER_TICK, PRODUCTIVITY_THRESHOLD, PRODUCTIVITY_RECOVERY_RATE, + DAY_NIGHT_RATIO, DAY_HOURS, SUNSET_DURATION_HOURS, SUNRISE_DURATION_HOURS, NIGHT_DARKNESS, + AWARENESS_RADIUS, FACING_DURATION, PAUSING_DURATION, EMOTING_DURATION, + SOCIAL_GLOBAL_COOLDOWN, SOCIAL_PAIR_COOLDOWN, PROPOSAL_EMOTING_DURATION, + MAX_NPC_COUNT, MOVE_SPEED, +} from '@dflike/shared'; + +const DEFAULTS: TunableConstants = { + TICK_RATE, BROADCAST_EVERY_N_TICKS, + HUNGER_DECAY_PER_TICK, ENERGY_DECAY_PER_TICK, HUNGER_THRESHOLD, ENERGY_THRESHOLD, NEED_RECOVERY_RATE, + SLEEP_ENERGY_RECOVERY_PER_TICK, SLEEP_HUNGER_DECAY_MULTIPLIER, SLEEP_WAKE_THRESHOLD, SLEEP_VOLUNTARY_ENERGY_THRESHOLD, + PRODUCTIVITY_DECAY_PER_TICK, PRODUCTIVITY_THRESHOLD, PRODUCTIVITY_RECOVERY_RATE, + DAY_NIGHT_RATIO, DAY_HOURS, SUNSET_DURATION_HOURS, SUNRISE_DURATION_HOURS, NIGHT_DARKNESS, + AWARENESS_RADIUS, FACING_DURATION, PAUSING_DURATION, EMOTING_DURATION, + SOCIAL_GLOBAL_COOLDOWN, SOCIAL_PAIR_COOLDOWN, PROPOSAL_EMOTING_DURATION, + MAX_NPC_COUNT, MOVE_SPEED, +}; + +export function createRuntimeConstants() { + const current: TunableConstants = { ...DEFAULTS }; + + return { + get(key: K): TunableConstants[K] { + return current[key]; + }, + + getAll(): TunableConstants { + return { ...current }; + }, + + update(key: TunableKey, value: number): boolean { + if (!(key in DEFAULTS)) return false; + current[key] = value; + return true; + }, + + resetDefaults(): void { + Object.assign(current, DEFAULTS); + }, + + getDefaults(): TunableConstants { + return { ...DEFAULTS }; + }, + }; +} + +export type RuntimeConstants = ReturnType;