From 1cf66c9e98d0ea5ebf4df9705e999be7d04fe503 Mon Sep 17 00:00:00 2001 From: Henry Aviles <108551827+Haviles04@users.noreply.github.com> Date: Tue, 7 Jan 2025 11:19:06 -0500 Subject: [PATCH] Feat #1031 Usercontroller.relogin gamestate rework (#1140) * feat: added conditional logic based on gamestate for relogin * test: removed skipper * Update api/controllers/UserController.js Co-authored-by: Ryan Emberling * Update api/controllers/UserController.js Co-authored-by: Ryan Emberling * fix: removed .loggedIn * fix: populating p0, p1 * chore: new line * test: fixed previously bugged test * fix: bugged test * test: updated test fixture * fix: set pnum if missed event * feat: added logic for lobby reload * fix: only add p1 if in game model * Update api/helpers/game-states/create-socket-event.js * feat: updated the way socket event is handled * fix: unneeded changes --------- Co-authored-by: Ryan Emberling Co-authored-by: Sean Kennedy --- api/controllers/UserController.js | 29 +++++++++++++ .../in-game/game-over/winConditions.spec.js | 1 + tests/e2e/specs/in-game/reconnecting.spec.js | 43 +++---------------- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/api/controllers/UserController.js b/api/controllers/UserController.js index 930a0df4d..3d7b8ea43 100644 --- a/api/controllers/UserController.js +++ b/api/controllers/UserController.js @@ -63,6 +63,34 @@ module.exports = { } // Query for game if user is in one const gameId = (user.game ?? req.session.game) ?? null; + + if (process.env.VITE_USE_GAMESTATE_API) { + const { unpackGamestate, createSocketEvent } = sails.helpers.gameStates; + const game = await Game.findOne(gameId) + .populate('gameStates') + .populate('p0') + .populate('p1'); + const gameObject = game.gameStates.length ? await unpackGamestate(game.gameStates.at(-1)) : null; + const socketEvent = game.gameStates.length ? + await createSocketEvent(game, gameObject) + : { game: { ...game, players: game.p1 ? [ game.p0, game.p1 ] : [ game.p0 ] } }; + + Game.subscribe(req, [ game.id ]); + req.session.usr = user.id; + // FIXME: #965 - remove game and pNum + req.session.game = game.id; + req.session.pNum = user.pNum ?? undefined; + Game.publish([ game.id ],socketEvent); + + const pNum = game.p0?.id === user.id ? 0 : 1; + return res.ok({ + game: socketEvent.game, + username: user.username, + pNum + }); + } + // FIXME: #965 + // Remove everything between here and catch AFTER gamestate is deployed const unpopulatedGame = gameId ? await gameService.findGame({ gameId }) : null; const populatedGame = unpopulatedGame?.status === GameStatus.STARTED @@ -97,6 +125,7 @@ module.exports = { username: user.username, pNum: user.pNum, }); + } catch (err) { return res.badRequest(err); } diff --git a/tests/e2e/specs/in-game/game-over/winConditions.spec.js b/tests/e2e/specs/in-game/game-over/winConditions.spec.js index 9412d5cae..cfb0ee1ca 100644 --- a/tests/e2e/specs/in-game/game-over/winConditions.spec.js +++ b/tests/e2e/specs/in-game/game-over/winConditions.spec.js @@ -401,6 +401,7 @@ describe('Stalemates', () => { }); it('Player requests stalemate, then reloads before opponent accepts', () => { + cy.skipOnGameStateApi(); cy.setupGameAsP1(); cy.get('#game-menu-activator').click(); cy.get('#game-menu').should('be.visible') diff --git a/tests/e2e/specs/in-game/reconnecting.spec.js b/tests/e2e/specs/in-game/reconnecting.spec.js index 778422291..0f62f5701 100644 --- a/tests/e2e/specs/in-game/reconnecting.spec.js +++ b/tests/e2e/specs/in-game/reconnecting.spec.js @@ -4,7 +4,6 @@ import { Card } from '../../fixtures/cards'; describe('Reconnecting to a game', () => { it('Refreshs Game from Game Menu', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP1(); cy.loadGameFixture(1, { p0Hand: [ Card.ACE_OF_CLUBS, Card.SEVEN_OF_DIAMONDS ], @@ -44,7 +43,6 @@ describe('Reconnecting to a game', () => { }); it('Persists session after refreshing the page', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP0(); cy.loadGameFixture(0, { @@ -74,7 +72,6 @@ describe('Reconnecting to a game', () => { }); it('Reconnects after refreshing the page', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP0(); cy.loadGameFixture(0, { @@ -105,7 +102,6 @@ describe('Reconnecting to a game', () => { describe('Reconnecting into Cannot Counter Dialog', () => { it('oneOff - Reconnect into cannot counter dialog', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP1(); cy.loadGameFixture(1, { @@ -141,7 +137,6 @@ describe('Reconnecting to a game', () => { }); it('targetedOneOff -- reconnect into cannot counter dialog', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP1(); cy.loadGameFixture(1, { @@ -177,7 +172,6 @@ describe('Reconnecting to a game', () => { }); it('counter -- Reconnect into cannot counter dialog', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP0(); cy.loadGameFixture(0, { p0Hand: [ Card.ACE_OF_CLUBS ], @@ -215,7 +209,6 @@ describe('Reconnecting to a game', () => { }); it('sevenOneOff -- Reconnect into cannot counter dialog', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP1(); cy.loadGameFixture(1, { p0Hand: [ Card.SEVEN_OF_CLUBS ], @@ -259,7 +252,6 @@ describe('Reconnecting to a game', () => { }); it('sevenTargetedOneOff -- Reconnect into cannot counter dialog', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP1(); cy.loadGameFixture(1, { p0Hand: [ Card.SEVEN_OF_CLUBS ], @@ -297,7 +289,6 @@ describe('Reconnecting to a game', () => { }); it('Opponent reconnects while player is in cannot-counter dialog', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP1(); cy.loadGameFixture(1, { @@ -334,7 +325,6 @@ describe('Reconnecting to a game', () => { describe('Reconnecting into Counter Dialog', () => { it('oneOff -- Reconnect into Counter Dialog', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP1(); cy.loadGameFixture(1, { p0Hand: [ Card.ACE_OF_CLUBS ], @@ -374,7 +364,6 @@ describe('Reconnecting to a game', () => { }); it('targetedOneOff -- reconnect into counter dialog', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP1(); cy.loadGameFixture(1, { p0Hand: [ Card.TWO_OF_SPADES ], @@ -417,7 +406,6 @@ describe('Reconnecting to a game', () => { }); it('targetedOneOff -- reconnect into waiting for opponent to counter overlay', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP1(); cy.loadGameFixture(1, { p0Hand: [ Card.TWO_OF_SPADES ], @@ -462,7 +450,6 @@ describe('Reconnecting to a game', () => { }); it('counter -- Reconnect into counter dialog', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP0(); cy.loadGameFixture(0, { p0Hand: [ Card.ACE_OF_CLUBS, Card.TWO_OF_SPADES ], @@ -518,7 +505,6 @@ describe('Reconnecting to a game', () => { }); it('sevenOneOff -- Reconnect into counter dialog', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP1(); cy.loadGameFixture(1, { p0Hand: [ Card.SEVEN_OF_CLUBS ], @@ -561,7 +547,6 @@ describe('Reconnecting to a game', () => { }); it('sevenTargetedOneOff -- Reconnect into counter dialog', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP1(); cy.loadGameFixture(1, { p0Hand: [ Card.SEVEN_OF_CLUBS ], @@ -608,7 +593,6 @@ describe('Reconnecting to a game', () => { describe('Reconnecting into One-Off resolutions', () => { describe('Reconnecting into 3s', () => { it('Resolve 3 after reconnect -- Player fetches card', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP0(); cy.loadGameFixture(0, { p0Hand: [ Card.THREE_OF_CLUBS ], @@ -647,7 +631,6 @@ describe('Reconnecting to a game', () => { }); it('Resolve opponents three after reconnect', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP1(); cy.loadGameFixture(1, { p0Hand: [ Card.THREE_OF_CLUBS ], @@ -687,7 +670,6 @@ describe('Reconnecting to a game', () => { }); // End 3's reconnect it('Resolve 4 after reconnect - Player discards', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP1(); cy.loadGameFixture(1, { p0Hand: [ Card.FOUR_OF_CLUBS ], @@ -727,7 +709,6 @@ describe('Reconnecting to a game', () => { }); it('Resolve 7 after reconnect - Player', () => { - cy.skipOnGameStateApi(); cy.setupGameAsP0(); cy.loadGameFixture(0, { p0Hand: [ Card.SEVEN_OF_CLUBS ], @@ -815,7 +796,6 @@ describe('Reconnecting after game is over', () => { }); it('Dialogs persist after refreshing when game is over by conceded and opponent request rematch', () => { - cy.skipOnGameStateApi(); cy.concedeOpponent(); cy.get('[data-cy=game-over-dialog]').should('be.visible'); cy.reload(); @@ -834,7 +814,6 @@ describe('Reconnecting after game is over', () => { }); it('Dialogs persist after refreshing when game is over by conceded and player request rematch', () => { - cy.skipOnGameStateApi(); cy.concedeOpponent(); cy.get('[data-cy=game-over-dialog]').should('be.visible'); cy.reload(); @@ -849,6 +828,7 @@ describe('Reconnecting after game is over', () => { }); it('Dialogs persist after refreshing when game is over by stalemate', () => { + cy.skipOnGameStateApi(); cy.get('#game-menu-activator').click(); cy.get('#game-menu').should('be.visible') .get('[data-cy=stalemate-initiate]') @@ -863,7 +843,6 @@ describe('Reconnecting after game is over', () => { }); it('Dialogs persist after refreshing when game is over by passing', () => { - cy.skipOnGameStateApi(); cy.loadGameFixture(0, { p0Hand: [ Card.SEVEN_OF_CLUBS ], p0Points: [ Card.SEVEN_OF_DIAMONDS, Card.SEVEN_OF_HEARTS ], @@ -871,6 +850,8 @@ describe('Reconnecting after game is over', () => { p1Hand: [], p1Points: [], p1FaceCards: [], + topCard: Card.TWO_OF_CLUBS, + secondCard: Card.ACE_OF_HEARTS, deck: [], }); @@ -891,7 +872,6 @@ describe('Reconnecting after game is over', () => { }); it('Dialogs persist after refreshing when game is over by points', () => { - cy.skipOnGameStateApi(); cy.loadGameFixture(0, { p0Hand: [ Card.SEVEN_OF_CLUBS ], p0Points: [ Card.SEVEN_OF_DIAMONDS, Card.SEVEN_OF_HEARTS ], @@ -911,7 +891,6 @@ describe('Reconnecting after game is over', () => { }); it('Dialogs persist after refreshing when game is over by points playing jack', () => { - cy.skipOnGameStateApi(); cy.loadGameFixture(0, { p0Hand: [ Card.JACK_OF_DIAMONDS ], p0Points: [ Card.SEVEN_OF_DIAMONDS, Card.SEVEN_OF_HEARTS ], @@ -932,7 +911,6 @@ describe('Reconnecting after game is over', () => { }); it('Dialogs persist after refreshing when game is over by points playing king', () => { - cy.skipOnGameStateApi(); cy.loadGameFixture(0, { p0Hand: [ Card.KING_OF_DIAMONDS ], p0Points: [ Card.SEVEN_OF_DIAMONDS, Card.SEVEN_OF_HEARTS ], @@ -952,7 +930,6 @@ describe('Reconnecting after game is over', () => { }); it('Dialogs persist after refreshing when game is over by resolving one-off', () => { - cy.skipOnGameStateApi(); cy.loadGameFixture(0, { p0Hand: [ Card.SIX_OF_DIAMONDS, Card.SEVEN_OF_SPADES ], p0Points: [ Card.SEVEN_OF_DIAMONDS, Card.SEVEN_OF_HEARTS ], @@ -960,7 +937,6 @@ describe('Reconnecting after game is over', () => { p1Hand: [ Card.JACK_OF_CLUBS ], p1Points: [], p1FaceCards: [], - deck: [], }); cy.get('#deck').click(); @@ -979,7 +955,6 @@ describe('Reconnecting after game is over', () => { }); it('Dialogs persist after refreshing when game is over by resolving one-off from a seven', () => { - cy.skipOnGameStateApi(); cy.loadGameFixture(0, { p0Hand: [ Card.SIX_OF_DIAMONDS, Card.SEVEN_OF_SPADES ], p0Points: [ Card.SEVEN_OF_DIAMONDS, Card.SEVEN_OF_HEARTS ], @@ -1009,13 +984,12 @@ describe('Reconnecting after game is over', () => { }); it('Dialogs persist after refreshing when game is over by playing jack from a seven', () => { - cy.skipOnGameStateApi(); cy.loadGameFixture(0, { p0Hand: [ Card.SIX_OF_DIAMONDS, Card.SEVEN_OF_SPADES ], p0Points: [ Card.SEVEN_OF_HEARTS, Card.SEVEN_OF_DIAMONDS ], p0FaceCards: [], p1Hand: [], - p1Points: [ Card.SEVEN_OF_SPADES ], + p1Points: [ Card.SEVEN_OF_CLUBS ], p1FaceCards: [], topCard: Card.JACK_OF_DIAMONDS, deck: [], @@ -1029,7 +1003,7 @@ describe('Reconnecting after game is over', () => { .click(); cy.get('[data-move-choice=jack]').should('be.visible') .click(); - cy.get('[data-opponent-point-card=7-3]').should('be.visible') + cy.get('[data-opponent-point-card=7-0]').should('be.visible') .click(); cy.get('[data-cy=game-over-dialog]').should('be.visible'); cy.reload(); @@ -1037,7 +1011,6 @@ describe('Reconnecting after game is over', () => { }); it('Dialogs persist after refreshing when game is over by playing points from a seven', () => { - cy.skipOnGameStateApi(); cy.loadGameFixture(0, { p0Hand: [ Card.SIX_OF_DIAMONDS, Card.SEVEN_OF_SPADES ], p0Points: [ Card.SEVEN_OF_HEARTS, Card.SEVEN_OF_DIAMONDS ], @@ -1045,7 +1018,7 @@ describe('Reconnecting after game is over', () => { p1Hand: [], p1Points: [], p1FaceCards: [], - topCard: Card.SEVEN_OF_SPADES, + topCard: Card.SEVEN_OF_CLUBS, deck: [], }); @@ -1053,7 +1026,7 @@ describe('Reconnecting after game is over', () => { cy.get('[data-move-choice=oneOff]').should('be.visible') .click(); cy.resolveOpponent(); - cy.get('[data-top-card=7-3]').click(); + cy.get('[data-top-card=7-0]').click(); cy.get('[data-move-choice=points]').should('be.visible') .click(); cy.get('[data-cy=game-over-dialog]').should('be.visible'); @@ -1062,7 +1035,6 @@ describe('Reconnecting after game is over', () => { }); it('Brings player to the rematch game when player hits rematch, disconnects, then refreshes after opponent hit rematch and started game', () => { - cy.skipOnGameStateApi(); cy.concedeOpponent(); cy.get('[data-cy=gameover-rematch').should('not.be.disabled') @@ -1115,7 +1087,6 @@ describe('Reconnecting after game is over', () => { }); it('Brings player to the rematch game when player hits rematch, disconnects, then reconnects socket after opponent hit rematch and started game', () => { - cy.skipOnGameStateApi(); cy.concedeOpponent(); cy.get('[data-cy=gameover-rematch').should('not.be.disabled')