Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
243 commits
Select commit Hold shift + click to select a range
d82409a
feat: add start game websocket dto
tasaje1 May 10, 2026
d268f37
feat: add lobby getter for websocket gameplay
tasaje1 May 10, 2026
f94dba4
refactor: inject gameplay websocket dependencies
tasaje1 May 10, 2026
3fb4b69
feat: add in memory game session storage
tasaje1 May 10, 2026
8a4ede1
refactor: encapsulate starting team selection in lobby service
tasaje1 May 10, 2026
06ae58b
feat: add websocket endpoint for starting games
tasaje1 May 10, 2026
3dd55fe
feat: add reveal card websocket dto
tasaje1 May 10, 2026
d3fcd88
feat: add websocket endpoint for revealing cards
tasaje1 May 10, 2026
11b88f9
feat: add clue websocket dto
tasaje1 May 10, 2026
4ce3354
feat: add websocket endpoint for clue submission
tasaje1 May 10, 2026
b216d7b
test: add game websocket controller tests
tasaje1 May 10, 2026
06384b0
test: verify websocket gameplay interactions
tasaje1 May 10, 2026
26bde4a
test: verify submit clue ignores missing game session
tasaje1 May 10, 2026
fe1e897
test: verify starting team selection
tasaje1 May 10, 2026
d695459
test: verify starting team selection returns null for missing lobby
tasaje1 May 10, 2026
9b127f5
docs: add javadocs
tasaje1 May 10, 2026
80ee9a4
style: fix imports
tasaje1 May 10, 2026
78723e0
Merge remote-tracking branch 'origin/main' into chore/merge-main-into…
tasaje1 May 11, 2026
83615c1
Merge pull request #98 from SS26-SE2-Codenames/chore/merge-main-into-…
tasaje1 May 11, 2026
66c486d
Merge branch 'development' into feature/websocket-gameplay-endpoints
tasaje1 May 11, 2026
dfdfff6
refactor: extract websocket game topic constant
tasaje1 May 11, 2026
869a89f
refactor: clean up websocket gameplay controller
tasaje1 May 11, 2026
62a7fe3
refactor: change incorrect use of enum for turn and winner
XtophB May 12, 2026
5142885
refactor: change incorrect use of enum for turn and winner in test class
XtophB May 12, 2026
c15de8c
refactor: change parameter type to Team
XtophB May 12, 2026
b276bcc
refactor: change String to Team enum
XtophB May 12, 2026
6bd03c3
refactor: remove unused variable
XtophB May 12, 2026
a306ffe
change lobby response to have a parameter playerList for frontend com…
the-only-queen-anna May 13, 2026
5f75c21
refactor: use Team datatype instead of string in DTO
XtophB May 13, 2026
59eb6a7
refactor: use Team data type instead of String as payload
XtophB May 13, 2026
e6ec847
refactor: change fix mismatched test - use Team instead of String
XtophB May 13, 2026
a58a119
refactor: split line - too long for google code style
XtophB May 13, 2026
38ff8d0
Merge pull request #99 from SS26-SE2-Codenames/maintenance/refactor-i…
XtophB May 13, 2026
7ade517
Merge remote-tracking branch 'origin/development' into feature/websoc…
tasaje1 May 13, 2026
93ab424
feat: add method to advance the current turn and role
XtophB May 13, 2026
55666ac
feat: add a check for correct turn or role
XtophB May 13, 2026
124dc3b
add methods to be called by endpoints to access GameManager methods
XtophB May 13, 2026
3d37b21
added endpoint for lobby updates and new dto for player list transfer…
the-only-queen-anna May 13, 2026
3ba5426
minor changes to leave flow
the-only-queen-anna May 13, 2026
5f828fb
lobbies are now removed when they are empty
the-only-queen-anna May 13, 2026
c040d67
test: add and fix test for lobby controller and service
the-only-queen-anna May 13, 2026
9b23f16
refactor: remove parameter since current team color is accessible
XtophB May 14, 2026
6b5dadf
feat: add method to end turn early
XtophB May 14, 2026
753cbd3
feat: add check to end turn when wrong card is flipped or out of guesses
XtophB May 14, 2026
5284f71
refactor: have method read from class attribute instead of passing it
XtophB May 14, 2026
7a0369d
refactor: replace reveal card color turn state with team model
tasaje1 May 14, 2026
a071b50
fix: change parameter for checkCorrectTurn
XtophB May 14, 2026
6b5ae25
test: align websocket gameplay tests with team turn handling
tasaje1 May 14, 2026
1a9efb0
fix: add callingTeam parameter that should be passed by frontend
XtophB May 14, 2026
0cf8e11
feat: add gameplay state dto
tasaje1 May 14, 2026
feca412
refactor: add gameplay state mapping helper
tasaje1 May 14, 2026
e15434b
refactor: unify websocket gameplay response payloads
tasaje1 May 14, 2026
b0f3991
style: fix checkstyle line length violation
tasaje1 May 14, 2026
23ff4f5
feat: add creating and storing GameMmanager for lobbies
XtophB May 14, 2026
f95fa18
fix: remove GameManager parameter as frontend should not know what gm is
XtophB May 14, 2026
770b81c
feat: add health endpoint for deployment monitoring
tasaje1 May 14, 2026
e38bbd6
docs: add JavaDocs for health endpoint
tasaje1 May 14, 2026
dff6b21
feat: create GameService and GameManager when a lobby is created
XtophB May 14, 2026
9347d5a
Merge remote-tracking branch 'origin/development' into feature/health…
tasaje1 May 14, 2026
beeba51
refactor: extract creation of GM for a lobby
XtophB May 14, 2026
213bac9
fix: add gameService mock to class test
XtophB May 14, 2026
a518444
docs: add java docs
XtophB May 14, 2026
ca28397
docs: add missing punctuation for checkstyle
XtophB May 14, 2026
9caa3f6
test: add test for verification of addGameManagerForLobby is invvoked
XtophB May 14, 2026
6c2e3ac
docs: fix check style
XtophB May 14, 2026
ec74ca4
docs: add missing param annotation in docs
XtophB May 14, 2026
aaa165f
fix: add missing parameters as source code changed
XtophB May 14, 2026
5cfc33f
test: add test to ensure we start with correct team and role
XtophB May 14, 2026
47a1d89
test: add test to ensure correct state after advancing once
XtophB May 14, 2026
2cf04a1
test: add test for advancing turn twice
XtophB May 14, 2026
50a3e34
test: add tests for passing turn voluntarily
XtophB May 14, 2026
048803a
test: add test for checking turn and role
XtophB May 14, 2026
74366d1
test: add test class for GameService
XtophB May 14, 2026
24217b8
fix errors in test due to incorrect turn and game phase
XtophB May 14, 2026
8fbbf92
feat: extract GameManager creation out of GameService into Factory
XtophB May 14, 2026
1f3f72c
refactor: use factory instead of creating
XtophB May 14, 2026
26e78e1
refactor: delete unused import
XtophB May 14, 2026
a1753a7
test: fix InvalidUseOfMatchers error
XtophB May 14, 2026
a731794
refactor: rename class
XtophB May 14, 2026
fc8a121
test: add tests for GameService
XtophB May 14, 2026
9da4938
test: add test class for GameManagerFactory
XtophB May 14, 2026
ab8c491
refactor: define variables for maintenance
XtophB May 14, 2026
85bde15
refactor: remove smells and SOLID violations
XtophB May 14, 2026
aec7377
refactor: replace DRY violations with helper methods
XtophB May 14, 2026
7780390
change lobby controller to use proper http methods
the-only-queen-anna May 15, 2026
11a41c0
added logger to lobby service
the-only-queen-anna May 15, 2026
9403127
test: update tests for lobby classes
the-only-queen-anna May 15, 2026
b37010b
style: added some java docs, checkstyle check
the-only-queen-anna May 15, 2026
eafbd35
resolve merge conflicts
the-only-queen-anna May 15, 2026
5a0f6bf
style: further refactoring plus merge with other device, forgotten co…
the-only-queen-anna May 15, 2026
101bb71
Merge pull request #100 from SS26-SE2-Codenames/feature/11-turn-manag…
XtophB May 15, 2026
efe60ff
fix: when lobby is empty, also the chat history is deleted
the-only-queen-anna May 15, 2026
b402384
merge with development
the-only-queen-anna May 15, 2026
b055978
fix: lobby is now also removed from gameService lists when it is empty
the-only-queen-anna May 15, 2026
831e9b4
log: added log output
the-only-queen-anna May 15, 2026
babf312
sonar: removed empty constructor of record class
the-only-queen-anna May 15, 2026
8e054d6
fix: minor fixes, see requested changes
the-only-queen-anna May 15, 2026
78988e2
style: reordered imports to fit checkstyles wishes
the-only-queen-anna May 15, 2026
ee1c2dd
test: removed tests that tested the unreachable if-else-branch
the-only-queen-anna May 15, 2026
efa79bc
Merge remote-tracking branch 'origin/development' into feature/websoc…
tasaje1 May 16, 2026
d970836
refactor: inject game service into websocket controller
tasaje1 May 16, 2026
1ca9086
refactor: simplify websocket controller dependencies
tasaje1 May 16, 2026
0adbd6e
feat: expose game state retrieval in game service
tasaje1 May 16, 2026
8da5538
refactor: use game service for start game state updates
tasaje1 May 16, 2026
d961772
refactor: delegate reveal card handling to game service
tasaje1 May 16, 2026
9dacbfc
refactor: add calling team to clue websocket message
tasaje1 May 16, 2026
b0bf540
refactor: delegate clue submission to game service
tasaje1 May 16, 2026
213c707
feat: add game state dto creation to game service
tasaje1 May 16, 2026
d182d0c
refactor: remove game state mapping from websocket controller
tasaje1 May 16, 2026
d4c6899
refactor: use game service for websocket response mapping
tasaje1 May 16, 2026
2782e3b
Merge pull request #102 from SS26-SE2-Codenames/lobby-integration
the-only-queen-anna May 16, 2026
d34d5f8
refactor: remove unused game state retrieval in websocket controller
tasaje1 May 16, 2026
a41f1a0
style: remove unused imports from websocket controller
tasaje1 May 16, 2026
cbe1ba4
Merge remote-tracking branch 'origin/development' into feature/websoc…
tasaje1 May 16, 2026
063e82a
test: align websocket controller tests with game service architecture
tasaje1 May 16, 2026
5a843b3
test: verify game state retrieval from service
tasaje1 May 16, 2026
032600a
test: verify game state dto creation
tasaje1 May 16, 2026
8b379ac
docs: add/modify javadocs
tasaje1 May 16, 2026
1d2dfa2
refactor: remove unused lobby starting team retrieval
tasaje1 May 16, 2026
1e95506
style: fix imports
tasaje1 May 16, 2026
a60e49f
style: fix test method naming to satisfy checkstyle
tasaje1 May 16, 2026
ef0f088
feat: include current turn and phase in game state dto
tasaje1 May 16, 2026
8da1fca
style: add line-break
tasaje1 May 16, 2026
4024650
Merge remote-tracking branch 'origin/development' into feature/game-s…
tasaje1 May 16, 2026
4d5e67a
feat: add websocket message for turn passing
tasaje1 May 16, 2026
5b8678f
feat: add current phase of the game to allow frontend show game loop
XtophB May 16, 2026
55a6292
feat: add websocket endpoint for passing turns
tasaje1 May 16, 2026
03d821a
refactor: move advance turn method into gameManager
XtophB May 16, 2026
bd4365c
test: add coverage for websocket pass turn endpoint
tasaje1 May 16, 2026
78737b5
docs: add Javadocs
tasaje1 May 16, 2026
6c21e7f
fix: update test to take current phase parameter
XtophB May 16, 2026
6e5f469
fix: add current phase to the expected value
XtophB May 16, 2026
8be964c
fix: change spymaster to operative in winning phase
XtophB May 16, 2026
c4272be
fix: service test should no longer verify advance turn being called
XtophB May 16, 2026
ecfeb77
fix: old tests were still assuming that submitClue did not advance turn
XtophB May 16, 2026
d2ad75b
refactor: remove accidentally added import
XtophB May 16, 2026
1cf9ae9
Merge remote-tracking branch 'origin/development' into feature/health…
tasaje1 May 17, 2026
8537f2c
test: add test for health endpoint
tasaje1 May 17, 2026
df0b016
Merge pull request #96 from SS26-SE2-Codenames/feature/websocket-game…
tasaje1 May 17, 2026
b4ecf64
Merge remote-tracking branch 'origin/development' into feature/health…
tasaje1 May 17, 2026
5194f41
add game start endpoint to lobby service
the-only-queen-anna May 17, 2026
84a7786
Merge branch 'development' into game-start
the-only-queen-anna May 17, 2026
6807a1d
Merge branch 'development' into feature/game-state-recovery-reconnect
tasaje1 May 17, 2026
83f1c0c
Merge branch 'development' into feature/51-update-game-state-dto
XtophB May 17, 2026
dd6f74d
refactor: keep lobby players on websocket disconnect
tasaje1 May 17, 2026
ad4be46
feat: send current game state on websocket join reconnect
tasaje1 May 17, 2026
5d7d21d
test: update websocket disconnect listener tests for reconnect behavior
tasaje1 May 17, 2026
95eed7d
test: update websocket disconnect listener tests for reconnect behavior
tasaje1 May 17, 2026
a31e654
docs: modify javadocs
tasaje1 May 17, 2026
1ffc137
style: remove constant parameter warning in websocket listener test
tasaje1 May 17, 2026
a94e25e
Merge branch 'development' into feature/health-endpoint
tasaje1 May 17, 2026
8505ccb
Merge branch 'feature/health-endpoint' of https://github.com/SS26-SE2…
tasaje1 May 17, 2026
d250720
websocket now returns a game state data transfer object, added some h…
the-only-queen-anna May 17, 2026
bc9d867
test: added & fixed tests
the-only-queen-anna May 17, 2026
cc5590c
refactor: resolved checkstyle and sonar issues
the-only-queen-anna May 17, 2026
5b021ab
Merge pull request #105 from SS26-SE2-Codenames/feature/health-endpoint
tasaje1 May 18, 2026
271b12d
Merge branch 'development' into feature/game-state-recovery-reconnect
tasaje1 May 18, 2026
c28f576
Merge pull request #106 from SS26-SE2-Codenames/feature/game-state-re…
tasaje1 May 18, 2026
10d1ea5
Merge branch 'development' into feature/51-update-game-state-dto
XtophB May 18, 2026
7c6d356
Merge pull request #104 from SS26-SE2-Codenames/feature/51-update-gam…
XtophB May 18, 2026
22ea0cb
merge with development + test fix
the-only-queen-anna May 18, 2026
f9802da
Merge remote-tracking branch 'origin/development' into feature/game-s…
tasaje1 May 18, 2026
2bde83a
feat: add system snapshot model for restart recovery
tasaje1 May 18, 2026
4f6ec34
feat: add json state store for atomic snapshot persistence
tasaje1 May 18, 2026
a888582
docs: add javadocs
tasaje1 May 18, 2026
11c84b1
test: add unit tests for json state store load and save behavior
tasaje1 May 18, 2026
55bae8f
test: replace redundant lobby emptiness assertion with size check
tasaje1 May 18, 2026
acef437
change data type in game state dto
the-only-queen-anna May 18, 2026
2cbaf40
Merge pull request #107 from SS26-SE2-Codenames/game-start
the-only-queen-anna May 18, 2026
2076b2c
Merge branch 'development' into clue-system-fix
the-only-queen-anna May 18, 2026
7676076
add clue dto and change parameter of game state dto from clue to clue…
the-only-queen-anna May 18, 2026
63a2dcb
test: fix and add tests
the-only-queen-anna May 18, 2026
7c06d0e
refactor: remove unused imports, clear warnings
the-only-queen-anna May 18, 2026
93d6cec
refactor: remove unnecessary empty string check
the-only-queen-anna May 18, 2026
6470db2
refactor: remove unused import
the-only-queen-anna May 18, 2026
559fad8
Merge pull request #108 from SS26-SE2-Codenames/clue-system-fix
the-only-queen-anna May 18, 2026
aa5e990
test: add json state store exception path coverage
tasaje1 May 18, 2026
ef7145a
refactor: extract snapshot load helper in json state store test
tasaje1 May 18, 2026
cb9d408
test: improve JsonStateStore coverage for getters and parentless save…
tasaje1 May 18, 2026
cc55c71
test: replace self-assertion on ioLock getter with non-null assertion
tasaje1 May 18, 2026
bfd2daf
Merge remote-tracking branch 'origin/development' into feature/game-s…
tasaje1 May 18, 2026
36fa601
feat: add startup state recovery service
tasaje1 May 18, 2026
7dc1752
feat: add lobby and game restore hooks
tasaje1 May 18, 2026
87708a4
feat: add GameManager and Board constructors for snapshot restore
tasaje1 May 18, 2026
7a170d9
refactor: use CardDataTransferObject in game snapshots for recovery
tasaje1 May 18, 2026
078d507
test: add startup recovery tests for SystemStateRecoveryService
tasaje1 May 18, 2026
9b99653
test: maximize SystemStateRecoveryService branch coverage
tasaje1 May 18, 2026
9d654bd
test: add tests for recovery
tasaje1 May 18, 2026
7393f5e
style: reorder imports in LobbyServiceTest
tasaje1 May 18, 2026
885cf5e
test: configure Mockito mock maker for local test stability
tasaje1 May 18, 2026
a0a41de
docs: add javadocs
tasaje1 May 18, 2026
cad7578
test: replace final DTO mocks with concrete instances in controller t…
tasaje1 May 19, 2026
2dc0d40
style: fix import order
tasaje1 May 19, 2026
080726d
refactor: delete unused clue snapshot record
tasaje1 May 19, 2026
a04a04a
refactor: delete unused lobby snapshot record
tasaje1 May 19, 2026
bd5cf0c
refactor: use ClueDto in game snapshot
tasaje1 May 19, 2026
b9d9f25
refactor: use player dto list in system snapshot
tasaje1 May 19, 2026
be85731
refactor: adapt game manager factory to dto based clue recovery
tasaje1 May 19, 2026
746ceec
refactor: adapt lobby recovery to dto based snapshot structure
tasaje1 May 19, 2026
04e823b
test: update game manager factory recovery tests
tasaje1 May 19, 2026
5d05310
test: update json state store tests for dto snapshots
tasaje1 May 19, 2026
510688e
test: update system state recovery tests for dto snapshots
tasaje1 May 19, 2026
7b8d762
test: simplify assertThrows lambdas in recovery constructor tests
tasaje1 May 19, 2026
9278789
refactor: add remaining guesses to game state transfer object
tasaje1 May 19, 2026
f7f4d0c
refactor: map remaining guesses in dto service
tasaje1 May 19, 2026
1240f53
refactor: remove legacy game state dto creation from game service
tasaje1 May 19, 2026
23e1358
refactor: use unified game state payload in game controller
tasaje1 May 19, 2026
79b01a8
refactor: remove unused game state dto record
tasaje1 May 19, 2026
6abec76
test: update game service tests for unified payload
tasaje1 May 19, 2026
82481fc
test: update game controller tests for unified payload
tasaje1 May 19, 2026
414b189
test: update game socket controller test payload constructor
tasaje1 May 19, 2026
27e903c
test: update serialization dto service tests for remaining guesses
tasaje1 May 19, 2026
ccfb59c
test: update serialization dto service tests for remaining guesses
tasaje1 May 19, 2026
c9af76c
refactor: unify game recovery state dto
tasaje1 May 19, 2026
6c242f7
test: update recovery tests for unified game state dto
tasaje1 May 19, 2026
4b8387d
refactor: remove redundant game recovery state
tasaje1 May 19, 2026
5c74a0c
refactor: remove GameRecoveryState and use game state dto directly
tasaje1 May 19, 2026
b516914
test: update recovery tests for direct game state dto
tasaje1 May 19, 2026
ada50ff
feat: add snapshot retrieval for lobby and game state
tasaje1 May 19, 2026
7301272
feat: add system state persistence service
tasaje1 May 19, 2026
7c9bbc1
test: add persistence service and snapshot tests
tasaje1 May 19, 2026
2848ef1
docs: add javadocs for system state persistence service
tasaje1 May 19, 2026
8d4bf23
refactor: persist system state after lobby and gameplay actions
tasaje1 May 19, 2026
5c23caf
test: update controller tests for state persistence calls
tasaje1 May 19, 2026
d689b01
style: fix imports
tasaje1 May 19, 2026
a31b94e
refactor: remove redundant response variable and verify persistence s…
tasaje1 May 19, 2026
e2b0e46
style: fix checkstyle issues
tasaje1 May 20, 2026
6d87ef9
removed verification with session registry from chat + adapted tests
the-only-queen-anna May 20, 2026
f709d98
refactor: removed unused import & cleared checkstyle warnings
the-only-queen-anna May 20, 2026
e4ea92e
chore: persist backend state with docker volume
tasaje1 May 20, 2026
24fabaa
refactor: reduce pre-game lobby persistence
tasaje1 May 20, 2026
e05976e
test: align lobby and game controller persistence expectations
tasaje1 May 20, 2026
e2898e4
refactor: remove unused persistence dependency from game controller
tasaje1 May 20, 2026
34d8e9b
doc: changed format of link comments
the-only-queen-anna May 20, 2026
06a51e1
Merge pull request #110 from SS26-SE2-Codenames/chat-endpoint-fix
the-only-queen-anna May 20, 2026
87318a6
Merge branch 'development' into feature/game-state-recovery-restart
tasaje1 May 20, 2026
38c490d
test: fix imports
tasaje1 May 20, 2026
67c801a
Merge pull request #109 from SS26-SE2-Codenames/feature/game-state-re…
tasaje1 May 20, 2026
81a27d3
refactor: remove wrongly added parameter from game state dto
the-only-queen-anna May 20, 2026
c40c04e
test: remove assertions from tests that were testing the removed para…
the-only-queen-anna May 20, 2026
b20de7e
changes to gitignore: excludes data/state.json
the-only-queen-anna May 20, 2026
5a6d05c
fix: add assertions to test w/o assertions
the-only-queen-anna May 20, 2026
9ed104a
Merge pull request #121 from SS26-SE2-Codenames/development-fix
the-only-queen-anna May 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ build/

### VS Code ###
.vscode/

### State Persistence ###
data/
4 changes: 3 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ services:
image: ghcr.io/ss26-se2-codenames/backend:latest
restart: unless-stopped
ports:
- "53213:8080"
- "53213:8080"
volumes:
- ./data:/app/data
Original file line number Diff line number Diff line change
@@ -1,67 +1,35 @@
package com.codenames.codenames.backend.chat;

import com.codenames.codenames.backend.lobby.services.LobbyService;
import com.codenames.codenames.backend.utility.ChatMessageType;
import com.codenames.codenames.backend.utility.Role;
import com.codenames.codenames.backend.utility.Team;
import com.codenames.codenames.backend.websocket.SessionRegistry;
import org.springframework.messaging.handler.annotation.DestinationVariable;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.stereotype.Controller;

/**
* Controller for broadcasting client messages to the desired destination with STOMP.
*
* <p>The destination is based on the lobbyID or team parameters passed when the method is invoked.
* The parameters are appended to the destination and broadcasted to all subscribers.
*/

@Controller
public class ChatController {

private final ChatService chatService;
private final LobbyService lobbyService;
private final SessionRegistry sessionRegistry;

/**
* Constructor for the ChatController.
*
* @param chatService the service used to validate and persist chat history
*/
public ChatController(
ChatService chatService, LobbyService lobbyService, SessionRegistry sessionRegistry) {
ChatService chatService, LobbyService lobbyService) {
this.chatService = chatService;
this.lobbyService = lobbyService;
this.sessionRegistry = sessionRegistry;
}

/**
* Verifies the username of the sender and checks if they are sending the message to their own
* lobby before allowing them to send a message.
*
* @param headerAccessor the header accessor containing the session information of the sender
* @param targetLobbyId the actual lobby ID associated with the sender's session, used to verify
* that they are sending the message to their own lobby
* @return the username if sender is verified, otherwise throws an exception
* @throws IllegalStateException if the username is null or if the sender is trying to send a
* message to a lobby they are not in
*/
private String getVerifiedUsername(
SimpMessageHeaderAccessor headerAccessor, String targetLobbyId) {
String sessionId = headerAccessor.getSessionId();
String realUsername = sessionRegistry.getUser(sessionId);
String realLobbyId = sessionRegistry.getLobby(sessionId);

if (realUsername == null) {
throw new IllegalStateException("Null username.");
}
if (targetLobbyId == null) {
throw new IllegalStateException("Null lobby ID.");
}
if (!targetLobbyId.equals(realLobbyId)) {
throw new IllegalStateException("Wrong lobby, user not in lobby " + realLobbyId);
}
return realUsername;
}

/**
Expand All @@ -72,18 +40,19 @@ private String getVerifiedUsername(
*/
@MessageMapping("/chat/{lobbyId}")
public void sendLobbyMessage(
@DestinationVariable String lobbyId,
@Payload ChatDto chatDto,
SimpMessageHeaderAccessor headerAccessor) {
String realUsername = getVerifiedUsername(headerAccessor, lobbyId);

// Create a new ChatDto with the verified username to prevent passing false username
ChatDto verifiedChatDto = new ChatDto(realUsername, chatDto.content(), chatDto.type());
@DestinationVariable String lobbyId,
@Payload ChatDto chatDto) {

ChatDto verifiedChatDto = new ChatDto(
chatDto.senderUsername(),
chatDto.content(),
ChatMessageType.CHAT
);
chatService.processMessage(lobbyId, "LOBBY", "", verifiedChatDto);
}

/**
* Verifies the sender's name, lobbyID, and team before sending a message to the entire team.
* Verifies the sender's team and delegates message processing to {@link ChatService}.
*
* @param lobbyId the ID of the lobby the client is in
* @param team the team the client is in (RED, BLUE)
Expand All @@ -93,25 +62,26 @@ public void sendLobbyMessage(
public void sendTeamMessage(
@DestinationVariable String lobbyId,
@DestinationVariable Team team,
@Payload ChatDto chatDto,
SimpMessageHeaderAccessor headerAccessor) {
String realUsername = getVerifiedUsername(headerAccessor, lobbyId);
@Payload ChatDto chatDto) {

Team playerTeam = lobbyService.getPlayerTeam(realUsername, lobbyId);
Team playerTeam = lobbyService.getPlayerTeam(chatDto.senderUsername(), lobbyId);
if (playerTeam != team) {
throw new IllegalStateException("You are not on team " + team.name());
}

ChatDto verifiedDto = new ChatDto(realUsername, chatDto.content(), chatDto.type());
ChatDto verifiedDto = new ChatDto(
chatDto.senderUsername(),
chatDto.content(),
ChatMessageType.CHAT
);

String roomKey = "TEAM_" + team.name();
String topicSuffix = "/" + team.name();
chatService.processMessage(lobbyId, roomKey, topicSuffix, verifiedDto);
}

/**
* Verifies the sender's name, lobbyID, team and role sending a message to the operatives on the
* respective team.
* Verifies the sender's team and role and delegates message processing to {@link ChatService}.
*
* @param lobbyId the ID of the lobby the client is in
* @param team the team the client is in (RED, BLUE)
Expand All @@ -121,19 +91,21 @@ public void sendTeamMessage(
public void sendTeamOperativeMessage(
@DestinationVariable String lobbyId,
@DestinationVariable Team team,
@Payload ChatDto chatDto,
SimpMessageHeaderAccessor headerAccessor) {
String realUsername = getVerifiedUsername(headerAccessor, lobbyId);
@Payload ChatDto chatDto) {

Team playerTeam = lobbyService.getPlayerTeam(realUsername, lobbyId);
Role playerRole = lobbyService.getPlayerRole(realUsername, lobbyId);
Team playerTeam = lobbyService.getPlayerTeam(chatDto.senderUsername(), lobbyId);
Role playerRole = lobbyService.getPlayerRole(chatDto.senderUsername(), lobbyId);

if (playerTeam != team || playerRole != Role.OPERATIVE) {
throw new IllegalStateException(
"You are either not an operative or are sending to the wrong team.");
}

ChatDto verifiedDto = new ChatDto(realUsername, chatDto.content(), chatDto.type());
ChatDto verifiedDto = new ChatDto(
chatDto.senderUsername(),
chatDto.content(),
ChatMessageType.CHAT
);

String roomKey = "OPERATIVE_" + team.name();
String topicSuffix = "/" + team.name() + "/operative";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.codenames.codenames.backend.controller;

import java.util.Map;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* Controller providing a simple health check endpoint to verify that the backend application is
* running.
*/
@RestController
public class HealthController {

/**
* Returns the current health status of the backend.
*
* @return a map containing the application status
*/
@GetMapping("/health")
public Map<String, String> health() {
return Map.of("status", "UP");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package com.codenames.codenames.backend.game.controller;

import com.codenames.codenames.backend.clue.Clue;
import com.codenames.codenames.backend.game.dto.ClueMessage;
import com.codenames.codenames.backend.game.dto.PassTurnMessage;
import com.codenames.codenames.backend.game.dto.RevealCardMessage;
import com.codenames.codenames.backend.game.dto.StartGameMessage;
import com.codenames.codenames.backend.playingfield.GameService;
import com.codenames.codenames.backend.recovery.SystemStatePersistenceService;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;

/**
* WebSocket controller for real-time gameplay interactions.
*
* <p>Handles game-related WebSocket requests such as starting games, submitting clues, and
* revealing cards. Broadcasts updated game state information to subscribed clients.
*/
@Controller
public class GameSocketController {

private final GameService gameService;

private final SimpMessagingTemplate messagingTemplate;
private final SystemStatePersistenceService persistenceService;

private static final String GAME_TOPIC_PREFIX = "/topic/game/";

/**
* Creates a new {@code GameSocketController}.
*
* @param gameService service responsible for gameplay logic
* @param messagingTemplate template used for broadcasting websocket messages
* @param persistenceService service used to persist current backend state
*/
public GameSocketController(
GameService gameService,
SimpMessagingTemplate messagingTemplate,
SystemStatePersistenceService persistenceService) {

this.gameService = gameService;
this.messagingTemplate = messagingTemplate;
this.persistenceService = persistenceService;
}

/**
* Sends the current game state to subscribed players.
*
* @param message contains the lobby code
*/
@MessageMapping("/start-game")
public void startGame(StartGameMessage message) {

messagingTemplate.convertAndSend(
GAME_TOPIC_PREFIX + message.getLobbyCode(),
gameService.getCurrentGameState(message.getLobbyCode()));
}

/**
* Reveals a card on the board.
*
* <p>Updates the game state and broadcasts the updated board to all subscribed players.
*
* @param message the reveal card request
*/
@MessageMapping("/reveal-card")
public void revealCard(RevealCardMessage message) {

gameService.flipCard(message.getLobbyCode(), message.getPosition(), message.getCurrentTurn());
persistenceService.persistCurrentState();

messagingTemplate.convertAndSend(
GAME_TOPIC_PREFIX + message.getLobbyCode(),
gameService.getCurrentGameState(message.getLobbyCode()));
}

/**
* Submits a clue for the current turn.
*
* <p>Updates the current clue and broadcasts the updated game state to all subscribed players.
*
* @param message the clue submission request
*/
@MessageMapping("/submit-clue")
public void submitClue(ClueMessage message) {

gameService.submitClue(
message.getLobbyCode(),
new Clue(message.getWord(), message.getGuessAmount()),
message.getCurrentTurn());
persistenceService.persistCurrentState();

messagingTemplate.convertAndSend(
GAME_TOPIC_PREFIX + message.getLobbyCode(),
gameService.getCurrentGameState(message.getLobbyCode()));
}

/**
* Ends the current turn early and broadcasts the updated game state.
*
* @param message contains lobby and team information
*/
@MessageMapping("/pass-turn")
public void passTurn(PassTurnMessage message) {

gameService.passTurn(message.getLobbyCode(), message.getCurrentTurn());
persistenceService.persistCurrentState();

messagingTemplate.convertAndSend(
GAME_TOPIC_PREFIX + message.getLobbyCode(),
gameService.getCurrentGameState(message.getLobbyCode()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.codenames.codenames.backend.game.dto;

/**
* Data transfer object for a clue, containing the clue word and the allowed number of guesses.
* This is only used for sending clues, not for receiving them.
* Therefore, the +1 is already included in the guessAmount.
*
* @param word the hint word
* @param guessAmount how many guesses are allowed
*/
public record ClueDto(String word, int guessAmount) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.codenames.codenames.backend.game.dto;

import com.codenames.codenames.backend.utility.Team;
import lombok.Getter;
import lombok.Setter;

/**
* WebSocket message for submitting a clue.
*
* <p>Contains the clue word and the allowed amount of guesses.
*/
@Getter
@Setter
public class ClueMessage {
private String lobbyCode;
private String word;
private int guessAmount;
private Team currentTurn;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.codenames.codenames.backend.game.dto;

import com.codenames.codenames.backend.utility.Team;
import lombok.Getter;
import lombok.Setter;

/**
* Message used for requesting an early turn pass.
*
* <p>Contains the lobby code and team initiating the action.
*/
@Getter
@Setter
public class PassTurnMessage {
private String lobbyCode;
private Team currentTurn;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.codenames.codenames.backend.game.dto;

import com.codenames.codenames.backend.utility.Team;
import lombok.Getter;
import lombok.Setter;

/**
* WebSocket message for revealing a card on the board.
*
* <p>Contains the lobby code, selected card position, and the current team's turn color.
*/
@Getter
@Setter
public class RevealCardMessage {
private String lobbyCode;
private int position;
private Team currentTurn;
}
Loading
Loading