base2020/src/net/Connection.ts

51 lines
1.8 KiB
TypeScript

import { Callbag, Source } from "callbag";
import create from "callbag-create";
import pipe from "callbag-pipe";
import share from "callbag-share";
import { Jsonified } from "../ecs/Data";
import { catchTalkback, defer, interval, makeSubject, map, merge } from "../utilities/Callbag";
import { ClientMessage, MessageTypes, ServerMessage } from "./LockstepClient";
type Server<LocalInput, State> = Callbag<ClientMessage<LocalInput, State>, ServerMessage<LocalInput[], State>>;
/** Connection to a websocket server that handles multiple clients, for schemes where GlobalInput = LocalInput[] */
export class Connection<LocalInput, State> {
public constructor(
private url: string
) { }
public readonly socket = defer(() => {
const ws = new WebSocket(this.url);
const source: Source<ServerMessage<LocalInput[], State>> = create((data, { }, close) => {
ws.onopen = () => {
// fake a HELO message & set state message until the server actually sends them
data({ t: MessageTypes.META, helo: "Websocket Server" });
data({ t: MessageTypes.SET_STATE, u: 0, s: {} });
};
ws.onmessage = msg => {
const decoded: Jsonified<ServerMessage<LocalInput[], State>> = JSON.parse(msg.data);
data(decoded as ServerMessage<LocalInput[], State>);
};
ws.onclose = () => {
close();
};
return () => {
// cleanup
ws.close();
};
});
return pipe(
source,
catchTalkback((message: ClientMessage<LocalInput, State>) => {
const encoded = JSON.stringify(message);
ws.send(encoded);
})
);
});
}