Add column drop, game info DTO, and disconnect
Introduce column-based drop mechanics and game info transfer; add disconnect handling and related API/interface updates. GameField API renamed Place->Drop and PlaceResult->DropResult, added ColumnFull, IsFull, and updated drop logic to insert at lowest empty row. Game model now exposes Players, adds GetPlayerByTag and makes StartGame public. New GameInformationDto conveys game state and field. Hub methods updated: GameCreated->GameJoined, RequestGameInformation, Place now forwards to Drop, and OnDisconnectedAsync notifies GameManager. GameManager implements RequestGameInformation, Drop (validates moves, broadcasts FieldUpdated and GameEnded on win/draw), improved JoinGame logic to auto-start when two players join, and handles player disconnects. Repository and interface extended with GetOneByConnectionId. Also tightened SignalR timeouts in Program.
This commit is contained in:
@@ -19,16 +19,93 @@ public class GameManager(IGameRepository gameRepository, IHubContext<GameHubSock
|
||||
{
|
||||
var game = gameRepository.GetOne(new SixDigitInt(gameCode));
|
||||
|
||||
var success = game != null && game.AddPlayer(player);
|
||||
var success = game != null && game.State == GameState.Lobby && game.AddPlayer(player);
|
||||
|
||||
if (game!.State == GameState.Running)
|
||||
await hubContext.Clients.Group(game.Id).SendAsync("GameStarted");
|
||||
if (!success) return null;
|
||||
|
||||
if (game.Players.Count == 2)
|
||||
{
|
||||
game.StartGame();
|
||||
|
||||
await hubContext.Clients.Group(game.Id).SendAsync("GameStarted", game.Players);
|
||||
}
|
||||
|
||||
return game.Id;
|
||||
}
|
||||
|
||||
public async Task<bool> Place(string gameCode, int coordinates, string playerConnectionId)
|
||||
public async Task RequestGameInformation(string gameId, string playerConnectionId)
|
||||
{
|
||||
return true;
|
||||
var game = gameRepository.GetOne(gameId);
|
||||
if (game == null)
|
||||
return;
|
||||
|
||||
var gameInfoDto = new GameInformationDto
|
||||
{
|
||||
Players = game?.Players,
|
||||
CurrentField = game?.Field.CurrentField,
|
||||
State = game?.State
|
||||
};
|
||||
|
||||
await hubContext.Clients.Client(playerConnectionId).SendAsync("GameInformation", gameInfoDto);
|
||||
}
|
||||
|
||||
public async Task Drop(string gameCode, int column, string playerConnectionId)
|
||||
{
|
||||
var game = gameRepository.GetOne(gameCode);
|
||||
|
||||
var player = game?.GetPlayerByConnectionId(playerConnectionId);
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
var result = game.Field.Drop(column, player.PlayerTag);
|
||||
|
||||
if (result != DropResult.Placed)
|
||||
{
|
||||
await hubContext.Clients.Client(playerConnectionId).SendAsync("Error", "Ungültiger Zug.");
|
||||
return;
|
||||
}
|
||||
|
||||
await hubContext.Clients.Group(game.Id).SendAsync("FieldUpdated", game.Field.CurrentField);
|
||||
|
||||
var winResult = game.Field.CheckForWin();
|
||||
if (winResult != 0)
|
||||
{
|
||||
var winPlayer = game.GetPlayerByTag(winResult);
|
||||
game.EndGame();
|
||||
await hubContext.Clients.Group(game.Id).SendAsync("GameEnded", new
|
||||
{
|
||||
Method = "Win",
|
||||
Player = winPlayer
|
||||
});
|
||||
}
|
||||
|
||||
if (game.Field.IsFull())
|
||||
{
|
||||
game.EndGame();
|
||||
|
||||
await hubContext.Clients.Group(game.Id).SendAsync("GameEnded", new
|
||||
{
|
||||
Method = "Draw"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public Task DisconnectedPlayer(string playerConnectionId)
|
||||
{
|
||||
var game = gameRepository.GetOneByConnectionId(playerConnectionId);
|
||||
if (game == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var player = game.GetPlayerByConnectionId(playerConnectionId);
|
||||
if (player == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
game.RemovePlayer(playerConnectionId);
|
||||
game.EndGame();
|
||||
return hubContext.Clients.Group(game.Id).SendAsync("GameEnded", new
|
||||
{
|
||||
Method = "PlayerDisconnected",
|
||||
Player = player
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,9 @@ namespace API.Services.GameManager;
|
||||
public interface IGameManager
|
||||
{
|
||||
public (string, int) CreateGame(Coordinates gFs, Player player);
|
||||
public Task<string?> JoinGame(Player player, int gameCode)
|
||||
public Task<bool> Place(string gameCode, int coordinates, string playerConnectionId)
|
||||
public Task<string?> JoinGame(Player player, int gameCode);
|
||||
public Task RequestGameInformation(string gameId, string playerConnectionId);
|
||||
public Task Drop(string gameCode, int coordinates, string playerConnectionId);
|
||||
|
||||
public Task DisconnectedPlayer(string playerConnectionId);
|
||||
}
|
||||
Reference in New Issue
Block a user