Skip to content

Commit c2bb9b9

Browse files
Fix PR #47 blocking issues for Game Lobby UI (BGE-145)
- Convert GameLobbyViewModels to record types (Architect blocking #1) - Add GameDefType and EndTime fields to GameSummaryViewModel and GameInfo (Architect required #5) - Fix AddPlayer() race condition: move PlayerCount update inside lock, return bool for duplicate-join detection (Architect blocking #2 and #3 / QA blocking #2) - Fix duplicate-join: return Conflict(409) if player already joined (Architect blocking #2) - Add [AllowAnonymous] to GetAll() — game list is a public endpoint per BGE-131 plan (Architect required #4) - Update controller to use record constructor syntax and handle AddPlayer bool return Build: 0 errors | Tests: 117/117 passed Co-Authored-By: Paperclip <noreply@paperclip.ing>
1 parent 36b34a5 commit c2bb9b9

File tree

4 files changed

+45
-35
lines changed

4 files changed

+45
-35
lines changed

src/BrowserGameEngine.FrontendServer/Controllers/GamesController.cs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using BrowserGameEngine.StatefulGameServer;
44
using Microsoft.AspNetCore.Authorization;
55
using Microsoft.AspNetCore.Mvc;
6-
using System;
76
using System.Linq;
87

98
namespace BrowserGameEngine.FrontendServer.Controllers {
@@ -23,17 +22,20 @@ GameRepository gameRepository
2322
}
2423

2524
[HttpGet]
25+
[AllowAnonymous]
2626
public ActionResult<GameListViewModel> GetAll() {
27-
var games = gameRepository.GetAll().Select(g => new GameSummaryViewModel {
28-
GameId = g.GameId,
29-
Name = g.Name,
30-
Status = g.Status.ToString().ToLowerInvariant(),
31-
PlayerCount = g.PlayerCount,
32-
MaxPlayers = g.MaxPlayers,
33-
StartTime = g.StartTime,
34-
CanJoin = g.Status == GameStatus.Upcoming
35-
}).ToList();
36-
return Ok(new GameListViewModel { Games = games });
27+
var games = gameRepository.GetAll().Select(g => new GameSummaryViewModel(
28+
g.GameId,
29+
g.Name,
30+
g.GameDefType,
31+
g.Status.ToString().ToLowerInvariant(),
32+
g.PlayerCount,
33+
g.MaxPlayers,
34+
g.StartTime,
35+
g.EndTime,
36+
g.Status == GameStatus.Upcoming
37+
)).ToList();
38+
return Ok(new GameListViewModel(games));
3739
}
3840

3941
[HttpPost("{gameId}/join")]
@@ -42,7 +44,9 @@ public ActionResult Join(string gameId) {
4244
var game = gameRepository.Get(gameId);
4345
if (game == null) return NotFound();
4446
if (game.Status != GameStatus.Upcoming) return BadRequest("This game is not open for joining.");
45-
gameRepository.AddPlayer(gameId, currentUserContext.PlayerId!.Id);
47+
if (!gameRepository.AddPlayer(gameId, currentUserContext.PlayerId!.Id)) {
48+
return Conflict("You have already joined this game.");
49+
}
4650
return Ok();
4751
}
4852
}

src/BrowserGameEngine.Shared/GameLobbyViewModels.cs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,19 @@
22
using System.Collections.Generic;
33

44
namespace BrowserGameEngine.Shared {
5-
public class GameListViewModel {
6-
public List<GameSummaryViewModel> Games { get; set; } = new();
7-
}
5+
public record GameSummaryViewModel(
6+
string GameId,
7+
string Name,
8+
string GameDefType,
9+
string Status,
10+
int PlayerCount,
11+
int MaxPlayers,
12+
DateTime? StartTime,
13+
DateTime? EndTime,
14+
bool CanJoin
15+
);
816

9-
public class GameSummaryViewModel {
10-
public string GameId { get; set; } = "";
11-
public string Name { get; set; } = "";
12-
public string Status { get; set; } = "";
13-
public int PlayerCount { get; set; }
14-
public int MaxPlayers { get; set; }
15-
public DateTime? StartTime { get; set; }
16-
public bool CanJoin { get; set; }
17-
}
17+
public record GameListViewModel(List<GameSummaryViewModel> Games);
1818

19-
public class JoinGameRequest {
20-
public string GameId { get; set; } = "";
21-
}
19+
public record JoinGameRequest(string GameId);
2220
}

src/BrowserGameEngine.StatefulGameServer/Repositories/Game/GameInfo.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ public enum GameStatus {
1010
public class GameInfo {
1111
public string GameId { get; set; } = "";
1212
public string Name { get; set; } = "";
13+
public string GameDefType { get; set; } = "sco";
1314
public GameStatus Status { get; set; }
1415
public int PlayerCount { get; set; }
1516
public int MaxPlayers { get; set; }
1617
public DateTime? StartTime { get; set; }
18+
public DateTime? EndTime { get; set; }
1719
}
1820
}

src/BrowserGameEngine.StatefulGameServer/Repositories/Game/GameRepository.cs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,17 @@ public bool IsPlayerInGame(string gameId, string playerId) {
2727
return playersByGame.TryGetValue(gameId, out var players) && players.Contains(playerId);
2828
}
2929

30-
public void AddPlayer(string gameId, string playerId) {
30+
public bool AddPlayer(string gameId, string playerId) {
3131
var players = playersByGame.GetOrAdd(gameId, _ => new HashSet<string>());
3232
lock (players) {
33-
players.Add(playerId);
34-
}
35-
if (games.TryGetValue(gameId, out var game)) {
36-
game.PlayerCount = playersByGame.TryGetValue(gameId, out var p) ? p.Count : 0;
33+
if (!players.Add(playerId)) {
34+
return false;
35+
}
36+
if (games.TryGetValue(gameId, out var game)) {
37+
game.PlayerCount = players.Count;
38+
}
3739
}
40+
return true;
3841
}
3942

4043
private void SeedDefaultGames() {
@@ -45,23 +48,26 @@ private void SeedDefaultGames() {
4548
Status = GameStatus.Upcoming,
4649
PlayerCount = 0,
4750
MaxPlayers = 50,
48-
StartTime = now.AddDays(2)
51+
StartTime = now.AddDays(2),
52+
EndTime = now.AddDays(16)
4953
};
5054
var active1 = new GameInfo {
5155
GameId = "game-beta",
5256
Name = "Beta Season",
5357
Status = GameStatus.Active,
5458
PlayerCount = 12,
5559
MaxPlayers = 50,
56-
StartTime = now.AddDays(-5)
60+
StartTime = now.AddDays(-5),
61+
EndTime = now.AddDays(9)
5762
};
5863
var finished1 = new GameInfo {
5964
GameId = "game-s1",
6065
Name = "Season 1",
6166
Status = GameStatus.Finished,
6267
PlayerCount = 38,
6368
MaxPlayers = 50,
64-
StartTime = now.AddDays(-30)
69+
StartTime = now.AddDays(-30),
70+
EndTime = now.AddDays(-16)
6571
};
6672
games[upcoming1.GameId] = upcoming1;
6773
games[active1.GameId] = active1;

0 commit comments

Comments
 (0)