diff options
Diffstat (limited to '')
-rw-r--r-- | client/src/net/multiplayer.ts (renamed from client/js/multiplayer.js) | 85 |
1 files changed, 35 insertions, 50 deletions
diff --git a/client/js/multiplayer.js b/client/src/net/multiplayer.ts index eec1c7d..e9f3057 100644 --- a/client/js/multiplayer.js +++ b/client/src/net/multiplayer.ts @@ -2,52 +2,39 @@ * @author tint */ -/** - * @template Input - * @typedef {{ - * added?: number[], - * removed?: number[], - * players: { - * [conn: number]: Input - * }, - * }} GameInput - */ +import { GameState, Message, PlayerInput } from "../types.js"; +import { Game } from "./game"; -/** - * @template Data, Input - * @param {import("./game.js").Game<Data, GameInput<Input>>} game - * @param {string} code - * @param {( - * startFrame: number, - * latency: number, - * connection: number, - * update: (input: Input, frame: number) => void, - * ping: () => Promise<number>, - * desyncCheck: () => Promise<boolean>, - * ) => void} onStart - * Called when the game is in a ready state with the current frame - * (or -1 if you're starting the room), an estimate of how many milliseconds have elapsed since that frame was sent, - * and your connection ID - */ -export function multiplayer(game, code, onStart) { - const url = new URL("api/join/" + encodeURIComponent(code), window.location); +export function multiplayer( + game: Game, + code: string, + onStart: ( + startFrame: number, + latency: number, + connection: number, + update: (input: PlayerInput, frame: number) => void, + ping: () => Promise<number>, + desyncCheck: (frame: number) => Promise<boolean>, + ) => boolean +) { + const url = new URL("api/join/" + encodeURIComponent(code), window.location.toString()); url.protocol = url.protocol.replace("http", "ws"); const socket = new WebSocket(url); - let requestStateTime; + let requestStateTime: number; let hasState = false; - let connectionId; + let connectionId: number; let cachedInputs = []; let connections = []; - let pingPromise; + let pingPromise: (type: Promise<number>) => void; - function send(obj) { + function send(obj: any) { socket.send(JSON.stringify(obj)); } - function applyInput(input) { + function applyInput(input: Message) { let prev = game.getHistory(input.frame); let newInput = prev && prev.input ? {...prev.input} : { players: {} }; @@ -74,11 +61,10 @@ export function multiplayer(game, code, onStart) { newInput.removed = (newInput.removed || []).concat([input.removed]); } } - game.setInput(input.frame, newInput); } - function flushCachedInputs(latency = 0) { + function flushCachedInputs(latency = 0): boolean { for(const input of cachedInputs) { // only care about inputs after the new state if(input.frame <= game.historyStart) { @@ -91,15 +77,14 @@ export function multiplayer(game, code, onStart) { return onStart(game.getFrame(), latency, connectionId, update, ping, desyncCheck); } - function update(input, frame) { + function update(input: PlayerInput, frame: number) { if(input === undefined) { // used to update the game locally if(hasState) { - applyInput({ - frame, - }); + applyInput({}) } return; } + const data = { type: "input", data: input, @@ -118,17 +103,17 @@ export function multiplayer(game, code, onStart) { type: "ping", frame: Math.max(0, game.currentFrame), }); - const frame = await new Promise(r => pingPromise = r); + const frame: number = await new Promise(r => pingPromise = r); return game.currentFrame - frame; } - async function desyncCheck(frame) { + async function desyncCheck(frame: number): Promise<boolean> { const history = game.getHistory(frame); if(!history) { console.error("tried to check for desyncs on a frame not in memory", frame); return true; } - const localstate = history.data; + // const localstate = history.data; const proms = connections .filter(n => n !== connectionId) .map(connection => { @@ -138,7 +123,7 @@ export function multiplayer(game, code, onStart) { connection, }); return new Promise(r => { - stateRequests[frame + "," + connection] = state => { + stateRequests[frame + "," + connection] = (state: GameState) => { r({ state, connection, @@ -150,11 +135,11 @@ export function multiplayer(game, code, onStart) { if(!proms.length) { return false; // this is the only connection, no check necessary } - const states = await Promise.all(proms); - if(!states.every(({ state }) => objeq(localstate, state))) { - console.error("desync! remote states:", states, "local state:", localstate); - return true; - } + // const states = await Promise.all(proms); + // if(!states.every(({ state }) => objeq(localstate, state))) { + // console.error("desync! remote states:", states, "local state:", localstate); + // return true; + // } return false; } @@ -203,7 +188,7 @@ export function multiplayer(game, code, onStart) { case "requeststate": // wait until there's some state to send const startTime = performance.now(); - function check() { + const check = () => { if(performance.now() - startTime > 5000) { return; // give up after 5s } @@ -272,7 +257,7 @@ export function multiplayer(game, code, onStart) { } // compare two plain objects (things that can be JSON.stringified) -function objeq(a, b) { +function objeq(a: any, b: any) { if(typeof(a) !== typeof(b)) { return false; } |