diff --git a/src/client/transport/local.test.js b/src/client/transport/local.test.js index 54b184641..1fa0ea227 100644 --- a/src/client/transport/local.test.js +++ b/src/client/transport/local.test.js @@ -10,6 +10,7 @@ import { createStore } from 'redux'; import { LocalTransport, LocalMaster, Local, GetBotPlayer } from './local'; import { makeMove, gameEvent } from '../../core/action-creators'; import { CreateGameReducer } from '../../core/reducer'; +import { ProcessGameConfig } from '../../core/game'; import { InitializeGame } from '../../core/initialize'; import { Client } from '../client'; import { RandomBot } from '../../ai/random-bot'; @@ -121,6 +122,33 @@ describe('GetBotPlayer', () => { }); }); +describe('Local', () => { + test('transports for same game use shared master', () => { + const gameKey = {}; + const game = ProcessGameConfig(gameKey); + const transport1 = Local()({ game, gameKey }); + const transport2 = Local()({ game, gameKey }); + expect(transport1.master).toBe(transport2.master); + }); + + test('transports use shared master with bots', () => { + const gameKey = {}; + const game = ProcessGameConfig(gameKey); + const bots = {}; + const transport1 = Local({ bots })({ game, gameKey }); + const transport2 = Local({ bots })({ game, gameKey }); + expect(transport1.master).toBe(transport2.master); + }); + + test('transports use different master for different bots', () => { + const gameKey = {}; + const game = ProcessGameConfig(gameKey); + const transport1 = Local({ bots: {} })({ game, gameKey }); + const transport2 = Local({ bots: {} })({ game, gameKey }); + expect(transport1.master).not.toBe(transport2.master); + }); +}); + describe('LocalMaster', () => { const game = {}; const master = new LocalMaster({ game }); diff --git a/src/client/transport/local.ts b/src/client/transport/local.ts index 0f2b6b58e..ffea3fcd0 100644 --- a/src/client/transport/local.ts +++ b/src/client/transport/local.ts @@ -43,7 +43,7 @@ export function GetBotPlayer(state: State, bots: Record) { interface LocalMasterOpts { game: Game; - bots: Record; + bots?: Record; } /** @@ -234,19 +234,32 @@ export class LocalTransport extends Transport { } } -const localMasters = new Map(); -export function Local(opts?: Pick) { +/** + * Global map storing local master instances. + */ +const localMasters: Map< + Game, + { master: LocalMaster; bots: LocalMasterOpts['bots'] } +> = new Map(); + +/** + * Create a local transport. + */ +export function Local({ bots }: Pick = {}) { return (transportOpts: TransportOpts) => { + const { gameKey, game } = transportOpts; let master: LocalMaster; - if (localMasters.has(transportOpts.gameKey) && !opts) { - master = localMasters.get(transportOpts.gameKey); - } else { - master = new LocalMaster({ - game: transportOpts.game, - bots: opts && opts.bots, - }); - localMasters.set(transportOpts.gameKey, master); + if (localMasters.has(gameKey)) { + const instance = localMasters.get(gameKey); + if (instance.bots === bots) { + master = instance.master; + } + } + + if (!master) { + master = new LocalMaster({ game, bots }); + localMasters.set(gameKey, { master, bots }); } return new LocalTransport({ master, ...transportOpts });