diff --git a/src/app/app.element.tsx b/src/app/app.element.tsx index d3f9ca4..896ab6e 100644 --- a/src/app/app.element.tsx +++ b/src/app/app.element.tsx @@ -97,7 +97,8 @@ export class AppElement extends HTMLElement { } const logger = this.#logger(); const i18n = this.#i18n(); - if (!i18n.set(newValue as Language) && !oldValue) { + const updated = i18n.set(newValue as Language); + if (!updated || !oldValue) { logger.log('App I18n:', newValue, '[no update]'); return; } diff --git a/src/app/signals/zeitgeber.ts b/src/app/signals/zeitgeber.ts index 83207a2..b0eab97 100644 --- a/src/app/signals/zeitgeber.ts +++ b/src/app/signals/zeitgeber.ts @@ -3,11 +3,16 @@ import { effect } from './effect'; type TimeoutQueueFunction = (callback: () => void, ms: number) => number; +export class Zeit { + readonly tick: number = 0; + readonly time: number = 0; +} + /** * The time-giver * takes care of time and tick cycles */ -export class Zeitgeber { +export class Zeitgeber implements Zeit { private zeitgeist: { tick: Signal.State; time: Signal.State; diff --git a/src/engine.server.ts b/src/engine.server.ts new file mode 100644 index 0000000..55d64d7 --- /dev/null +++ b/src/engine.server.ts @@ -0,0 +1,29 @@ +import { injectable, inject, Injector } from '@joist/di'; +import { Zeit, Zeitgeber } from './app/signals/zeitgeber'; +import { Debug } from './app/debug.element'; + +@injectable +export class EngineService { + #logger = inject(Debug); + #zeit = inject(Zeitgeber); + + get time(): Zeit { + const zeit = this.#zeit(); + this.#logger().log('Tick', zeit.tick, zeit.time); + return zeit; + } + + start() { + const zeit = this.#zeit(); + this.#logger().log('Start', zeit.tick, zeit.time); + zeit.start(); + } +} + +/** + * TODO? this probably won't stay Singleton + * One injector per open socket? + * Injector lifetime? + */ +export const engineInjector = new Injector(); +engineInjector.get(EngineService).start(); diff --git a/src/main.ts b/src/main.ts index 8d450fa..0969fe1 100644 --- a/src/main.ts +++ b/src/main.ts @@ -9,11 +9,11 @@ import { EnergyElement, ResourceElement, ResourcesElement } from './app/resource import { LanguageSelectDropdownElement } from './app/language.dropdown.element'; customElements.define('debug-ctx', DebugCtx); +customElements.define('app-root', AppElement); customElements.define('zeit-ctx', ZeitElement); customElements.define('game-ctx', GameElement); customElements.define('empire-ctx', EmpireElement); customElements.define('ph-ctx', PhlameElement); -customElements.define('app-root', AppElement); customElements.define('app-i18n-select', LanguageSelectDropdownElement); customElements.define('app-clock', ClockElement); customElements.define('app-percent', PercentElement); diff --git a/src/render.server.tsx b/src/render.server.tsx index 7e885b9..cb6e3ae 100644 --- a/src/render.server.tsx +++ b/src/render.server.tsx @@ -1,6 +1,8 @@ import { raw } from 'hono/html'; import { appToJSX } from './app/app.element'; import { defaultLang, I18n, Language, useTranslations } from './app/i18n'; +import { engineInjector, EngineService } from './engine.server'; +import { Injector } from '@joist/di'; const AppRoot = ( t: I18n, @@ -17,15 +19,18 @@ const AppRoot = ( export class GameRenderer { static TITLE_PLACEHOLDER = ''; static APP_ROOT_PLACEHOLDER = ''; - constructor(readonly htmlFrame: string, readonly title: string, readonly lang: Language) {} - render(tick = 42, time = Date.now()): string { - const t = useTranslations(this.lang); - return this.htmlFrame - .replace(GameRenderer.TITLE_PLACEHOLDER, this.title) + render(i: Injector, htmlFrame: string, title: string, lang: Language): string { + const t = useTranslations(lang); + + const engine = i.get(EngineService); + const zeit = engine.time; + + return htmlFrame + .replace(GameRenderer.TITLE_PLACEHOLDER, title) .replace( GameRenderer.APP_ROOT_PLACEHOLDER, - raw(AppRoot(t, this.title, tick, time, this.lang)), + raw(AppRoot(t, title, zeit.tick, zeit.time, lang)), ); } } diff --git a/src/server.ts b/src/server.ts index 7920030..7cccedb 100644 --- a/src/server.ts +++ b/src/server.ts @@ -6,6 +6,7 @@ import './html.element.server'; import { GameRenderer } from './render.server'; import { defaultLang, Language, useTranslations } from './app/i18n'; import { getCookie, setCookie } from 'hono/cookie'; +import { engineInjector } from './engine.server'; const isProd = process.env['NODE_ENV'] === 'production'; const distFolder = process.env['BUILD_DIR'] || 'dist/phlame'; @@ -22,12 +23,16 @@ const t = useTranslations(defaultLang); if (isProd) { const index = await html(); - const game = new GameRenderer(index, 'Production Phlame', defaultLang); - app.get('/*', (c) => c.html(game.render())); + const game = new GameRenderer(); + app.get('/*', (c) => + c.html(game.render(engineInjector, index, 'Production Phlame', defaultLang)), + ); } else { + const game = new GameRenderer(); + app.get('/*', async (c) => { const lang = (getCookie(c, 'lang') as Language) || defaultLang; - return c.html(new GameRenderer(await html(), 'JIT Phlame', lang).render()); + return c.html(game.render(engineInjector, await html(), 'JIT Phlame', lang)); }); } export default app;