Skip to content

Commit

Permalink
Tick tock
Browse files Browse the repository at this point in the history
  • Loading branch information
Phoscur committed May 17, 2024
1 parent cd9fc19 commit 7f1f7a5
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 37 deletions.
1 change: 1 addition & 0 deletions engine/src/lib/Economy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export class Economy<
readonly resources: EnergyCalculation<ResourceType>;

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<ResourceType>,
readonly buildings: Building<ResourceType, BuildingType>[] = [],
Expand Down
3 changes: 2 additions & 1 deletion engine/src/lib/Phlame.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
});
7 changes: 5 additions & 2 deletions engine/src/lib/Phlame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export type PhlameJSON<
UnitType extends BuildingIdentifier,
> = {
id: ID;
tick: TimeUnit;
stock: StockJSON<ResourceType>;
buildings: BuildingJSON<UnitType>[];
};
Expand Down Expand Up @@ -46,7 +47,8 @@ export class Phlame<ResourceType extends ResourceIdentifier, UnitType extends Bu
update(tick: TimeUnit) {
const { lastTick } = this;
this.tick = tick;
// TODO update economy
// TODO while checking actions
this.economy = this.economy.tick(tick - lastTick);
return this;
}

Expand All @@ -55,9 +57,10 @@ export class Phlame<ResourceType extends ResourceIdentifier, UnitType extends Bu
}

toJSON(): PhlameJSON<ResourceType, UnitType> {
const { id, economy } = this;
const { id, economy, tick } = this;
return {
id,
tick,
...economy.toJSON(),
};
}
Expand Down
6 changes: 2 additions & 4 deletions src/app/engine/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -23,7 +22,6 @@ export type PhlameEntity = Phlame<ResourceIdentifier, BuildingIdentifier>;

@injectable
export class EngineFactory {
#zeit = inject(Zeitgeber);
#resource = inject(ResourceFactory);
#building = inject(BuildingFactory);

Expand All @@ -36,16 +34,16 @@ export class EngineFactory {
createEntities(
es: PhlameJSON<ResourceIdentifier, BuildingIdentifier>[],
): Phlame<ResourceIdentifier, BuildingIdentifier>[] {
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<ResourceIdentifier>,
// TODO actions
buildings: BuildingJSON<BuildingIdentifier>[] = [],
): Phlame<ResourceIdentifier, BuildingIdentifier> {
const { tick } = this.#zeit();
return new Phlame(
id,
this.createEconomy({
Expand Down
8 changes: 4 additions & 4 deletions src/app/engine/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import { type EmpireEntity, EngineFactory } from './factory';
export function emptyEconomy(name: string) {
return new Economy<ResourceIdentifier, BuildingIdentifier>(name, emptyStock, defaultBuildings);
}
export function emptyPlanet(id: ID) {
return new Phlame<ResourceIdentifier, BuildingIdentifier>(id, emptyEconomy(`E${id}`));
export function emptyPlanet(id: ID, tick?: number) {
return new Phlame<ResourceIdentifier, BuildingIdentifier>(id, emptyEconomy(`E${id}`), [], tick);
}

export function emptyEmpire(id: ID, planetID: ID) {
return new Empire<ResourceIdentifier, BuildingIdentifier>(id, [emptyPlanet(planetID)]);
export function emptyEmpire(id: ID, planetID: ID, tick?: number) {
return new Empire<ResourceIdentifier, BuildingIdentifier>(id, [emptyPlanet(planetID, tick)]);
}

export class Repository<T extends Entity> {
Expand Down
16 changes: 7 additions & 9 deletions src/app/game.element.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,13 @@ export const gameToJSX = (t: I18n, empire: Empire<ResourceIdentifier, BuildingId
<>
<empire-ctx id={empire.id} entities={JSON.stringify(empire.toJSON().entities)}>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<ph-ctx id={empire.entities[0].id}>
<ph-planet>{planetToJSX(t, empire.entities[0])}</ph-planet>
</ph-ctx>
<div class="">
<ph-planet />
</div>
<div class="">
<ph-planet />
</div>
{empire.entities.map((p) => (
<>
<ph-ctx id={p.id}>
<ph-planet>{planetToJSX(t, p)}</ph-planet>
</ph-ctx>
</>
))}
</div>
</empire-ctx>
</>
Expand Down
45 changes: 30 additions & 15 deletions src/engine.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,29 +55,44 @@ export class EngineService {
return this;
}

/**
* @param sid SessionID
* @returns {Promise<number>} 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;
Expand All @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions src/render.server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
18 changes: 16 additions & 2 deletions src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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('<h1>Sum sum</h1>'));
.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(`<h1>Ouch, Error: ${code}</h1>`);
}
// TODO engine.update&save()
// but it's actually not worth updating the snapshot as long as nothing changed besides the tick
}
return c.html(`<h1>Sum sum ${engine.time.tick}</h1>`);
});

const { createRoutes } = await import('./routes');
createRoutes(app);
Expand Down

0 comments on commit 7f1f7a5

Please sign in to comment.