import {pong, gc, clientInfo} from "./global.js" import * as d from "./draw.js"; import { socket } from "./ws.js"; import * as ev from "../shared_js/class/Event.js" import * as en from "../shared_js/enums.js" export let gridDisplay = false; let actual_time: number = Date.now(); let last_time: number; let delta_time: number; class InputHistory { input: en.InputEnum; inputId: number; deltaTime: number; constructor(input: en.InputEnum, inputId: number, deltaTime: number) { this.input = input; this.inputId = inputId; this.deltaTime = deltaTime; } } const inputHistoryArr: InputHistory[] = []; let id = 0; /* idMax should be high enough to prevent duplicate "id" in "inputHistoryArr". In theory a little more than (1000/handleInputIntervalMS) should be enough. */ const idMax = 999; // 999 arbitrary function handleInput() { console.log("handleInput"); last_time = actual_time; actual_time = Date.now(); delta_time = (actual_time - last_time) / 1000; if (id > idMax) { id = 0; } var keys = pong.keys; if (keys.length == 0) return; if (keys.indexOf("g") != -1) { if (gridDisplay) { pong.clear(); d.drawStatic(); } gridDisplay = !gridDisplay; pong.deleteKey("g"); } playerMove(delta_time, keys); } function playerMove(delta: number, keys: string[]) { if (keys.indexOf("w") !== -1 || keys.indexOf("ArrowUp".toLowerCase()) !== -1) { if (keys.indexOf("s") === -1 && keys.indexOf("ArrowDown".toLowerCase()) === -1) { const input = new ev.EventInput(en.InputEnum.up, ++id); inputHistoryArr.push(new InputHistory(input.input, input.inputId, delta)); socket.send(JSON.stringify(input)); playerMovePrediction(delta, input.input); // client prediction } } else if (keys.indexOf("s") !== -1 || keys.indexOf("ArrowDown".toLowerCase()) !== -1) { const input = new ev.EventInput(en.InputEnum.down, ++id); inputHistoryArr.push(new InputHistory(input.input, input.inputId, delta)); socket.send(JSON.stringify(input)); playerMovePrediction(delta, input.input); // client prediction } } function playerMovePrediction(delta: number, input: en.InputEnum) { // client prediction const racket = clientInfo.racket; racket.dir.y = 0; if (input === en.InputEnum.up) { racket.dir.y += -1; } else if (input === en.InputEnum.down) { racket.dir.y += 1; } racket.moveAndCollide(delta, [gc.wallTop, gc.wallBottom]); } function repeatInput(lastInputId: number) { // server reconciliation let i = inputHistoryArr.findIndex((value: InputHistory) => { if (value.inputId === lastInputId) { return true; } return false; }); // console.log("repeatInput, lastInputId = " + lastInputId); // console.log("repeatInput, before splice up to index " + i); // console.log(inputHistoryArr); inputHistoryArr.splice(0, i+1); // console.log("repeatInput, after splice"); // console.log(inputHistoryArr); inputHistoryArr.forEach((value: InputHistory) => { playerMovePrediction(value.deltaTime, value.input); }); } export {handleInput, repeatInput}