From e6be827d5703beac3f7c14324d4f812e1de65b24 Mon Sep 17 00:00:00 2001 From: Joey Nenni Date: Fri, 7 Feb 2025 15:53:41 -0600 Subject: [PATCH 1/2] feat: added shutdown method --- templates/base/server/.hathora/store.ts.hbs | 3 ++- templates/bootstrap/server/impl.ts.hbs | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/templates/base/server/.hathora/store.ts.hbs b/templates/base/server/.hathora/store.ts.hbs index d74e002d..132cf7d9 100644 --- a/templates/base/server/.hathora/store.ts.hbs +++ b/templates/base/server/.hathora/store.ts.hbs @@ -65,8 +65,9 @@ setInterval(() => { pendingMessages.clear(); }, {{#if tick}}{{tick}}{{else}}50{{/if}}); setInterval(() => { - rooms.forEach(({ subscriptions }, stateId) => { + rooms.forEach(async ({ impl, subscriptions }, stateId) => { if (subscriptions.size === 0) { + await impl.onShutdown(ctxNoEvents(chance, time, stateId)); rooms.delete(stateId); log.unload(stateId); } diff --git a/templates/bootstrap/server/impl.ts.hbs b/templates/bootstrap/server/impl.ts.hbs index 48f962dc..66721393 100644 --- a/templates/bootstrap/server/impl.ts.hbs +++ b/templates/bootstrap/server/impl.ts.hbs @@ -37,6 +37,7 @@ export class Impl implements Methods { {{#if tick}} onTick(state: InternalState, ctx: Context, timeDelta: number): void {} {{/if}} + onShutdown(state: InternalState, ctx: Context): void {} } {{#*inline "renderDefault"}} {{#if (eq type "array")}} From d680261ed564cb7d767d9127f92b1799ca27c5c0 Mon Sep 17 00:00:00 2001 From: Joey Nenni Date: Fri, 7 Feb 2025 16:15:24 -0600 Subject: [PATCH 2/2] fix: additional fixes --- package-lock.json | 4 ++-- package.json | 2 +- templates/base/server/.hathora/methods.ts.hbs | 1 + templates/base/server/.hathora/store.ts.hbs | 21 +++++++++---------- templates/base/server/.hathora/wrapper.ts.hbs | 4 ++++ 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 242d694a..819418d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "hathora", - "version": "0.12.2", + "version": "0.13.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "hathora", - "version": "0.12.2", + "version": "0.13.0", "license": "MIT", "dependencies": { "@node-loader/core": "hpx7/node-loader-core#patch-1", diff --git a/package.json b/package.json index 55728783..d28cce7f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hathora", - "version": "0.12.2", + "version": "0.13.0", "description": "Multiplayer game framework", "bin": "lib/cli.js", "files": [ diff --git a/templates/base/server/.hathora/methods.ts.hbs b/templates/base/server/.hathora/methods.ts.hbs index cfb682d8..77fa7492 100644 --- a/templates/base/server/.hathora/methods.ts.hbs +++ b/templates/base/server/.hathora/methods.ts.hbs @@ -37,4 +37,5 @@ export interface Methods { {{#if tick}} onTick(state: T, ctx: Context, timeDelta: number): void; {{/if}} + onShutdown(state: T, ctx: Context): void; } diff --git a/templates/base/server/.hathora/store.ts.hbs b/templates/base/server/.hathora/store.ts.hbs index 132cf7d9..27fee661 100644 --- a/templates/base/server/.hathora/store.ts.hbs +++ b/templates/base/server/.hathora/store.ts.hbs @@ -45,15 +45,13 @@ setInterval(() => { {{#if tick}} const currTime = Date.now(); rooms.forEach(async ({ impl, chance, subscriptions }, stateId) => { - if (subscriptions.size > 0) { - const timeDelta = currTime - prevUpdateTime; - await impl.onTick(ctx(chance, currTime, stateId), timeDelta / 1000); - const changedAt = impl.changedAt(); - if (changedAt !== undefined) { - changedStates.set(stateId, changedAt); - pendingMessages.delete(stateId); - log.append(stateId, currTime, new Writer().writeUInt8(0xff).writeUVarint(timeDelta).toBuffer()); - } + const timeDelta = currTime - prevUpdateTime; + await impl.onTick(ctx(chance, currTime, stateId), timeDelta / 1000); + const changedAt = impl.changedAt(); + if (changedAt !== undefined) { + changedStates.set(stateId, changedAt); + pendingMessages.delete(stateId); + log.append(stateId, currTime, new Writer().writeUInt8(0xff).writeUVarint(timeDelta).toBuffer()); } }); prevUpdateTime = currTime; @@ -65,9 +63,10 @@ setInterval(() => { pendingMessages.clear(); }, {{#if tick}}{{tick}}{{else}}50{{/if}}); setInterval(() => { - rooms.forEach(async ({ impl, subscriptions }, stateId) => { + rooms.forEach(async ({ impl, chance, subscriptions }, stateId) => { if (subscriptions.size === 0) { - await impl.onShutdown(ctxNoEvents(chance, time, stateId)); + const currTime = Date.now(); + await impl.onShutdown(ctxNoEvents(chance, currTime, stateId)); rooms.delete(stateId); log.unload(stateId); } diff --git a/templates/base/server/.hathora/wrapper.ts.hbs b/templates/base/server/.hathora/wrapper.ts.hbs index e903f2ea..f2e35e88 100644 --- a/templates/base/server/.hathora/wrapper.ts.hbs +++ b/templates/base/server/.hathora/wrapper.ts.hbs @@ -37,6 +37,10 @@ export class ImplWrapper { restoreSideEffectFunctions(); } {{/if}} + public async onShutdown(ctx: Context) { + const impl = await getLatestImpl(); + return impl.onShutdown(this.state, ctx); + } public async getUserState(userId: UserId) { const impl = await getLatestImpl(); return impl.getUserState(onChange.target(this.state), userId);