@mnbroatch/boardgame.io 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +102 -0
- package/ai/package.json +7 -0
- package/client/package.json +7 -0
- package/core/package.json +7 -0
- package/debug/package.json +7 -0
- package/dist/boardgameio.es.js +14238 -0
- package/dist/boardgameio.js +14277 -0
- package/dist/boardgameio.min.js +16 -0
- package/dist/cjs/Debug-9d141c06.js +9586 -0
- package/dist/cjs/ai-e0e8a768.js +377 -0
- package/dist/cjs/ai.js +20 -0
- package/dist/cjs/client-76dec77b.js +258 -0
- package/dist/cjs/client-a22d7500.js +524 -0
- package/dist/cjs/client.js +26 -0
- package/dist/cjs/core.js +52 -0
- package/dist/cjs/debug.js +18 -0
- package/dist/cjs/filter-player-view-bb02e2f6.js +89 -0
- package/dist/cjs/initialize-267fcd69.js +61 -0
- package/dist/cjs/internal.js +25 -0
- package/dist/cjs/master-2904879d.js +320 -0
- package/dist/cjs/master.js +18 -0
- package/dist/cjs/multiplayer.js +23 -0
- package/dist/cjs/plugin-random-7425844d.js +229 -0
- package/dist/cjs/plugins.js +59 -0
- package/dist/cjs/react-native.js +182 -0
- package/dist/cjs/react.js +727 -0
- package/dist/cjs/reducer-16eec232.js +1203 -0
- package/dist/cjs/server.js +4087 -0
- package/dist/cjs/socketio-7a0837eb.js +478 -0
- package/dist/cjs/testing.js +30 -0
- package/dist/cjs/transport-b1874dfa.js +37 -0
- package/dist/cjs/turn-order-b2ff8740.js +1136 -0
- package/dist/cjs/util-fcfd8fb8.js +140 -0
- package/dist/esm/Debug-0141fe2d.js +9577 -0
- package/dist/esm/ai-5c06e761.js +371 -0
- package/dist/esm/ai.js +8 -0
- package/dist/esm/client-2e653027.js +522 -0
- package/dist/esm/client-5f57c3f2.js +255 -0
- package/dist/esm/client.js +16 -0
- package/dist/esm/core.js +40 -0
- package/dist/esm/debug.js +10 -0
- package/dist/esm/filter-player-view-2c6cc96f.js +87 -0
- package/dist/esm/initialize-11d626ca.js +59 -0
- package/dist/esm/internal.js +10 -0
- package/dist/esm/master-fa8f2e43.js +318 -0
- package/dist/esm/master.js +10 -0
- package/dist/esm/multiplayer.js +14 -0
- package/dist/esm/plugin-random-087f861e.js +226 -0
- package/dist/esm/plugins.js +55 -0
- package/dist/esm/react-native.js +173 -0
- package/dist/esm/react.js +716 -0
- package/dist/esm/reducer-c46da7e5.js +1198 -0
- package/dist/esm/socketio-c22ffa65.js +455 -0
- package/dist/esm/testing.js +26 -0
- package/dist/esm/transport-ce07b771.js +35 -0
- package/dist/esm/turn-order-376d315e.js +1091 -0
- package/dist/esm/util-b6147cef.js +135 -0
- package/dist/types/packages/ai.d.ts +5 -0
- package/dist/types/packages/client.d.ts +3 -0
- package/dist/types/packages/core.d.ts +5 -0
- package/dist/types/packages/debug.d.ts +2 -0
- package/dist/types/packages/internal.d.ts +8 -0
- package/dist/types/packages/master.d.ts +2 -0
- package/dist/types/packages/multiplayer.d.ts +3 -0
- package/dist/types/packages/plugins.d.ts +3 -0
- package/dist/types/packages/react-native.d.ts +2 -0
- package/dist/types/packages/react.d.ts +3 -0
- package/dist/types/packages/server.d.ts +6 -0
- package/dist/types/packages/testing.d.ts +1 -0
- package/dist/types/src/ai/ai.d.ts +53 -0
- package/dist/types/src/ai/ai.test.d.ts +1 -0
- package/dist/types/src/ai/bot.d.ts +40 -0
- package/dist/types/src/ai/mcts-bot.d.ts +60 -0
- package/dist/types/src/ai/random-bot.d.ts +27 -0
- package/dist/types/src/client/client.d.ts +104 -0
- package/dist/types/src/client/client.test.d.ts +1 -0
- package/dist/types/src/client/debug/tests/debug.test.d.ts +1 -0
- package/dist/types/src/client/manager.d.ts +61 -0
- package/dist/types/src/client/react.d.ts +75 -0
- package/dist/types/src/client/react.ssr.test.d.ts +4 -0
- package/dist/types/src/client/react.test.d.ts +1 -0
- package/dist/types/src/client/transport/dummy.d.ts +18 -0
- package/dist/types/src/client/transport/local.d.ts +59 -0
- package/dist/types/src/client/transport/local.test.d.ts +1 -0
- package/dist/types/src/client/transport/socketio.d.ts +45 -0
- package/dist/types/src/client/transport/socketio.test.d.ts +1 -0
- package/dist/types/src/client/transport/transport.d.ts +50 -0
- package/dist/types/src/client/transport/transport.test.d.ts +1 -0
- package/dist/types/src/core/action-creators.d.ts +144 -0
- package/dist/types/src/core/action-types.d.ts +10 -0
- package/dist/types/src/core/backwards-compatibility.d.ts +12 -0
- package/dist/types/src/core/constants.d.ts +6 -0
- package/dist/types/src/core/errors.d.ts +15 -0
- package/dist/types/src/core/flow.d.ts +28 -0
- package/dist/types/src/core/flow.test.d.ts +1 -0
- package/dist/types/src/core/game-methods.d.ts +9 -0
- package/dist/types/src/core/game.d.ts +26 -0
- package/dist/types/src/core/game.test.d.ts +1 -0
- package/dist/types/src/core/initialize.d.ts +9 -0
- package/dist/types/src/core/logger.d.ts +2 -0
- package/dist/types/src/core/player-view.d.ts +7 -0
- package/dist/types/src/core/player-view.test.d.ts +1 -0
- package/dist/types/src/core/reducer.d.ts +155 -0
- package/dist/types/src/core/reducer.test.d.ts +1 -0
- package/dist/types/src/core/turn-order.d.ts +179 -0
- package/dist/types/src/core/turn-order.test.d.ts +8 -0
- package/dist/types/src/lobby/client.d.ts +194 -0
- package/dist/types/src/lobby/client.test.d.ts +1 -0
- package/dist/types/src/lobby/connection.d.ts +44 -0
- package/dist/types/src/lobby/connection.test.d.ts +1 -0
- package/dist/types/src/lobby/create-match-form.d.ts +26 -0
- package/dist/types/src/lobby/login-form.d.ts +23 -0
- package/dist/types/src/lobby/match-instance.d.ts +31 -0
- package/dist/types/src/lobby/react.d.ts +113 -0
- package/dist/types/src/lobby/react.ssr.test.d.ts +4 -0
- package/dist/types/src/lobby/react.test.d.ts +1 -0
- package/dist/types/src/master/filter-player-view.d.ts +96 -0
- package/dist/types/src/master/filter-player-view.test.d.ts +1 -0
- package/dist/types/src/master/master.d.ts +94 -0
- package/dist/types/src/master/master.test.d.ts +1 -0
- package/dist/types/src/plugins/events/events.d.ts +54 -0
- package/dist/types/src/plugins/events/events.test.d.ts +1 -0
- package/dist/types/src/plugins/main.d.ts +75 -0
- package/dist/types/src/plugins/main.test.d.ts +1 -0
- package/dist/types/src/plugins/plugin-events.d.ts +5 -0
- package/dist/types/src/plugins/plugin-immer.d.ts +7 -0
- package/dist/types/src/plugins/plugin-immer.test.d.ts +1 -0
- package/dist/types/src/plugins/plugin-log.d.ts +14 -0
- package/dist/types/src/plugins/plugin-log.test.d.ts +1 -0
- package/dist/types/src/plugins/plugin-player.d.ts +29 -0
- package/dist/types/src/plugins/plugin-player.test.d.ts +1 -0
- package/dist/types/src/plugins/plugin-random.d.ts +4 -0
- package/dist/types/src/plugins/plugin-serializable.d.ts +7 -0
- package/dist/types/src/plugins/plugin-serializable.test.d.ts +1 -0
- package/dist/types/src/plugins/random/random.alea.d.ts +19 -0
- package/dist/types/src/plugins/random/random.d.ts +54 -0
- package/dist/types/src/plugins/random/random.test.d.ts +1 -0
- package/dist/types/src/server/api.d.ts +13 -0
- package/dist/types/src/server/api.test.d.ts +1 -0
- package/dist/types/src/server/auth.d.ts +38 -0
- package/dist/types/src/server/auth.test.d.ts +1 -0
- package/dist/types/src/server/cors.d.ts +4 -0
- package/dist/types/src/server/cors.test.d.ts +1 -0
- package/dist/types/src/server/db/base.d.ts +192 -0
- package/dist/types/src/server/db/flatfile.d.ts +44 -0
- package/dist/types/src/server/db/flatfile.test.d.ts +1 -0
- package/dist/types/src/server/db/index.d.ts +4 -0
- package/dist/types/src/server/db/index.test.d.ts +1 -0
- package/dist/types/src/server/db/inmemory.d.ts +43 -0
- package/dist/types/src/server/db/inmemory.test.d.ts +1 -0
- package/dist/types/src/server/db/localstorage.d.ts +7 -0
- package/dist/types/src/server/db/localstorage.test.d.ts +1 -0
- package/dist/types/src/server/index.d.ts +68 -0
- package/dist/types/src/server/index.test.d.ts +1 -0
- package/dist/types/src/server/transport/pubsub/generic-pub-sub.d.ts +6 -0
- package/dist/types/src/server/transport/pubsub/in-memory-pub-sub.d.ts +7 -0
- package/dist/types/src/server/transport/pubsub/in-memory-pub-sub.test.d.ts +1 -0
- package/dist/types/src/server/transport/socketio-simultaneous.test.d.ts +1 -0
- package/dist/types/src/server/transport/socketio.d.ts +65 -0
- package/dist/types/src/server/transport/socketio.test.d.ts +1 -0
- package/dist/types/src/server/util.d.ts +35 -0
- package/dist/types/src/testing/mock-random.d.ts +15 -0
- package/dist/types/src/testing/mock-random.test.d.ts +1 -0
- package/dist/types/src/types.d.ts +387 -0
- package/internal/package.json +7 -0
- package/master/package.json +7 -0
- package/multiplayer/package.json +7 -0
- package/package.json +211 -0
- package/plugins/package.json +7 -0
- package/react/package.json +7 -0
- package/react-native/package.json +7 -0
- package/server/package.json +6 -0
- package/src/ai/ai.test.ts +433 -0
- package/src/ai/ai.ts +84 -0
- package/src/ai/bot.ts +122 -0
- package/src/ai/mcts-bot.ts +331 -0
- package/src/ai/random-bot.ts +20 -0
- package/src/client/client.test.ts +993 -0
- package/src/client/client.ts +588 -0
- package/src/client/debug/Debug.svelte +239 -0
- package/src/client/debug/Menu.svelte +65 -0
- package/src/client/debug/ai/AI.svelte +215 -0
- package/src/client/debug/ai/Options.svelte +48 -0
- package/src/client/debug/info/Info.svelte +22 -0
- package/src/client/debug/info/Item.svelte +24 -0
- package/src/client/debug/log/Log.svelte +157 -0
- package/src/client/debug/log/LogEvent.svelte +149 -0
- package/src/client/debug/log/LogMetadata.svelte +7 -0
- package/src/client/debug/log/PhaseMarker.svelte +27 -0
- package/src/client/debug/log/TurnMarker.svelte +23 -0
- package/src/client/debug/main/ClientSwitcher.svelte +59 -0
- package/src/client/debug/main/Controls.svelte +58 -0
- package/src/client/debug/main/Hotkey.svelte +84 -0
- package/src/client/debug/main/InteractiveFunction.svelte +85 -0
- package/src/client/debug/main/Main.svelte +121 -0
- package/src/client/debug/main/Move.svelte +68 -0
- package/src/client/debug/main/PlayerInfo.svelte +70 -0
- package/src/client/debug/mcts/Action.svelte +22 -0
- package/src/client/debug/mcts/MCTS.svelte +78 -0
- package/src/client/debug/mcts/Table.svelte +98 -0
- package/src/client/debug/tests/JSONTree.mock.svelte +3 -0
- package/src/client/debug/tests/debug.test.ts +183 -0
- package/src/client/debug/utils/shortcuts.js +50 -0
- package/src/client/debug/utils/shortcuts.test.js +49 -0
- package/src/client/manager.ts +177 -0
- package/src/client/react-native.js +136 -0
- package/src/client/react-native.test.js +229 -0
- package/src/client/react.ssr.test.tsx +24 -0
- package/src/client/react.test.tsx +213 -0
- package/src/client/react.tsx +192 -0
- package/src/client/transport/dummy.ts +19 -0
- package/src/client/transport/local.test.ts +353 -0
- package/src/client/transport/local.ts +230 -0
- package/src/client/transport/socketio.test.ts +328 -0
- package/src/client/transport/socketio.ts +210 -0
- package/src/client/transport/transport.test.ts +27 -0
- package/src/client/transport/transport.ts +95 -0
- package/src/core/action-creators.ts +159 -0
- package/src/core/action-types.ts +18 -0
- package/src/core/backwards-compatibility.ts +23 -0
- package/src/core/constants.ts +6 -0
- package/src/core/errors.ts +35 -0
- package/src/core/flow.test.ts +2433 -0
- package/src/core/flow.ts +897 -0
- package/src/core/game-methods.ts +9 -0
- package/src/core/game.test.ts +286 -0
- package/src/core/game.ts +114 -0
- package/src/core/initialize.ts +77 -0
- package/src/core/logger.test.js +90 -0
- package/src/core/logger.ts +18 -0
- package/src/core/player-view.test.ts +50 -0
- package/src/core/player-view.ts +39 -0
- package/src/core/reducer.test.ts +991 -0
- package/src/core/reducer.ts +532 -0
- package/src/core/turn-order.test.ts +1123 -0
- package/src/core/turn-order.ts +473 -0
- package/src/lobby/client.test.ts +385 -0
- package/src/lobby/client.ts +358 -0
- package/src/lobby/connection.test.ts +207 -0
- package/src/lobby/connection.ts +162 -0
- package/src/lobby/create-match-form.tsx +122 -0
- package/src/lobby/login-form.tsx +75 -0
- package/src/lobby/match-instance.tsx +135 -0
- package/src/lobby/react.ssr.test.tsx +22 -0
- package/src/lobby/react.test.tsx +594 -0
- package/src/lobby/react.tsx +402 -0
- package/src/master/filter-player-view.test.ts +381 -0
- package/src/master/filter-player-view.ts +102 -0
- package/src/master/master.test.ts +1068 -0
- package/src/master/master.ts +492 -0
- package/src/plugins/events/events.test.ts +108 -0
- package/src/plugins/events/events.ts +209 -0
- package/src/plugins/main.test.ts +411 -0
- package/src/plugins/main.ts +314 -0
- package/src/plugins/plugin-events.ts +40 -0
- package/src/plugins/plugin-immer.test.ts +86 -0
- package/src/plugins/plugin-immer.ts +37 -0
- package/src/plugins/plugin-log.test.ts +37 -0
- package/src/plugins/plugin-log.ts +40 -0
- package/src/plugins/plugin-player.test.ts +172 -0
- package/src/plugins/plugin-player.ts +100 -0
- package/src/plugins/plugin-random.ts +40 -0
- package/src/plugins/plugin-serializable.test.ts +40 -0
- package/src/plugins/plugin-serializable.ts +55 -0
- package/src/plugins/random/random.alea.ts +109 -0
- package/src/plugins/random/random.test.ts +167 -0
- package/src/plugins/random/random.ts +198 -0
- package/src/server/api.test.ts +1699 -0
- package/src/server/api.ts +527 -0
- package/src/server/auth.test.ts +275 -0
- package/src/server/auth.ts +89 -0
- package/src/server/cors.test.ts +121 -0
- package/src/server/cors.ts +7 -0
- package/src/server/db/base.ts +296 -0
- package/src/server/db/flatfile.test.ts +221 -0
- package/src/server/db/flatfile.ts +228 -0
- package/src/server/db/index.test.ts +8 -0
- package/src/server/db/index.ts +12 -0
- package/src/server/db/inmemory.test.ts +143 -0
- package/src/server/db/inmemory.ts +143 -0
- package/src/server/db/localstorage.test.ts +73 -0
- package/src/server/db/localstorage.ts +44 -0
- package/src/server/index.test.ts +265 -0
- package/src/server/index.ts +175 -0
- package/src/server/transport/pubsub/generic-pub-sub.ts +11 -0
- package/src/server/transport/pubsub/in-memory-pub-sub.test.ts +47 -0
- package/src/server/transport/pubsub/in-memory-pub-sub.ts +28 -0
- package/src/server/transport/socketio-simultaneous.test.ts +603 -0
- package/src/server/transport/socketio.test.ts +303 -0
- package/src/server/transport/socketio.ts +279 -0
- package/src/server/util.ts +85 -0
- package/src/testing/mock-random.test.ts +45 -0
- package/src/testing/mock-random.ts +27 -0
- package/src/types.ts +511 -0
- package/testing/package.json +7 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2017 The boardgame.io Authors
|
|
3
|
+
*
|
|
4
|
+
* Use of this source code is governed by a MIT-style
|
|
5
|
+
* license that can be found in the LICENSE file or at
|
|
6
|
+
* https://opensource.org/licenses/MIT.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { SocketIOTransport } from './socketio';
|
|
10
|
+
import type * as ioNamespace from 'socket.io-client';
|
|
11
|
+
import { makeMove } from '../../core/action-creators';
|
|
12
|
+
import type { Master } from '../../master/master';
|
|
13
|
+
import type { ChatMessage, State } from '../../types';
|
|
14
|
+
import { ProcessGameConfig } from '../../core/game';
|
|
15
|
+
|
|
16
|
+
jest.mock('../../core/logger', () => ({
|
|
17
|
+
info: jest.fn(),
|
|
18
|
+
error: jest.fn(),
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
type UpdateArgs = Parameters<Master['onUpdate']>;
|
|
22
|
+
type SyncArgs = Parameters<Master['onSync']>;
|
|
23
|
+
|
|
24
|
+
class MockSocket {
|
|
25
|
+
callbacks: Record<string, (arg0?: any, arg1?: any) => void>;
|
|
26
|
+
emit: jest.Mock;
|
|
27
|
+
|
|
28
|
+
constructor() {
|
|
29
|
+
this.callbacks = {};
|
|
30
|
+
this.emit = jest.fn();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
receive(type: string, ...args) {
|
|
34
|
+
this.callbacks[type](...args);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
on(type: string, callback: (arg0?: any, arg1?: any) => void) {
|
|
38
|
+
this.callbacks[type] = callback;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
close() {}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
test('defaults', () => {
|
|
45
|
+
const m = new SocketIOTransport({
|
|
46
|
+
transportDataCallback: () => {},
|
|
47
|
+
game: ProcessGameConfig({}),
|
|
48
|
+
gameKey: {},
|
|
49
|
+
});
|
|
50
|
+
expect(typeof (m as any).connectionStatusCallback).toBe('function');
|
|
51
|
+
(m as any).connectionStatusCallback();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
class TransportAdapter extends SocketIOTransport {
|
|
55
|
+
declare socket: ioNamespace.Socket & {
|
|
56
|
+
io: { engine: any };
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
getMatchID() {
|
|
60
|
+
return this.matchID;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
getPlayerID() {
|
|
64
|
+
return this.playerID;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
getCredentials() {
|
|
68
|
+
return this.credentials;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
describe('update matchID / playerID / credentials', () => {
|
|
73
|
+
const socket = new MockSocket();
|
|
74
|
+
const m = new TransportAdapter({
|
|
75
|
+
socket,
|
|
76
|
+
transportDataCallback: () => {},
|
|
77
|
+
game: ProcessGameConfig({}),
|
|
78
|
+
gameKey: {},
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
beforeEach(() => (socket.emit = jest.fn()));
|
|
82
|
+
|
|
83
|
+
test('matchID', () => {
|
|
84
|
+
m.updateMatchID('test');
|
|
85
|
+
expect(m.getMatchID()).toBe('test');
|
|
86
|
+
const args: SyncArgs = ['test', null, undefined, 2];
|
|
87
|
+
expect(socket.emit).lastCalledWith('sync', ...args);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('playerID', () => {
|
|
91
|
+
m.updatePlayerID('player');
|
|
92
|
+
expect(m.getPlayerID()).toBe('player');
|
|
93
|
+
const args: SyncArgs = ['test', 'player', undefined, 2];
|
|
94
|
+
expect(socket.emit).lastCalledWith('sync', ...args);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test('credentials', () => {
|
|
98
|
+
m.updateCredentials('1234');
|
|
99
|
+
expect(m.getCredentials()).toBe('1234');
|
|
100
|
+
const args: SyncArgs = ['test', 'player', '1234', 2];
|
|
101
|
+
expect(socket.emit).lastCalledWith('sync', ...args);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe('connection status', () => {
|
|
106
|
+
let onChangeMock: jest.Mock;
|
|
107
|
+
let mockSocket: MockSocket;
|
|
108
|
+
let m: SocketIOTransport;
|
|
109
|
+
|
|
110
|
+
beforeEach(() => {
|
|
111
|
+
onChangeMock = jest.fn();
|
|
112
|
+
mockSocket = new MockSocket();
|
|
113
|
+
m = new SocketIOTransport({
|
|
114
|
+
socket: mockSocket,
|
|
115
|
+
matchID: '0',
|
|
116
|
+
playerID: '0',
|
|
117
|
+
gameName: 'foo',
|
|
118
|
+
game: ProcessGameConfig({}),
|
|
119
|
+
gameKey: {},
|
|
120
|
+
numPlayers: 2,
|
|
121
|
+
transportDataCallback: () => {},
|
|
122
|
+
});
|
|
123
|
+
m.subscribeToConnectionStatus(onChangeMock);
|
|
124
|
+
m.connect();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test('connect', () => {
|
|
128
|
+
mockSocket.callbacks['connect']();
|
|
129
|
+
expect(onChangeMock).toHaveBeenCalled();
|
|
130
|
+
expect(m.isConnected).toBe(true);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test('disconnect', () => {
|
|
134
|
+
mockSocket.callbacks['disconnect']();
|
|
135
|
+
expect(onChangeMock).toHaveBeenCalled();
|
|
136
|
+
expect(m.isConnected).toBe(false);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test('close socket', () => {
|
|
140
|
+
mockSocket.callbacks['connect']();
|
|
141
|
+
expect(m.isConnected).toBe(true);
|
|
142
|
+
m.disconnect();
|
|
143
|
+
expect(m.isConnected).toBe(false);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test('doesn’t crash if syncing before connecting', () => {
|
|
147
|
+
const transportDataCallback = jest.fn();
|
|
148
|
+
const transport = new SocketIOTransport({
|
|
149
|
+
transportDataCallback,
|
|
150
|
+
game: ProcessGameConfig({}),
|
|
151
|
+
gameKey: {},
|
|
152
|
+
});
|
|
153
|
+
transport.requestSync();
|
|
154
|
+
expect(transportDataCallback).not.toHaveBeenCalled();
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
describe('multiplayer', () => {
|
|
159
|
+
const mockSocket = new MockSocket();
|
|
160
|
+
const transportDataCallback = jest.fn();
|
|
161
|
+
const transport = new TransportAdapter({
|
|
162
|
+
socket: mockSocket,
|
|
163
|
+
transportDataCallback,
|
|
164
|
+
game: ProcessGameConfig({}),
|
|
165
|
+
gameKey: {},
|
|
166
|
+
});
|
|
167
|
+
transport.connect();
|
|
168
|
+
|
|
169
|
+
beforeEach(jest.clearAllMocks);
|
|
170
|
+
|
|
171
|
+
test('receive update', () => {
|
|
172
|
+
const restored: { restore: boolean; _stateID?: number } = { restore: true };
|
|
173
|
+
mockSocket.receive('update', 'default', restored);
|
|
174
|
+
expect(transportDataCallback).toHaveBeenCalledWith({
|
|
175
|
+
type: 'update',
|
|
176
|
+
args: ['default', restored, undefined],
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test('receive sync', () => {
|
|
181
|
+
const restored = { restore: true };
|
|
182
|
+
mockSocket.receive('sync', 'default', { state: restored });
|
|
183
|
+
expect(transportDataCallback).toHaveBeenCalledWith({
|
|
184
|
+
type: 'sync',
|
|
185
|
+
args: ['default', { state: restored }],
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
test('receive matchData', () => {
|
|
190
|
+
const matchData = [{ id: '0', name: 'Alice' }];
|
|
191
|
+
mockSocket.receive('matchData', 'default', matchData);
|
|
192
|
+
expect(transportDataCallback).toHaveBeenCalledWith({
|
|
193
|
+
type: 'matchData',
|
|
194
|
+
args: ['default', matchData],
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test('send update', () => {
|
|
199
|
+
const action = makeMove(undefined, undefined, undefined);
|
|
200
|
+
const state = { _stateID: 0 } as State;
|
|
201
|
+
transport.sendAction(state, action);
|
|
202
|
+
const args: UpdateArgs = [action, state._stateID, 'default', null];
|
|
203
|
+
expect(mockSocket.emit).lastCalledWith('update', ...args);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
test('receive chat-message', () => {
|
|
207
|
+
const chatData = { message: 'foo' };
|
|
208
|
+
mockSocket.receive('chat', 'default', chatData);
|
|
209
|
+
expect(transportDataCallback).toHaveBeenCalledWith({
|
|
210
|
+
type: 'chat',
|
|
211
|
+
args: ['default', chatData],
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
test('send chat-message', () => {
|
|
216
|
+
const message: ChatMessage = {
|
|
217
|
+
id: '0',
|
|
218
|
+
sender: '0',
|
|
219
|
+
payload: { message: 'foo' },
|
|
220
|
+
};
|
|
221
|
+
transport.sendChatMessage('matchID', message);
|
|
222
|
+
expect(mockSocket.emit).lastCalledWith(
|
|
223
|
+
'chat',
|
|
224
|
+
'matchID',
|
|
225
|
+
message,
|
|
226
|
+
transport.getCredentials()
|
|
227
|
+
);
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
describe('multiplayer delta state', () => {
|
|
232
|
+
const mockSocket = new MockSocket();
|
|
233
|
+
const transportDataCallback = jest.fn();
|
|
234
|
+
const transport = new TransportAdapter({
|
|
235
|
+
socket: mockSocket,
|
|
236
|
+
transportDataCallback,
|
|
237
|
+
game: ProcessGameConfig({}),
|
|
238
|
+
gameKey: {},
|
|
239
|
+
});
|
|
240
|
+
transport.connect();
|
|
241
|
+
|
|
242
|
+
beforeEach(jest.clearAllMocks);
|
|
243
|
+
|
|
244
|
+
test('receive patch', () => {
|
|
245
|
+
const patch1 = [
|
|
246
|
+
'default',
|
|
247
|
+
0,
|
|
248
|
+
1,
|
|
249
|
+
[{ op: 'replace', path: '/_stateID', value: 1 }],
|
|
250
|
+
[],
|
|
251
|
+
];
|
|
252
|
+
mockSocket.receive('patch', ...patch1);
|
|
253
|
+
expect(transportDataCallback).toHaveBeenCalledWith({
|
|
254
|
+
type: 'patch',
|
|
255
|
+
args: patch1,
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
describe('server option', () => {
|
|
261
|
+
const hostname = 'host';
|
|
262
|
+
const port = '1234';
|
|
263
|
+
|
|
264
|
+
test('without protocol', () => {
|
|
265
|
+
const server = hostname + ':' + port;
|
|
266
|
+
const m = new TransportAdapter({
|
|
267
|
+
server,
|
|
268
|
+
transportDataCallback: () => {},
|
|
269
|
+
game: ProcessGameConfig({}),
|
|
270
|
+
gameKey: {},
|
|
271
|
+
});
|
|
272
|
+
m.connect();
|
|
273
|
+
expect(m.socket.io.engine.hostname).toEqual(hostname);
|
|
274
|
+
expect(m.socket.io.engine.port).toEqual(port);
|
|
275
|
+
expect(m.socket.io.engine.secure).toEqual(false);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
test('without trailing slash', () => {
|
|
279
|
+
const server = 'http://' + hostname + ':' + port;
|
|
280
|
+
const m = new SocketIOTransport({
|
|
281
|
+
server,
|
|
282
|
+
transportDataCallback: () => {},
|
|
283
|
+
game: ProcessGameConfig({}),
|
|
284
|
+
gameKey: {},
|
|
285
|
+
});
|
|
286
|
+
m.connect();
|
|
287
|
+
expect((m.socket.io as any).uri).toEqual(server + '/default');
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
test('https', () => {
|
|
291
|
+
const serverWithProtocol = 'https://' + hostname + ':' + port + '/';
|
|
292
|
+
const m = new TransportAdapter({
|
|
293
|
+
server: serverWithProtocol,
|
|
294
|
+
transportDataCallback: () => {},
|
|
295
|
+
game: ProcessGameConfig({}),
|
|
296
|
+
gameKey: {},
|
|
297
|
+
});
|
|
298
|
+
m.connect();
|
|
299
|
+
expect(m.socket.io.engine.hostname).toEqual(hostname);
|
|
300
|
+
expect(m.socket.io.engine.port).toEqual(port);
|
|
301
|
+
expect(m.socket.io.engine.secure).toEqual(true);
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
test('http', () => {
|
|
305
|
+
const serverWithProtocol = 'http://' + hostname + ':' + port + '/';
|
|
306
|
+
const m = new TransportAdapter({
|
|
307
|
+
server: serverWithProtocol,
|
|
308
|
+
transportDataCallback: () => {},
|
|
309
|
+
game: ProcessGameConfig({}),
|
|
310
|
+
gameKey: {},
|
|
311
|
+
});
|
|
312
|
+
m.connect();
|
|
313
|
+
expect(m.socket.io.engine.hostname).toEqual(hostname);
|
|
314
|
+
expect(m.socket.io.engine.port).toEqual(port);
|
|
315
|
+
expect(m.socket.io.engine.secure).toEqual(false);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
test('no server set', () => {
|
|
319
|
+
const m = new TransportAdapter({
|
|
320
|
+
transportDataCallback: () => {},
|
|
321
|
+
game: ProcessGameConfig({}),
|
|
322
|
+
gameKey: {},
|
|
323
|
+
});
|
|
324
|
+
m.connect();
|
|
325
|
+
expect(m.socket.io.engine.hostname).not.toEqual(hostname);
|
|
326
|
+
expect(m.socket.io.engine.port).not.toEqual(port);
|
|
327
|
+
});
|
|
328
|
+
});
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2017 The boardgame.io Authors
|
|
3
|
+
*
|
|
4
|
+
* Use of this source code is governed by a MIT-style
|
|
5
|
+
* license that can be found in the LICENSE file or at
|
|
6
|
+
* https://opensource.org/licenses/MIT.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import * as ioNamespace from 'socket.io-client';
|
|
10
|
+
|
|
11
|
+
const io = ioNamespace.default;
|
|
12
|
+
|
|
13
|
+
import type { Master } from '../../master/master';
|
|
14
|
+
import { Transport } from './transport';
|
|
15
|
+
import type { Operation } from 'rfc6902';
|
|
16
|
+
import type { TransportOpts } from './transport';
|
|
17
|
+
import type {
|
|
18
|
+
CredentialedActionShape,
|
|
19
|
+
FilteredMetadata,
|
|
20
|
+
LogEntry,
|
|
21
|
+
PlayerID,
|
|
22
|
+
State,
|
|
23
|
+
SyncInfo,
|
|
24
|
+
ChatMessage,
|
|
25
|
+
} from '../../types';
|
|
26
|
+
|
|
27
|
+
type SocketOpts = Partial<
|
|
28
|
+
ioNamespace.SocketOptions & ioNamespace.ManagerOptions
|
|
29
|
+
>;
|
|
30
|
+
|
|
31
|
+
interface SocketIOOpts {
|
|
32
|
+
server?: string;
|
|
33
|
+
socketOpts?: SocketOpts;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
type SocketIOTransportOpts = TransportOpts &
|
|
37
|
+
SocketIOOpts & {
|
|
38
|
+
socket?;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* SocketIO
|
|
43
|
+
*
|
|
44
|
+
* Transport interface that interacts with the Master via socket.io.
|
|
45
|
+
*/
|
|
46
|
+
export class SocketIOTransport extends Transport {
|
|
47
|
+
server: string;
|
|
48
|
+
socket: ioNamespace.Socket;
|
|
49
|
+
socketOpts: SocketOpts;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Creates a new Multiplayer instance.
|
|
53
|
+
* @param {object} socket - Override for unit tests.
|
|
54
|
+
* @param {object} socketOpts - Options to pass to socket.io.
|
|
55
|
+
* @param {object} store - Redux store
|
|
56
|
+
* @param {string} matchID - The game ID to connect to.
|
|
57
|
+
* @param {string} playerID - The player ID associated with this client.
|
|
58
|
+
* @param {string} credentials - Authentication credentials
|
|
59
|
+
* @param {string} gameName - The game type (the `name` field in `Game`).
|
|
60
|
+
* @param {string} numPlayers - The number of players.
|
|
61
|
+
* @param {string} server - The game server in the form of 'hostname:port'. Defaults to the server serving the client if not provided.
|
|
62
|
+
*/
|
|
63
|
+
constructor({ socket, socketOpts, server, ...opts }: SocketIOTransportOpts) {
|
|
64
|
+
super(opts);
|
|
65
|
+
|
|
66
|
+
this.server = server;
|
|
67
|
+
this.socket = socket;
|
|
68
|
+
this.socketOpts = socketOpts;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
sendAction(state: State, action: CredentialedActionShape.Any): void {
|
|
72
|
+
const args: Parameters<Master['onUpdate']> = [
|
|
73
|
+
action,
|
|
74
|
+
state._stateID,
|
|
75
|
+
this.matchID,
|
|
76
|
+
this.playerID,
|
|
77
|
+
];
|
|
78
|
+
this.socket.emit('update', ...args);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
sendChatMessage(matchID: string, chatMessage: ChatMessage): void {
|
|
82
|
+
const args: Parameters<Master['onChatMessage']> = [
|
|
83
|
+
matchID,
|
|
84
|
+
chatMessage,
|
|
85
|
+
this.credentials,
|
|
86
|
+
];
|
|
87
|
+
this.socket.emit('chat', ...args);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
connect(): void {
|
|
91
|
+
if (!this.socket) {
|
|
92
|
+
if (this.server) {
|
|
93
|
+
let server = this.server;
|
|
94
|
+
if (server.search(/^https?:\/\//) == -1) {
|
|
95
|
+
server = 'http://' + this.server;
|
|
96
|
+
}
|
|
97
|
+
if (server.slice(-1) != '/') {
|
|
98
|
+
// add trailing slash if not already present
|
|
99
|
+
server = server + '/';
|
|
100
|
+
}
|
|
101
|
+
this.socket = io(server + this.gameName, this.socketOpts);
|
|
102
|
+
} else {
|
|
103
|
+
this.socket = io('/' + this.gameName, this.socketOpts);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Called when another player makes a move and the
|
|
108
|
+
// master broadcasts the update as a patch to other clients (including
|
|
109
|
+
// this one).
|
|
110
|
+
this.socket.on(
|
|
111
|
+
'patch',
|
|
112
|
+
(
|
|
113
|
+
matchID: string,
|
|
114
|
+
prevStateID: number,
|
|
115
|
+
stateID: number,
|
|
116
|
+
patch: Operation[],
|
|
117
|
+
deltalog: LogEntry[]
|
|
118
|
+
) => {
|
|
119
|
+
this.notifyClient({
|
|
120
|
+
type: 'patch',
|
|
121
|
+
args: [matchID, prevStateID, stateID, patch, deltalog],
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
// Called when another player makes a move and the
|
|
127
|
+
// master broadcasts the update to other clients (including
|
|
128
|
+
// this one).
|
|
129
|
+
this.socket.on(
|
|
130
|
+
'update',
|
|
131
|
+
(matchID: string, state: State, deltalog: LogEntry[]) => {
|
|
132
|
+
this.notifyClient({
|
|
133
|
+
type: 'update',
|
|
134
|
+
args: [matchID, state, deltalog],
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
// Called when the client first connects to the master
|
|
140
|
+
// and requests the current game state.
|
|
141
|
+
this.socket.on('sync', (matchID: string, syncInfo: SyncInfo) => {
|
|
142
|
+
this.notifyClient({ type: 'sync', args: [matchID, syncInfo] });
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Called when new player joins the match or changes
|
|
146
|
+
// it's connection status
|
|
147
|
+
this.socket.on(
|
|
148
|
+
'matchData',
|
|
149
|
+
(matchID: string, matchData: FilteredMetadata) => {
|
|
150
|
+
this.notifyClient({ type: 'matchData', args: [matchID, matchData] });
|
|
151
|
+
}
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
this.socket.on('chat', (matchID: string, chatMessage: ChatMessage) => {
|
|
155
|
+
this.notifyClient({ type: 'chat', args: [matchID, chatMessage] });
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Keep track of connection status.
|
|
159
|
+
this.socket.on('connect', () => {
|
|
160
|
+
// Initial sync to get game state.
|
|
161
|
+
this.requestSync();
|
|
162
|
+
this.setConnectionStatus(true);
|
|
163
|
+
});
|
|
164
|
+
this.socket.on('disconnect', () => {
|
|
165
|
+
this.setConnectionStatus(false);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
disconnect(): void {
|
|
170
|
+
this.socket.close();
|
|
171
|
+
this.socket = null;
|
|
172
|
+
this.setConnectionStatus(false);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
requestSync(): void {
|
|
176
|
+
if (this.socket) {
|
|
177
|
+
const args: Parameters<Master['onSync']> = [
|
|
178
|
+
this.matchID,
|
|
179
|
+
this.playerID,
|
|
180
|
+
this.credentials,
|
|
181
|
+
this.numPlayers,
|
|
182
|
+
];
|
|
183
|
+
this.socket.emit('sync', ...args);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
updateMatchID(id: string): void {
|
|
188
|
+
this.matchID = id;
|
|
189
|
+
this.requestSync();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
updatePlayerID(id: PlayerID): void {
|
|
193
|
+
this.playerID = id;
|
|
194
|
+
this.requestSync();
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
updateCredentials(credentials?: string): void {
|
|
198
|
+
this.credentials = credentials;
|
|
199
|
+
this.requestSync();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function SocketIO({ server, socketOpts }: SocketIOOpts = {}) {
|
|
204
|
+
return (transportOpts: SocketIOTransportOpts) =>
|
|
205
|
+
new SocketIOTransport({
|
|
206
|
+
server,
|
|
207
|
+
socketOpts,
|
|
208
|
+
...transportOpts,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Transport } from './transport';
|
|
2
|
+
import { ProcessGameConfig } from '../../core/game';
|
|
3
|
+
|
|
4
|
+
describe('Transport', () => {
|
|
5
|
+
class SimpleTransport extends Transport {
|
|
6
|
+
connect() {}
|
|
7
|
+
disconnect() {}
|
|
8
|
+
sendAction() {}
|
|
9
|
+
sendChatMessage() {}
|
|
10
|
+
requestSync() {}
|
|
11
|
+
updateMatchID() {}
|
|
12
|
+
updatePlayerID() {}
|
|
13
|
+
updateCredentials() {}
|
|
14
|
+
get(key: 'connectionStatusCallback') {
|
|
15
|
+
return this[key].bind(this);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
test('base class sets up callbacks', () => {
|
|
20
|
+
const transport = new SimpleTransport({
|
|
21
|
+
transportDataCallback: () => {},
|
|
22
|
+
game: ProcessGameConfig({}),
|
|
23
|
+
gameKey: {},
|
|
24
|
+
});
|
|
25
|
+
expect(transport.get('connectionStatusCallback')()).toBeUndefined();
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2017 The boardgame.io Authors
|
|
3
|
+
*
|
|
4
|
+
* Use of this source code is governed by a MIT-style
|
|
5
|
+
* license that can be found in the LICENSE file or at
|
|
6
|
+
* https://opensource.org/licenses/MIT.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { ProcessGameConfig } from '../../core/game';
|
|
10
|
+
import type { TransportData } from '../../master/master';
|
|
11
|
+
import type {
|
|
12
|
+
Game,
|
|
13
|
+
PlayerID,
|
|
14
|
+
CredentialedActionShape,
|
|
15
|
+
State,
|
|
16
|
+
SyncInfo,
|
|
17
|
+
ChatMessage,
|
|
18
|
+
} from '../../types';
|
|
19
|
+
|
|
20
|
+
export type MetadataCallback = (metadata: SyncInfo['filteredMetadata']) => void;
|
|
21
|
+
|
|
22
|
+
export type ChatCallback = (message: ChatMessage) => void;
|
|
23
|
+
|
|
24
|
+
export interface TransportOpts {
|
|
25
|
+
transportDataCallback: (data: TransportData) => void;
|
|
26
|
+
gameName?: string;
|
|
27
|
+
gameKey: Game;
|
|
28
|
+
game: ReturnType<typeof ProcessGameConfig>;
|
|
29
|
+
playerID?: PlayerID;
|
|
30
|
+
matchID?: string;
|
|
31
|
+
credentials?: string;
|
|
32
|
+
numPlayers?: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export abstract class Transport {
|
|
36
|
+
protected gameName: string;
|
|
37
|
+
protected playerID: PlayerID | null;
|
|
38
|
+
protected matchID: string;
|
|
39
|
+
protected credentials?: string;
|
|
40
|
+
protected numPlayers: number;
|
|
41
|
+
/** Callback to pass transport data back to the client. */
|
|
42
|
+
private transportDataCallback: (data: TransportData) => void;
|
|
43
|
+
/** Callback to let the client know when the connection status has changed. */
|
|
44
|
+
private connectionStatusCallback: () => void = () => {};
|
|
45
|
+
isConnected = false;
|
|
46
|
+
|
|
47
|
+
constructor({
|
|
48
|
+
transportDataCallback,
|
|
49
|
+
gameName,
|
|
50
|
+
playerID,
|
|
51
|
+
matchID,
|
|
52
|
+
credentials,
|
|
53
|
+
numPlayers,
|
|
54
|
+
}: TransportOpts) {
|
|
55
|
+
this.transportDataCallback = transportDataCallback;
|
|
56
|
+
this.gameName = gameName || 'default';
|
|
57
|
+
this.playerID = playerID || null;
|
|
58
|
+
this.matchID = matchID || 'default';
|
|
59
|
+
this.credentials = credentials;
|
|
60
|
+
this.numPlayers = numPlayers || 2;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Subscribe to connection state changes. */
|
|
64
|
+
subscribeToConnectionStatus(fn: () => void): void {
|
|
65
|
+
this.connectionStatusCallback = fn;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Transport implementations should call this when they connect/disconnect. */
|
|
69
|
+
protected setConnectionStatus(isConnected: boolean): void {
|
|
70
|
+
this.isConnected = isConnected;
|
|
71
|
+
this.connectionStatusCallback();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Transport implementations should call this when they receive data from a master. */
|
|
75
|
+
protected notifyClient(data: TransportData): void {
|
|
76
|
+
this.transportDataCallback(data);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Called by the client to connect the transport. */
|
|
80
|
+
abstract connect(): void;
|
|
81
|
+
/** Called by the client to disconnect the transport. */
|
|
82
|
+
abstract disconnect(): void;
|
|
83
|
+
/** Called by the client to dispatch an action via the transport. */
|
|
84
|
+
abstract sendAction(state: State, action: CredentialedActionShape.Any): void;
|
|
85
|
+
/** Called by the client to dispatch a chat message via the transport. */
|
|
86
|
+
abstract sendChatMessage(matchID: string, chatMessage: ChatMessage): void;
|
|
87
|
+
/** Called by the client to request a sync action from the transport. */
|
|
88
|
+
abstract requestSync(): void;
|
|
89
|
+
/** Called by the client to update the matchID it wants to connect to. */
|
|
90
|
+
abstract updateMatchID(id: string): void;
|
|
91
|
+
/** Called by the client to update the playerID it is playing as. */
|
|
92
|
+
abstract updatePlayerID(id: PlayerID): void;
|
|
93
|
+
/** Called by the client to update the credentials it is using. */
|
|
94
|
+
abstract updateCredentials(credentials?: string): void;
|
|
95
|
+
}
|