diff --git a/common/Protocol.js b/common/Protocol.js new file mode 100644 index 0000000..07f4ccb --- /dev/null +++ b/common/Protocol.js @@ -0,0 +1,51 @@ +/* +SERVER_CLIENT_MESSAGE_PROTOCOL +NOTE: clients always send game id and their id + when creating sockets (via socket.protocol), so + this doesn't need to be set in each message data + +NOTE: first value in the array is always the type of event/message + when describing them below, the value each has is used + instead of writing EVENT_TYPE or something ismilar + + +EV_CLIENT_EVENT: event triggered by clients and sent to server +[ + EV_CLIENT_EVENT, // constant value, type of event + CLIENT_SEQ, // sequence number sent by client. + EV_DATA, // (eg. mouse input info) +] + +EV_SERVER_EVENT: event sent to clients after recieving a client + event and processing it +[ + EV_SERVER_EVENT, // constant value, type of event + CLIENT_ID, // user who sent the client event + CLIENT_SEQ, // sequence number of the client event msg + CHANGES_TRIGGERED_BY_CLIENT_EVENT, +] + +EV_CLIENT_INIT: event sent by client to enter a game +[ + EV_CLIENT_INIT, // constant value, type of event +] + +EV_SERVER_INIT: event sent to one client after that client + connects to a game +[ + EV_SERVER_INIT, // constant value, type of event + GAME, // complete game instance required by + // client to build client side of the game +] +*/ +const EV_SERVER_EVENT = 1 +const EV_SERVER_INIT = 4 +const EV_CLIENT_EVENT = 2 +const EV_CLIENT_INIT = 3 + +export default { + EV_SERVER_EVENT, + EV_SERVER_INIT, + EV_CLIENT_EVENT, + EV_CLIENT_INIT, +} diff --git a/game/Camera.js b/game/Camera.js index 0f32c2a..bb92a67 100644 --- a/game/Camera.js +++ b/game/Camera.js @@ -35,6 +35,7 @@ export default class Camera { } // centered zoom + // TODO: mouse-centered-zoom this.x -= Math.round(((this.width / this.zoom) - (this.width / zoom)) / 2) this.y -= Math.round(((this.height / this.zoom) - (this.height / zoom)) / 2) diff --git a/game/Communication.js b/game/Communication.js index 04cdf8d..9a91573 100644 --- a/game/Communication.js +++ b/game/Communication.js @@ -1,41 +1,50 @@ import WsClient from './WsClient.js' +import Protocol from './../common/Protocol.js' -const EV_SERVER_STATE_CHANGED = 1 -const EV_SERVER_INIT = 4 -const EV_CLIENT_MOUSE = 2 -const EV_CLIENT_INIT = 3 - +/** @type WsClient */ let conn let changesCallback = () => {} -function onChanges(callback) { +function onServerChange(callback) { changesCallback = callback } +function send(message) { + conn.send(JSON.stringify(message)) +} + +let clientSeq +let events function connect(gameId, playerId) { + clientSeq = 0 + events = {} conn = new WsClient(WS_ADDRESS, playerId + '|' + gameId) return new Promise(r => { conn.connect() - conn.send(JSON.stringify([EV_CLIENT_INIT])) + send([Protocol.EV_CLIENT_INIT]) conn.onSocket('message', async ({ data }) => { - const [type, typeData] = JSON.parse(data) - if (type === EV_SERVER_INIT) { - const game = typeData + const msg = JSON.parse(data) + const msgType = msg[0] + if (msgType === Protocol.EV_SERVER_INIT) { + const game = msg[1] r(game) - } else if (type === EV_SERVER_STATE_CHANGED) { - const changes = typeData - changesCallback(changes) + } else if (msgType === Protocol.EV_SERVER_EVENT) { + changesCallback(msg) } }) }) } -function addMouse(mouse) { - conn.send(JSON.stringify([EV_CLIENT_MOUSE, mouse])) +function sendClientEvent(mouse) { + // when sending event, increase number of sent events + // and add the event locally + clientSeq++; + events[clientSeq] = mouse + send([Protocol.EV_CLIENT_EVENT, clientSeq, events[clientSeq]]) } export default { connect, - onChanges, - addMouse, + onServerChange, + sendClientEvent, } diff --git a/game/EventAdapter.js b/game/EventAdapter.js deleted file mode 100644 index 806959b..0000000 --- a/game/EventAdapter.js +++ /dev/null @@ -1,38 +0,0 @@ -export default class EventAdapter { - constructor(canvas) { - this._mouseEvts = [] - canvas.addEventListener('mousedown', this._mouseDown.bind(this)) - canvas.addEventListener('mouseup', this._mouseUp.bind(this)) - canvas.addEventListener('mousemove', this._mouseMove.bind(this)) - canvas.addEventListener('wheel', this._wheel.bind(this)) - } - - consumeAll() { - if (this._mouseEvts.length === 0) { - return [] - } - const all = this._mouseEvts.slice() - this._mouseEvts = [] - return all - } - - _mouseDown(e) { - if (e.button === 0) { - this._mouseEvts.push({type: 'down', x: e.offsetX, y: e.offsetY}) - } - } - - _mouseUp(e) { - if (e.button === 0) { - this._mouseEvts.push({type: 'up', x: e.offsetX, y: e.offsetY}) - } - } - - _mouseMove(e) { - this._mouseEvts.push({type: 'move', x: e.offsetX, y: e.offsetY}) - } - - _wheel(e) { - this._mouseEvts.push({type: 'wheel', deltaY: e.deltaY, x: e.offsetX, y: e.offsetY}) - } -} diff --git a/game/PuzzleGraphics.js b/game/PuzzleGraphics.js new file mode 100644 index 0000000..29dc7a7 --- /dev/null +++ b/game/PuzzleGraphics.js @@ -0,0 +1,119 @@ +import Geometry from '../common/Geometry.js' +import Graphics from './Graphics.js' + +async function createPuzzleTileBitmaps(img, tiles, info) { + var tileSize = info.tileSize + var tileMarginWidth = info.tileMarginWidth + var tileDrawSize = info.tileDrawSize + var tileRatio = tileSize / 100.0 + + var curvyCoords = [ + 0, 0, 40, 15, 37, 5, + 37, 5, 40, 0, 38, -5, + 38, -5, 20, -20, 50, -20, + 50, -20, 80, -20, 62, -5, + 62, -5, 60, 0, 63, 5, + 63, 5, 65, 15, 100, 0 + ]; + + const bitmaps = new Array(tiles.length) + + const paths = {} + function pathForShape(shape) { + const key = `${shape.top}${shape.right}${shape.left}${shape.bottom}` + if (paths[key]) { + return paths[key] + } + + const path = new Path2D() + const topLeftEdge = { x: tileMarginWidth, y: tileMarginWidth } + path.moveTo(topLeftEdge.x, topLeftEdge.y) + for (let i = 0; i < curvyCoords.length / 6; i++) { + const p1 = Geometry.pointAdd(topLeftEdge, { x: curvyCoords[i * 6 + 0] * tileRatio, y: shape.top * curvyCoords[i * 6 + 1] * tileRatio }) + const p2 = Geometry.pointAdd(topLeftEdge, { x: curvyCoords[i * 6 + 2] * tileRatio, y: shape.top * curvyCoords[i * 6 + 3] * tileRatio }) + const p3 = Geometry.pointAdd(topLeftEdge, { x: curvyCoords[i * 6 + 4] * tileRatio, y: shape.top * curvyCoords[i * 6 + 5] * tileRatio }) + path.bezierCurveTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); + } + const topRightEdge = Geometry.pointAdd(topLeftEdge, { x: tileSize, y: 0 }) + for (let i = 0; i < curvyCoords.length / 6; i++) { + const p1 = Geometry.pointAdd(topRightEdge, { x: -shape.right * curvyCoords[i * 6 + 1] * tileRatio, y: curvyCoords[i * 6 + 0] * tileRatio }) + const p2 = Geometry.pointAdd(topRightEdge, { x: -shape.right * curvyCoords[i * 6 + 3] * tileRatio, y: curvyCoords[i * 6 + 2] * tileRatio }) + const p3 = Geometry.pointAdd(topRightEdge, { x: -shape.right * curvyCoords[i * 6 + 5] * tileRatio, y: curvyCoords[i * 6 + 4] * tileRatio }) + path.bezierCurveTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); + } + const bottomRightEdge = Geometry.pointAdd(topRightEdge, { x: 0, y: tileSize }) + for (let i = 0; i < curvyCoords.length / 6; i++) { + let p1 = Geometry.pointSub(bottomRightEdge, { x: curvyCoords[i * 6 + 0] * tileRatio, y: shape.bottom * curvyCoords[i * 6 + 1] * tileRatio }) + let p2 = Geometry.pointSub(bottomRightEdge, { x: curvyCoords[i * 6 + 2] * tileRatio, y: shape.bottom * curvyCoords[i * 6 + 3] * tileRatio }) + let p3 = Geometry.pointSub(bottomRightEdge, { x: curvyCoords[i * 6 + 4] * tileRatio, y: shape.bottom * curvyCoords[i * 6 + 5] * tileRatio }) + path.bezierCurveTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); + } + const bottomLeftEdge = Geometry.pointSub(bottomRightEdge, { x: tileSize, y: 0 }) + for (let i = 0; i < curvyCoords.length / 6; i++) { + let p1 = Geometry.pointSub(bottomLeftEdge, { x: -shape.left * curvyCoords[i * 6 + 1] * tileRatio, y: curvyCoords[i * 6 + 0] * tileRatio }) + let p2 = Geometry.pointSub(bottomLeftEdge, { x: -shape.left * curvyCoords[i * 6 + 3] * tileRatio, y: curvyCoords[i * 6 + 2] * tileRatio }) + let p3 = Geometry.pointSub(bottomLeftEdge, { x: -shape.left * curvyCoords[i * 6 + 5] * tileRatio, y: curvyCoords[i * 6 + 4] * tileRatio }) + path.bezierCurveTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); + } + paths[key] = path + return path + } + + for (let tile of tiles) { + const srcRect = srcRectByIdx(info, tile.idx) + const path = pathForShape(info.shapes[tile.idx]) + + const c = Graphics.createCanvas(tileDrawSize, tileDrawSize) + const ctx = c.getContext('2d') + // ----------------------------------------------------------- + // ----------------------------------------------------------- + ctx.lineWidth = 2 + ctx.stroke(path) + // ----------------------------------------------------------- + // ----------------------------------------------------------- + ctx.save(); + ctx.clip(path) + ctx.drawImage( + img, + srcRect.x - tileMarginWidth, + srcRect.y - tileMarginWidth, + tileDrawSize, + tileDrawSize, + 0, + 0, + tileDrawSize, + tileDrawSize, + ) + ctx.stroke(path) + ctx.restore(); + + bitmaps[tile.idx] = await createImageBitmap(c) + } + + return bitmaps +} + +function srcRectByIdx(puzzleInfo, idx) { + const c = puzzleInfo.coords[idx] + return { + x: c.x * puzzleInfo.tileSize, + y: c.y * puzzleInfo.tileSize, + w: puzzleInfo.tileSize, + h: puzzleInfo.tileSize, + } +} + +async function loadPuzzleBitmaps(puzzle) { + // load bitmap, to determine the original size of the image + const bmp = await Graphics.loadImageToBitmap(puzzle.info.imageUrl) + + // creation of tile bitmaps + // then create the final puzzle bitmap + // NOTE: this can decrease OR increase in size! + const bmpResized = await Graphics.resizeBitmap(bmp, puzzle.info.width, puzzle.info.height) + return await createPuzzleTileBitmaps(bmpResized, puzzle.tiles, puzzle.info) +} + +export default { + loadPuzzleBitmaps, +} diff --git a/game/index.js b/game/index.js index 12a2418..786260b 100644 --- a/game/index.js +++ b/game/index.js @@ -1,12 +1,11 @@ "use strict" import {run} from './gameloop.js' import Camera from './Camera.js' -import EventAdapter from './EventAdapter.js' import Graphics from './Graphics.js' import Debug from './Debug.js' import Communication from './Communication.js' -import Geometry from './../common/Geometry.js' import Util from './../common/Util.js' +import PuzzleGraphics from './PuzzleGraphics.js' if (typeof GAME_ID === 'undefined') throw '[ GAME_ID not set ]' if (typeof WS_ADDRESS === 'undefined') throw '[ WS_ADDRESS not set ]' @@ -18,121 +17,6 @@ function addCanvasToDom(canvas) { return canvas } -async function createPuzzleTileBitmaps(img, tiles, info) { - var tileSize = info.tileSize - var tileMarginWidth = info.tileMarginWidth - var tileDrawSize = info.tileDrawSize - var tileRatio = tileSize / 100.0 - - var curvyCoords = [ - 0, 0, 40, 15, 37, 5, - 37, 5, 40, 0, 38, -5, - 38, -5, 20, -20, 50, -20, - 50, -20, 80, -20, 62, -5, - 62, -5, 60, 0, 63, 5, - 63, 5, 65, 15, 100, 0 - ]; - - const bitmaps = new Array(tiles.length) - - const paths = {} - function pathForShape(shape) { - const key = `${shape.top}${shape.right}${shape.left}${shape.bottom}` - if (paths[key]) { - return paths[key] - } - - const path = new Path2D() - const topLeftEdge = { x: tileMarginWidth, y: tileMarginWidth } - path.moveTo(topLeftEdge.x, topLeftEdge.y) - for (let i = 0; i < curvyCoords.length / 6; i++) { - const p1 = Geometry.pointAdd(topLeftEdge, { x: curvyCoords[i * 6 + 0] * tileRatio, y: shape.top * curvyCoords[i * 6 + 1] * tileRatio }) - const p2 = Geometry.pointAdd(topLeftEdge, { x: curvyCoords[i * 6 + 2] * tileRatio, y: shape.top * curvyCoords[i * 6 + 3] * tileRatio }) - const p3 = Geometry.pointAdd(topLeftEdge, { x: curvyCoords[i * 6 + 4] * tileRatio, y: shape.top * curvyCoords[i * 6 + 5] * tileRatio }) - path.bezierCurveTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); - } - const topRightEdge = Geometry.pointAdd(topLeftEdge, { x: tileSize, y: 0 }) - for (let i = 0; i < curvyCoords.length / 6; i++) { - const p1 = Geometry.pointAdd(topRightEdge, { x: -shape.right * curvyCoords[i * 6 + 1] * tileRatio, y: curvyCoords[i * 6 + 0] * tileRatio }) - const p2 = Geometry.pointAdd(topRightEdge, { x: -shape.right * curvyCoords[i * 6 + 3] * tileRatio, y: curvyCoords[i * 6 + 2] * tileRatio }) - const p3 = Geometry.pointAdd(topRightEdge, { x: -shape.right * curvyCoords[i * 6 + 5] * tileRatio, y: curvyCoords[i * 6 + 4] * tileRatio }) - path.bezierCurveTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); - } - const bottomRightEdge = Geometry.pointAdd(topRightEdge, { x: 0, y: tileSize }) - for (let i = 0; i < curvyCoords.length / 6; i++) { - let p1 = Geometry.pointSub(bottomRightEdge, { x: curvyCoords[i * 6 + 0] * tileRatio, y: shape.bottom * curvyCoords[i * 6 + 1] * tileRatio }) - let p2 = Geometry.pointSub(bottomRightEdge, { x: curvyCoords[i * 6 + 2] * tileRatio, y: shape.bottom * curvyCoords[i * 6 + 3] * tileRatio }) - let p3 = Geometry.pointSub(bottomRightEdge, { x: curvyCoords[i * 6 + 4] * tileRatio, y: shape.bottom * curvyCoords[i * 6 + 5] * tileRatio }) - path.bezierCurveTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); - } - const bottomLeftEdge = Geometry.pointSub(bottomRightEdge, { x: tileSize, y: 0 }) - for (let i = 0; i < curvyCoords.length / 6; i++) { - let p1 = Geometry.pointSub(bottomLeftEdge, { x: -shape.left * curvyCoords[i * 6 + 1] * tileRatio, y: curvyCoords[i * 6 + 0] * tileRatio }) - let p2 = Geometry.pointSub(bottomLeftEdge, { x: -shape.left * curvyCoords[i * 6 + 3] * tileRatio, y: curvyCoords[i * 6 + 2] * tileRatio }) - let p3 = Geometry.pointSub(bottomLeftEdge, { x: -shape.left * curvyCoords[i * 6 + 5] * tileRatio, y: curvyCoords[i * 6 + 4] * tileRatio }) - path.bezierCurveTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); - } - paths[key] = path - return path - } - - for (let tile of tiles) { - const srcRect = srcRectByIdx(info, tile.idx) - const path = pathForShape(info.shapes[tile.idx]) - - const c = Graphics.createCanvas(tileDrawSize, tileDrawSize) - const ctx = c.getContext('2d') - // ----------------------------------------------------------- - // ----------------------------------------------------------- - ctx.lineWidth = 2 - ctx.stroke(path) - // ----------------------------------------------------------- - // ----------------------------------------------------------- - ctx.save(); - ctx.clip(path) - ctx.drawImage( - img, - srcRect.x - tileMarginWidth, - srcRect.y - tileMarginWidth, - tileDrawSize, - tileDrawSize, - 0, - 0, - tileDrawSize, - tileDrawSize, - ) - ctx.stroke(path) - ctx.restore(); - - bitmaps[tile.idx] = await createImageBitmap(c) - } - - return bitmaps -} - -function srcRectByIdx(puzzleInfo, idx) { - let c = puzzleInfo.coords[idx] - let cx = c.x * puzzleInfo.tileSize - let cy = c.y * puzzleInfo.tileSize - return { - x: cx, - y: cy, - w: puzzleInfo.tileSize, - h: puzzleInfo.tileSize, - } -} - -async function loadPuzzleBitmaps(puzzle) { - // load bitmap, to determine the original size of the image - const bmp = await Graphics.loadImageToBitmap(puzzle.info.imageUrl) - - // creation of tile bitmaps - // then create the final puzzle bitmap - // NOTE: this can decrease OR increase in size! - const bmpResized = await Graphics.resizeBitmap(bmp, puzzle.info.width, puzzle.info.height) - return await createPuzzleTileBitmaps(bmpResized, puzzle.tiles, puzzle.info) -} - function initme() { // return uniqId() let ID = localStorage.getItem("ID") @@ -152,7 +36,64 @@ const getFirstOwnedTile = (puzzle, userId) => { return null } -async function main () { +export default class EventAdapter { + constructor(canvas, viewport) { + this._mouseEvts = [] + this._viewport = viewport + canvas.addEventListener('mousedown', this._mouseDown.bind(this)) + canvas.addEventListener('mouseup', this._mouseUp.bind(this)) + canvas.addEventListener('mousemove', this._mouseMove.bind(this)) + canvas.addEventListener('wheel', this._wheel.bind(this)) + } + + consumeAll() { + if (this._mouseEvts.length === 0) { + return [] + } + const all = this._mouseEvts.slice() + this._mouseEvts = [] + return all + } + + _mouseDown(e) { + if (e.button === 0) { + const pos = this._viewport.viewportToWorld({ + x: e.offsetX, + y: e.offsetY, + }) + this._mouseEvts.push(['down', pos.x, pos.y]) + } + } + + _mouseUp(e) { + if (e.button === 0) { + const pos = this._viewport.viewportToWorld({ + x: e.offsetX, + y: e.offsetY, + }) + this._mouseEvts.push(['up', pos.x, pos.y]) + } + } + + _mouseMove(e) { + const pos = this._viewport.viewportToWorld({ + x: e.offsetX, + y: e.offsetY, + }) + this._mouseEvts.push(['move', pos.x, pos.y]) + } + + _wheel(e) { + const pos = this._viewport.viewportToWorld({ + x: e.offsetX, + y: e.offsetY, + }) + const evt = e.deltaY < 0 ? 'zoomin' : 'zoomout' + this._mouseEvts.push([evt, pos.x, pos.y]) + } +} + +async function main() { let gameId = GAME_ID let me = initme() @@ -161,7 +102,7 @@ async function main () { const game = await Communication.connect(gameId, me) - const bitmaps = await loadPuzzleBitmaps(game.puzzle) + const bitmaps = await PuzzleGraphics.loadPuzzleBitmaps(game.puzzle) const puzzle = game.puzzle const players = game.players @@ -176,7 +117,6 @@ async function main () { // Create a dom and attach adapters to it so we can work with it const canvas = addCanvasToDom(Graphics.createCanvas()) const ctx = canvas.getContext('2d') - const evts = new EventAdapter(canvas) // initialize some view data // this global data will change according to input events @@ -187,21 +127,27 @@ async function main () { -(puzzle.info.table.height - viewport.height) /2 ) - Communication.onChanges((changes) => { - for (let [type, typeData] of changes) { - switch (type) { + const evts = new EventAdapter(canvas, viewport) + + Communication.onServerChange((msg) => { + const msgType = msg[0] + const evClientId = msg[1] + const evClientSeq = msg[2] + const evChanges = msg[3] + for(let [changeType, changeData] of evChanges) { + switch (changeType) { case 'player': { - if (typeData.id !== me) { - players[typeData.id] = typeData + if (changeData.id !== me) { + players[changeData.id] = changeData rerender = true } } break; case 'tile': { - puzzle.tiles[typeData.idx] = typeData + puzzle.tiles[changeData.idx] = changeData rerender = true } break; case 'data': { - puzzle.data = typeData + puzzle.data = changeData rerender = true } break; } @@ -217,40 +163,41 @@ async function main () { return sorted.sort((t1, t2) => t1.z - t2.z) } - let _last_mouse_down = null const onUpdate = () => { - for (let mouse of evts.consumeAll()) { - const tp = viewport.viewportToWorld(mouse) + for (let evt of evts.consumeAll()) { + const type = evt[0] + const pos = {x: evt[1], y: evt[2]} - if (mouse.type === 'move') { - Communication.addMouse(['move', tp.x, tp.y]) + if (type === 'move') { rerender = true - changePlayer({ x: tp.x, y: tp.y }) + changePlayer(pos) if (_last_mouse_down && !getFirstOwnedTile(puzzle, me)) { // move the cam + const mouse = viewport.worldToViewport(pos) const diffX = Math.round(mouse.x - _last_mouse_down.x) const diffY = Math.round(mouse.y - _last_mouse_down.y) viewport.move(diffX, diffY) _last_mouse_down = mouse } - } else if (mouse.type === 'down') { - Communication.addMouse(['down', tp.x, tp.y]) - _last_mouse_down = mouse - } else if (mouse.type === 'up') { - Communication.addMouse(['up', tp.x, tp.y]) + } else if (type === 'down') { + _last_mouse_down = viewport.worldToViewport(pos) + } else if (type === 'up') { _last_mouse_down = null - } else if (mouse.type === 'wheel') { - if ( - mouse.deltaY < 0 && viewport.zoomIn() - || mouse.deltaY > 0 && viewport.zoomOut() - ) { + } else if (type === 'zoomin') { + if (viewport.zoomIn()) { rerender = true - changePlayer({ x: tp.x, y: tp.y }) + changePlayer(pos) + } + } else if (type === 'zoomout') { + if (viewport.zoomOut()) { + rerender = true + changePlayer(pos) } } + Communication.sendClientEvent(evt) } } diff --git a/server/index.js b/server/index.js index b241553..0c3224c 100644 --- a/server/index.js +++ b/server/index.js @@ -2,14 +2,10 @@ import WebSocketServer from './WebSocketServer.js' import express from 'express' import config from './config.js' +import Protocol from './../common/Protocol.js' import Util from './../common/Util.js' import Game from './Game.js' -const EV_SERVER_STATE_CHANGED = 1 -const EV_SERVER_INIT = 4 -const EV_CLIENT_MOUSE = 2 -const EV_CLIENT_INIT = 3 - // desired number of tiles // actual calculated number can be higher const TARGET_TILES = 1000 @@ -65,35 +61,41 @@ app.use('/', (req, res, next) => { const wss = new WebSocketServer(config.ws); const notify = (data, sockets) => { - // TODO: throttle + // TODO: throttle? for (let socket of sockets) { wss.notifyOne(data, socket) } - // console.log('notify', data) } wss.on('message', async ({socket, data}) => { try { const proto = socket.protocol.split('|') - const playerId = proto[0] + const clientId = proto[0] const gameId = proto[1] - const [type, typeData] = JSON.parse(data) - switch (type) { - case EV_CLIENT_INIT: { + const msg = JSON.parse(data) + const msgType = msg[0] + switch (msgType) { + case Protocol.EV_CLIENT_INIT: { if (!Game.exists(gameId)) { await Game.createGame(gameId, TARGET_TILES, Util.choice(IMAGES)) } - Game.addPlayer(gameId, playerId) + Game.addPlayer(gameId, clientId) Game.addSocket(gameId, socket) - wss.notifyOne([EV_SERVER_INIT, Game.get(gameId)], socket) + notify( + [Protocol.EV_SERVER_INIT, Game.get(gameId)], + [socket] + ) } break; - case EV_CLIENT_MOUSE: { - const changes = Game.handleInput(gameId, playerId, typeData) - if (changes.length > 0) { - notify([EV_SERVER_STATE_CHANGED, changes], Game.getSockets(gameId)) - } + case Protocol.EV_CLIENT_EVENT: { + const clientSeq = msg[1] + const clientEvtData = msg[2] + const changes = Game.handleInput(gameId, clientId, clientEvtData) + notify( + [Protocol.EV_SERVER_EVENT, clientId, clientSeq, changes], + Game.getSockets(gameId) + ) } break; } } catch (e) {