diff --git a/engine/src/lib/Economy.ts b/engine/src/lib/Economy.ts index 4668bc1..36cdf86 100644 --- a/engine/src/lib/Economy.ts +++ b/engine/src/lib/Economy.ts @@ -23,6 +23,7 @@ export class Economy< readonly resources: EnergyCalculation; constructor( + // TODO add/replace: readonly seed - binary or ID like/derived string readonly name: string, // TODO? remove unused - or use this as a type? - rather leave it to an actual entity resources: Stock, readonly buildings: Building[] = [], diff --git a/engine/src/lib/Phlame.spec.ts b/engine/src/lib/Phlame.spec.ts index f6fb129..ef85c61 100644 --- a/engine/src/lib/Phlame.spec.ts +++ b/engine/src/lib/Phlame.spec.ts @@ -71,5 +71,6 @@ describe('Phlame Entity', () => { expect(phlame.lastTick).to.eql(1); }); - // it.todo("should have env properties - e.g. base temperature to start from"); + // it.todo("should have env properties - e.g. base temperature and amounts of resources to start from"); + // idea: use parts of the ID for random data }); diff --git a/engine/src/lib/Phlame.ts b/engine/src/lib/Phlame.ts index f90972b..7844ce8 100644 --- a/engine/src/lib/Phlame.ts +++ b/engine/src/lib/Phlame.ts @@ -8,6 +8,7 @@ export type PhlameJSON< UnitType extends BuildingIdentifier, > = { id: ID; + tick: TimeUnit; stock: StockJSON; buildings: BuildingJSON[]; }; @@ -46,7 +47,8 @@ export class Phlame { - const { id, economy } = this; + const { id, economy, tick } = this; return { id, + tick, ...economy.toJSON(), }; } diff --git a/src/app/engine/factory.ts b/src/app/engine/factory.ts index 7031130..fa98304 100644 --- a/src/app/engine/factory.ts +++ b/src/app/engine/factory.ts @@ -14,7 +14,6 @@ import { type PhlameJSON, EmpireJSON, } from '@phlame/engine'; -import { Zeitgeber } from '../signals/zeitgeber'; import { ResourceFactory, type ResourceIdentifier } from './resources'; import { BuildingFactory, type BuildingIdentifier } from './buildings'; @@ -23,7 +22,6 @@ export type PhlameEntity = Phlame; @injectable export class EngineFactory { - #zeit = inject(Zeitgeber); #resource = inject(ResourceFactory); #building = inject(BuildingFactory); @@ -36,16 +34,16 @@ export class EngineFactory { createEntities( es: PhlameJSON[], ): Phlame[] { - return es.map((p) => this.createPhlame(p.id, p.stock, p.buildings)); + return es.map((p) => this.createPhlame(p.id, p.tick, p.stock, p.buildings)); } createPhlame( id: ID, + tick: number, stock: StockJSON, // TODO actions buildings: BuildingJSON[] = [], ): Phlame { - const { tick } = this.#zeit(); return new Phlame( id, this.createEconomy({ diff --git a/src/app/engine/services.ts b/src/app/engine/services.ts index 157e2db..46ad919 100644 --- a/src/app/engine/services.ts +++ b/src/app/engine/services.ts @@ -8,12 +8,12 @@ import { type EmpireEntity, EngineFactory } from './factory'; export function emptyEconomy(name: string) { return new Economy(name, emptyStock, defaultBuildings); } -export function emptyPlanet(id: ID) { - return new Phlame(id, emptyEconomy(`E${id}`)); +export function emptyPlanet(id: ID, tick?: number) { + return new Phlame(id, emptyEconomy(`E${id}`), [], tick); } -export function emptyEmpire(id: ID, planetID: ID) { - return new Empire(id, [emptyPlanet(planetID)]); +export function emptyEmpire(id: ID, planetID: ID, tick?: number) { + return new Empire(id, [emptyPlanet(planetID, tick)]); } export class Repository { diff --git a/src/app/game.element.tsx b/src/app/game.element.tsx index 1366868..d2e89c3 100644 --- a/src/app/game.element.tsx +++ b/src/app/game.element.tsx @@ -13,15 +13,13 @@ export const gameToJSX = (t: I18n, empire: Empire
- - {planetToJSX(t, empire.entities[0])} - -
- -
-
- -
+ {empire.entities.map((p) => ( + <> + + {planetToJSX(t, p)} + + + ))}
diff --git a/src/engine.server.ts b/src/engine.server.ts index 4194a06..e98727e 100644 --- a/src/engine.server.ts +++ b/src/engine.server.ts @@ -55,29 +55,44 @@ export class EngineService { return this; } + /** + * @param sid SessionID + * @returns {Promise} error code + */ async load(sid: string) { const zeit = this.#zeit(); const persistence = this.#persistence(); - // TODO try {} catch (JSON parse) - const { - zeit: { time, tick }, - empire, - } = await persistence.loadSession(sid); - console.log('Loading', tick, 'from', time, sid, empire.id, empire.entities[0]?.id); - /* if (tick && tick !== zeit.tick) { - zeit.stop(); - // TODO catch up ticks - zeit.start(time, tick); - }*/ - this.#empire().setupFromJSON(empire); + try { + const session = await persistence.loadSession(sid); + const { + zeit: { time, tick }, + empire, + } = session; + console.log('Current', zeit.tick, 'at ', zeit.time); + // Actually Session(User) Empire & MainPlanet could share an ID, then it could be ommitted for log readability? + console.log('Loading', tick, 'from', time, sid); //, empire.id, empire.entities[0]?.id); + console.log('Created', zeit.tick - tick, 'ticks ago.'); + /* if (tick && tick !== zeit.tick) { + zeit.stop(); + // TODO catch up ticks with actions + zeit.start(time, tick); + }*/ + this.#empire().setupFromJSON(empire); + + return 0; + } catch (e: any) { + this.#logger().log('Error loading session', sid, e?.code, e); + return e?.code || 1; + } } async generateSession() { + const zeit = this.#zeit(); const persistence = this.#persistence(); const sid = persistence.generateID(); const eid = persistence.generateID(); const pid = persistence.generateID(); - const session = this.createSession(sid, eid, pid); + const session = this.createSession(sid, eid, pid, zeit.tick); await this.saveSession(session); this.#empire().setup(session.empire); return session; @@ -92,8 +107,8 @@ export class EngineService { }); } - createSession(sid: string, eid: string, pid: string): Session { - const empire = emptyEmpire(eid, pid); + createSession(sid: string, eid: string, pid: string, tick?: number): Session { + const empire = emptyEmpire(eid, pid, tick); return { sid, empire, diff --git a/src/render.server.tsx b/src/render.server.tsx index e4a6aa2..5650d22 100644 --- a/src/render.server.tsx +++ b/src/render.server.tsx @@ -28,6 +28,11 @@ export class GameRenderer { const engine = i.get(EngineService); const zeit = engine.time; const empire = engine.empire; + // TODO? empire.update(zeit.tick) + for (const entity of empire.entities) { + entity.update(zeit.tick); + } + // console.log('Render', zeit.tick, empire.toString()); return htmlFrame .replace(GameRenderer.TITLE_PLACEHOLDER, title) diff --git a/src/server.ts b/src/server.ts index 54fda3b..6ad30d8 100644 --- a/src/server.ts +++ b/src/server.ts @@ -7,7 +7,6 @@ import './html.element.server'; import { defaultLang, Language } from './app/i18n'; import { GameRenderer } from './render.server'; import { EngineService, startup } from './engine.server'; -import { DataService } from './data.server'; const isProd = process.env['NODE_ENV'] === 'production'; const distFolder = process.env['BUILD_DIR'] || 'dist/phlame'; @@ -44,7 +43,22 @@ async function sessionHelper(engine: EngineService, ctx: Context) { const app = new Hono() .use('/assets/*', serveStatic({ root: isProd ? `${distFolder}/` : './' })) // path must end with '/' - .get('/sum', (c) => c.html('

Sum sum

')); + .get('/sum', async (c) => { + const engine = engineInjector.get(EngineService); + const lang = (getCookie(c, 'lang') as Language) || defaultLang; + const sid = getCookie(c, 'sid'); + if (sid) { + const code = await engine.load(sid); + // TODO engine.save + if (0 !== code) { + c.status(code >= 200 ? code : 500); + return c.html(`

Ouch, Error: ${code}

`); + } + // TODO engine.update&save() + // but it's actually not worth updating the snapshot as long as nothing changed besides the tick + } + return c.html(`

Sum sum ${engine.time.tick}

`); + }); const { createRoutes } = await import('./routes'); createRoutes(app);