diff options
Diffstat (limited to 'frontend/src/sagas')
-rw-r--r-- | frontend/src/sagas/gameBrowser.js | 77 | ||||
-rw-r--r-- | frontend/src/sagas/lobby.js | 58 |
2 files changed, 91 insertions, 44 deletions
diff --git a/frontend/src/sagas/gameBrowser.js b/frontend/src/sagas/gameBrowser.js index 4f3309c3..10d6ec1d 100644 --- a/frontend/src/sagas/gameBrowser.js +++ b/frontend/src/sagas/gameBrowser.js @@ -1,73 +1,62 @@ import { call, put, take, apply } from 'redux-saga/effects' -import { eventChannel } from 'redux-saga' +import { createSubscriptionChannel } from '../utils/websocket' import { push } from 'react-router-redux' import { normalize } from 'normalizr' -import { game, gameList } from '../schemas/games' +import { game as gameSchema, gameList as gameListSchema} from '../schemas/games' import { actions as gameActions, types } from '../redux/games' import { actions as playerActions } from '../redux/players' -function gameBrowserChannel(socket) { - return eventChannel(emit => { - - const makeHandler = type => event => { - const response = JSON.parse(event.body) - emit({type, response}) - } - - const newGame = socket.subscribe('/topic/games', makeHandler(types.UPDATE_GAMES)) - const joinGame = socket.subscribe('/user/queue/lobby/joined', makeHandler(types.ENTER_LOBBY)) - - return () => { - newGame.unsubscribe() - joinGame.unsubscribe() +function *watchGames({socket}) { + const gamesChannel = yield call(createSubscriptionChannel, socket, '/topic/games') + try { + while (true) { + const gameList = yield take(gamesChannel) + const normGameList = normalize(gameList, gameListSchema) + // for an empty game array, there is no players/games entity maps + yield put(playerActions.updatePlayers(normGameList.entities.players || {})) + yield put(gameActions.updateGames(normGameList.entities.games || {})) } - }) + } finally { + yield apply(gamesChannel, gamesChannel.close) + } } -export function *watchGames({socket}) { - const socketChannel = gameBrowserChannel(socket) - +function *watchLobbyJoined({socket}) { + const joinedLobbyChannel = yield call(createSubscriptionChannel, socket, '/user/queue/lobby/joined') try { - while (true) { - const {type, response} = yield take(socketChannel) - - switch (type) { - case types.UPDATE_GAMES: - const normGameList = normalize(response, gameList) - yield put(playerActions.updatePlayers(normGameList.entities.players || {})) - yield put(gameActions.updateGames(normGameList.entities.games || {})) - break - case types.ENTER_LOBBY: - const normGame = normalize(response, game) - yield put(gameActions.enterLobby(normGame.entities.games[normGame.result])) - socketChannel.close() - yield put(push('/lobby')) - break - default: - console.error('Unknown type') - } - } + const joinedLobby = yield take(joinedLobbyChannel) + const normalized = normalize(joinedLobby, gameSchema) + const gameId = normalized.result + yield put(playerActions.updatePlayers(normalized.entities.players)) + yield put(gameActions.updateGames(normalized.entities.games)) + yield put(gameActions.enterLobby(normalized.entities.games[gameId])) + yield put(push(`/lobby/${gameId}`)) } finally { - console.info('gameBrowserChannel closed') + yield apply(joinedLobbyChannel, joinedLobbyChannel.close) } } -export function *createGame({socket}) { +function *createGame({socket}) { const {gameName} = yield take(types.REQUEST_CREATE_GAME) yield apply(socket, socket.send, ['/app/lobby/create', JSON.stringify({gameName}), {}]) } -export function *joinGame({socket}) { +function *joinGame({socket}) { const {gameId} = yield take(types.REQUEST_JOIN_GAME) yield apply(socket, socket.send, ['/app/lobby/join', JSON.stringify({gameId}), {}]) } -export function *gameBrowserSaga(socketConnection) { - yield [call(watchGames, socketConnection), call(createGame, socketConnection), call(joinGame, socketConnection)] +function *gameBrowserSaga(socketConnection) { + yield [ + call(watchGames, socketConnection), + call(watchLobbyJoined, socketConnection), + call(createGame, socketConnection), + call(joinGame, socketConnection) + ] } export default gameBrowserSaga diff --git a/frontend/src/sagas/lobby.js b/frontend/src/sagas/lobby.js new file mode 100644 index 00000000..f002c897 --- /dev/null +++ b/frontend/src/sagas/lobby.js @@ -0,0 +1,58 @@ +import { call, put, take, apply } from 'redux-saga/effects' +import { createSubscriptionChannel } from '../utils/websocket' +import { push } from 'react-router-redux' + +import { normalize } from 'normalizr' +import { game as gameSchema } from '../schemas/games' + +import { actions as gameActions, types } from '../redux/games' +import { actions as playerActions } from '../redux/players' + +function getCurrentGameId() { + const path = window.location.pathname + return path.split('lobby/')[1] +} + +function *watchLobbyUpdates({ socket }) { + const currentGameId = getCurrentGameId() + const lobbyUpdatesChannel = yield call(createSubscriptionChannel, socket, `/topic/lobby/${currentGameId}/updated`) + try { + while (true) { + const lobby = yield take(lobbyUpdatesChannel) + const normalized = normalize(lobby, gameSchema) + yield put(gameActions.updateGames(normalized.entities.games)) + yield put(playerActions.updatePlayers(normalized.entities.players)) + } + } finally { + yield apply(lobbyUpdatesChannel, lobbyUpdatesChannel.close) + } +} + +function *watchGameStart({ socket }) { + const currentGameId = getCurrentGameId() + const gameStartedChannel = yield call(createSubscriptionChannel, socket, `/topic/lobby/${currentGameId}/started`) + try { + yield take(gameStartedChannel) + yield put(gameActions.enterGame()) + yield put(push('/game')) + } finally { + yield apply(gameStartedChannel, gameStartedChannel.close) + } +} + +function *startGame({ socket }) { + while (true) { + yield take(types.REQUEST_START_GAME) + yield apply(socket, socket.send, ['/app/lobby/startGame', {}]) + } +} + +function *lobbySaga(socketConnection) { + yield [ + call(watchLobbyUpdates, socketConnection), + call(watchGameStart, socketConnection), + call(startGame, socketConnection) + ] +} + +export default lobbySaga |