puzzle/src/frontend/Communication.ts

140 lines
3.6 KiB
TypeScript
Raw Normal View History

2021-05-09 13:49:40 +02:00
"use strict"
2021-05-17 00:27:47 +02:00
import { logger } from '../common/Util'
import Protocol from './../common/Protocol'
2020-11-09 01:54:05 +01:00
const log = logger('Communication.js')
const CODE_GOING_AWAY = 1001
const CODE_CUSTOM_DISCONNECT = 4000
const CONN_STATE_NOT_CONNECTED = 0 // not connected yet
const CONN_STATE_DISCONNECTED = 1 // not connected, but was connected before
const CONN_STATE_CONNECTED = 2 // connected
const CONN_STATE_CONNECTING = 3 // connecting
const CONN_STATE_CLOSED = 4 // not connected (closed on purpose)
2021-05-17 00:27:47 +02:00
let ws: WebSocket
let changesCallback = (msg: Array<any>) => {}
let connectionStateChangeCallback = (state: number) => {}
2020-11-09 01:54:05 +01:00
2021-05-15 17:40:04 +02:00
// TODO: change these to something like on(EVT, cb)
2021-05-17 00:27:47 +02:00
function onServerChange(callback: (msg: Array<any>) => void) {
2020-11-09 01:54:05 +01:00
changesCallback = callback
}
2021-05-17 00:27:47 +02:00
function onConnectionStateChange(callback: (state: number) => void) {
connectionStateChangeCallback = callback
2021-05-15 17:40:04 +02:00
}
2020-11-09 01:54:05 +01:00
let connectionState = CONN_STATE_NOT_CONNECTED
2021-05-17 00:27:47 +02:00
const setConnectionState = (state: number) => {
if (connectionState !== state) {
connectionState = state
connectionStateChangeCallback(state)
}
}
2021-05-17 00:27:47 +02:00
function send(message: Array<any>): void {
if (connectionState === CONN_STATE_CONNECTED) {
try {
ws.send(JSON.stringify(message))
} catch (e) {
log.info('unable to send message.. maybe because ws is invalid?')
}
}
2020-11-17 21:46:56 +01:00
}
2021-05-17 00:27:47 +02:00
let clientSeq: number
let events: Record<number, any>
function connect(
address: string,
gameId: string,
clientId: string
): Promise<any> {
2020-11-17 21:46:56 +01:00
clientSeq = 0
events = {}
setConnectionState(CONN_STATE_CONNECTING)
2021-05-09 21:43:35 +02:00
return new Promise(resolve => {
ws = new WebSocket(address, clientId + '|' + gameId)
ws.onopen = (e) => {
setConnectionState(CONN_STATE_CONNECTED)
send([Protocol.EV_CLIENT_INIT])
}
ws.onmessage = (e) => {
const msg = JSON.parse(e.data)
2020-11-17 21:46:56 +01:00
const msgType = msg[0]
if (msgType === Protocol.EV_SERVER_INIT) {
const game = msg[1]
2021-05-09 21:43:35 +02:00
resolve(game)
2020-11-17 21:46:56 +01:00
} else if (msgType === Protocol.EV_SERVER_EVENT) {
2020-11-17 22:34:15 +01:00
const msgClientId = msg[1]
const msgClientSeq = msg[2]
if (msgClientId === clientId && events[msgClientSeq]) {
delete events[msgClientSeq]
2020-11-17 22:47:55 +01:00
// we have already calculated that change locally. probably
return
2020-11-17 22:34:15 +01:00
}
2020-11-17 21:46:56 +01:00
changesCallback(msg)
2021-05-09 21:43:35 +02:00
} else {
throw `[ 2021-05-09 invalid connect msgType ${msgType} ]`
2020-11-09 01:54:05 +01:00
}
}
ws.onerror = (e) => {
setConnectionState(CONN_STATE_DISCONNECTED)
throw `[ 2021-05-15 onerror ]`
}
ws.onclose = (e) => {
if (e.code === CODE_CUSTOM_DISCONNECT || e.code === CODE_GOING_AWAY) {
setConnectionState(CONN_STATE_CLOSED)
} else {
setConnectionState(CONN_STATE_DISCONNECTED)
}
}
2020-11-09 01:54:05 +01:00
})
}
2021-05-29 12:40:46 +02:00
async function requestReplayData(
gameId: string,
2021-05-29 11:44:55 +02:00
offset: number,
size: number
2021-05-29 12:40:46 +02:00
): Promise<{ log: Array<any>, game: any }> {
const res = await fetch(`/api/replay-data?gameId=${gameId}&offset=${offset}&size=${size}`)
const json: { log: Array<any>, game: any } = await res.json()
return json
2020-12-22 22:35:09 +01:00
}
2021-05-17 00:27:47 +02:00
function disconnect(): void {
if (ws) {
ws.close(CODE_CUSTOM_DISCONNECT)
2021-05-13 22:45:55 +02:00
}
clientSeq = 0
events = {}
}
2021-05-17 00:27:47 +02:00
function sendClientEvent(evt: any): void {
2020-11-17 21:46:56 +01:00
// when sending event, increase number of sent events
// and add the event locally
clientSeq++;
2021-05-09 21:43:35 +02:00
events[clientSeq] = evt
2020-11-17 21:46:56 +01:00
send([Protocol.EV_CLIENT_EVENT, clientSeq, events[clientSeq]])
2020-11-09 01:54:05 +01:00
}
export default {
connect,
2021-05-29 11:44:55 +02:00
requestReplayData,
2021-05-13 22:45:55 +02:00
disconnect,
2020-11-17 21:46:56 +01:00
sendClientEvent,
2021-05-15 17:40:04 +02:00
onServerChange,
onConnectionStateChange,
CODE_CUSTOM_DISCONNECT,
CONN_STATE_NOT_CONNECTED,
CONN_STATE_DISCONNECTED,
CONN_STATE_CLOSED,
CONN_STATE_CONNECTED,
CONN_STATE_CONNECTING,
2020-11-09 01:54:05 +01:00
}