diff --git a/templates/base/server/.hathora/methods.ts.hbs b/templates/base/server/.hathora/methods.ts.hbs index 7945ad2f..06e73e9c 100644 --- a/templates/base/server/.hathora/methods.ts.hbs +++ b/templates/base/server/.hathora/methods.ts.hbs @@ -32,6 +32,8 @@ export interface Methods { {{@key}}(state: T, userId: UserId, ctx: Context, request: {{makeRequestName @key}}): Response; {{/each}} getUserState(state: T, userId: UserId): UserState; + onUserJoin?(state: T, userId: UserId, ctx: Context): void; + onUserLeave?(state: T, userId: UserId, ctx: Context): void; {{#if tick}} onTick(state: T, ctx: Context, timeDelta: number): void; {{/if}} diff --git a/templates/base/server/.hathora/store.ts.hbs b/templates/base/server/.hathora/store.ts.hbs index 941366a1..205f11c3 100644 --- a/templates/base/server/.hathora/store.ts.hbs +++ b/templates/base/server/.hathora/store.ts.hbs @@ -103,14 +103,17 @@ const store: Application = { } } sendSnapshot(roomId, userId); + const { impl, chance } = rooms.get(roomId)!; + impl._onUserJoin(userId, ctx(chance, Date.now(), roomId)); }, async unsubscribeUser(roomId: RoomId, userId: UserId): Promise { if (!rooms.has(roomId)) { return; } - const subscribers = rooms.get(roomId)!.subscriptions; - subscribers.delete(userId); - if (subscribers.size === 0) { + const { impl, chance, subscriptions } = rooms.get(roomId)!; + impl._onUserLeave(userId, ctx(chance, Date.now(), roomId)); + subscriptions.delete(userId); + if (subscriptions.size === 0) { changedStates.delete(roomId); pendingMessages.delete(roomId); } diff --git a/templates/base/server/.hathora/wrapper.ts.hbs b/templates/base/server/.hathora/wrapper.ts.hbs index e903f2ea..c7cee095 100644 --- a/templates/base/server/.hathora/wrapper.ts.hbs +++ b/templates/base/server/.hathora/wrapper.ts.hbs @@ -41,6 +41,18 @@ export class ImplWrapper { const impl = await getLatestImpl(); return impl.getUserState(onChange.target(this.state), userId); } + public async _onUserJoin(userId: UserId, ctx: Context) { + const impl = await getLatestImpl(); + if (impl.onUserJoin !== undefined) { + await impl.onUserJoin(this.state, userId, ctx); + } + } + public async _onUserLeave(userId: UserId, ctx: Context) { + const impl = await getLatestImpl(); + if (impl.onUserLeave !== undefined) { + await impl.onUserLeave(this.state, userId, ctx); + } + } public changedAt(): number | undefined { const res = this._changedAt; this._changedAt = undefined;