Fixed bugs when disconnecting and reconnecting, disconnect message is sent before closing websocket connection
This commit is contained in:
parent
554b8cff2a
commit
cb9371b33b
pac-man-board-game
ClientApp/src/components
Controllers
GameStuff/Items
Services
@ -16,8 +16,6 @@ const wsService = new WebSocketService(import.meta.env.VITE_API_WS);
|
|||||||
|
|
||||||
// TODO bug, when taking player on last dice, the currentPlayer changes and the wrong character gets to steal
|
// TODO bug, when taking player on last dice, the currentPlayer changes and the wrong character gets to steal
|
||||||
// TODO bug, first player can sometimes roll dice twice
|
// TODO bug, first player can sometimes roll dice twice
|
||||||
// TODO bug, when refreshing page, the player is still in disconnected state
|
|
||||||
// TODO bug, when refreshing page, the characters are reset for all players
|
|
||||||
// TODO bug, when refreshing page, some data is missing until other clients make a move
|
// TODO bug, when refreshing page, some data is missing until other clients make a move
|
||||||
// TODO bug, teleportation doesn't work
|
// TODO bug, teleportation doesn't work
|
||||||
|
|
||||||
|
@ -15,10 +15,10 @@ public class GameController : GenericController
|
|||||||
private readonly IActionService _actionService;
|
private readonly IActionService _actionService;
|
||||||
private readonly GameService _gameService;
|
private readonly GameService _gameService;
|
||||||
|
|
||||||
public GameController(ILogger<GameController> logger, GameService gameService, IActionService actionService) :
|
public GameController(ILogger<GameController> logger, GameService webSocketService, IActionService actionService) :
|
||||||
base(logger, gameService)
|
base(logger, webSocketService)
|
||||||
{
|
{
|
||||||
_gameService = gameService;
|
_gameService = webSocketService;
|
||||||
_actionService = actionService;
|
_actionService = actionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,5 +85,9 @@ public class GameController : GenericController
|
|||||||
|
|
||||||
protected override void Send(ArraySegment<byte> segment) => _actionService.SendToAll(segment);
|
protected override void Send(ArraySegment<byte> segment) => _actionService.SendToAll(segment);
|
||||||
|
|
||||||
protected override void Disconnect() => _actionService.Disconnect();
|
protected override ArraySegment<byte>? Disconnect() =>
|
||||||
|
new ActionMessage { Action = GameAction.Disconnect, Data = _actionService.Disconnect() }
|
||||||
|
.ToArraySegment();
|
||||||
|
|
||||||
|
protected override void SendDisconnectMessage(ArraySegment<byte> segment) => _actionService.SendToAll(segment);
|
||||||
}
|
}
|
||||||
|
@ -7,14 +7,14 @@ namespace pacMan.Controllers;
|
|||||||
public abstract class GenericController : ControllerBase
|
public abstract class GenericController : ControllerBase
|
||||||
{
|
{
|
||||||
private const int BufferSize = 1024 * 4;
|
private const int BufferSize = 1024 * 4;
|
||||||
protected readonly IWebSocketService GameService;
|
private readonly IWebSocketService _webSocketService;
|
||||||
protected readonly ILogger<GenericController> Logger;
|
protected readonly ILogger<GenericController> Logger;
|
||||||
protected WebSocket? WebSocket;
|
protected WebSocket? WebSocket;
|
||||||
|
|
||||||
protected GenericController(ILogger<GenericController> logger, IWebSocketService gameService)
|
protected GenericController(ILogger<GenericController> logger, IWebSocketService webSocketService)
|
||||||
{
|
{
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
GameService = gameService;
|
_webSocketService = webSocketService;
|
||||||
Logger.Log(LogLevel.Debug, "WebSocket Controller created");
|
Logger.Log(LogLevel.Debug, "WebSocket Controller created");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ public abstract class GenericController : ControllerBase
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
var buffer = new byte[BufferSize];
|
var buffer = new byte[BufferSize];
|
||||||
result = await GameService.Receive(WebSocket, buffer);
|
result = await _webSocketService.Receive(WebSocket, buffer);
|
||||||
|
|
||||||
if (result.CloseStatus.HasValue) break;
|
if (result.CloseStatus.HasValue) break;
|
||||||
|
|
||||||
@ -51,23 +51,26 @@ public abstract class GenericController : ControllerBase
|
|||||||
Send(segment);
|
Send(segment);
|
||||||
} while (true);
|
} while (true);
|
||||||
|
|
||||||
await GameService.Close(WebSocket, result.CloseStatus.Value, result.CloseStatusDescription);
|
var disconnectSegment = Disconnect();
|
||||||
|
if (disconnectSegment != null) SendDisconnectMessage((ArraySegment<byte>)disconnectSegment);
|
||||||
|
|
||||||
|
await _webSocketService.Close(WebSocket, result.CloseStatus.Value, result.CloseStatusDescription);
|
||||||
}
|
}
|
||||||
catch (WebSocketException e)
|
catch (WebSocketException e)
|
||||||
{
|
{
|
||||||
Logger.Log(LogLevel.Error, "{}", e.Message);
|
Logger.Log(LogLevel.Error, "{}", e.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
Disconnect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual async void Send(ArraySegment<byte> segment)
|
protected virtual async void Send(ArraySegment<byte> segment)
|
||||||
{
|
{
|
||||||
if (WebSocket == null) return;
|
if (WebSocket == null) return;
|
||||||
await GameService.Send(WebSocket, segment);
|
await _webSocketService.Send(WebSocket, segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract ArraySegment<byte> Run(WebSocketReceiveResult result, byte[] data);
|
protected abstract ArraySegment<byte> Run(WebSocketReceiveResult result, byte[] data);
|
||||||
|
|
||||||
protected virtual void Disconnect() { }
|
protected virtual ArraySegment<byte>? Disconnect() => null;
|
||||||
|
|
||||||
|
protected virtual void SendDisconnectMessage(ArraySegment<byte> segment) { }
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,11 @@ public class Player : IEquatable<Player>
|
|||||||
{
|
{
|
||||||
[JsonPropertyName("username")] public required string Username { get; init; }
|
[JsonPropertyName("username")] public required string Username { get; init; }
|
||||||
|
|
||||||
[JsonPropertyName("pacMan")] public required Character PacMan { get; init; }
|
[JsonPropertyName("pacMan")] public required Character PacMan { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("colour")] public required string Colour { get; init; }
|
[JsonPropertyName("colour")] public required string Colour { get; init; }
|
||||||
|
|
||||||
[JsonPropertyName("box")] public Box? Box { get; init; }
|
[JsonPropertyName("box")] public Box? Box { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("state")] public State State { get; set; } = State.WaitingForPlayers;
|
[JsonPropertyName("state")] public State State { get; set; } = State.WaitingForPlayers;
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ public interface IActionService
|
|||||||
string FindNextPlayer();
|
string FindNextPlayer();
|
||||||
List<Player> LeaveGame();
|
List<Player> LeaveGame();
|
||||||
void SendToAll(ArraySegment<byte> segment);
|
void SendToAll(ArraySegment<byte> segment);
|
||||||
void Disconnect();
|
List<Player>? Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ActionService : IActionService
|
public class ActionService : IActionService
|
||||||
@ -65,8 +65,12 @@ public class ActionService : IActionService
|
|||||||
public object? HandleMoveCharacter(JsonElement? jsonElement)
|
public object? HandleMoveCharacter(JsonElement? jsonElement)
|
||||||
{
|
{
|
||||||
if (Game != null && jsonElement.HasValue)
|
if (Game != null && jsonElement.HasValue)
|
||||||
|
{
|
||||||
Game.Ghosts = jsonElement.Value.GetProperty("ghosts").Deserialize<List<Character>>() ??
|
Game.Ghosts = jsonElement.Value.GetProperty("ghosts").Deserialize<List<Character>>() ??
|
||||||
throw new JsonException("Ghosts is null");
|
throw new JsonException("Ghosts is null");
|
||||||
|
Game.Players = jsonElement.Value.GetProperty("players").Deserialize<List<Player>>() ??
|
||||||
|
throw new NullReferenceException("Players is null");
|
||||||
|
}
|
||||||
|
|
||||||
return jsonElement;
|
return jsonElement;
|
||||||
}
|
}
|
||||||
@ -77,10 +81,11 @@ public class ActionService : IActionService
|
|||||||
Player = data.Player;
|
Player = data.Player;
|
||||||
|
|
||||||
Game? game;
|
Game? game;
|
||||||
Player? player;
|
if ((game = _gameService.FindGameByUsername(Player.Username)) != null)
|
||||||
if ((game = _gameService.FindGameByUsername(Player.Username)) != null &&
|
|
||||||
(player = game.Players.Find(p => p.Username == Player.Username))?.State == State.Disconnected)
|
|
||||||
{
|
{
|
||||||
|
var player = game.Players.Find(p => p.Username == Player.Username);
|
||||||
|
if (player is null) throw new NullReferenceException("Player is null");
|
||||||
|
|
||||||
player.State = game.IsGameStarted ? State.InGame : State.WaitingForPlayers; // TODO doesn't work anymore
|
player.State = game.IsGameStarted ? State.InGame : State.WaitingForPlayers; // TODO doesn't work anymore
|
||||||
Player = player;
|
Player = player;
|
||||||
Game = game;
|
Game = game;
|
||||||
@ -125,11 +130,12 @@ public class ActionService : IActionService
|
|||||||
return Game.Players;
|
return Game.Players;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Disconnect()
|
public List<Player>? Disconnect()
|
||||||
{
|
{
|
||||||
if (Player == null) return;
|
if (Player == null) return null;
|
||||||
Player.State = State.Disconnected;
|
Player.State = State.Disconnected;
|
||||||
if (Game != null) Game.Connections -= SendSegment;
|
if (Game != null) Game.Connections -= SendSegment;
|
||||||
|
return Game?.Players;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendToAll(ArraySegment<byte> segment) => Game?.SendToAll(segment);
|
public void SendToAll(ArraySegment<byte> segment) => Game?.SendToAll(segment);
|
||||||
|
@ -9,12 +9,25 @@ public class Game // TODO handle disconnects and reconnects
|
|||||||
{
|
{
|
||||||
private readonly Random _random = new();
|
private readonly Random _random = new();
|
||||||
private int _currentPlayerIndex;
|
private int _currentPlayerIndex;
|
||||||
|
private List<Player> _players = new();
|
||||||
|
|
||||||
public Game(Queue<DirectionalPosition> spawns) => Spawns = spawns;
|
public Game(Queue<DirectionalPosition> spawns) => Spawns = spawns;
|
||||||
|
|
||||||
[JsonInclude] public Guid Id { get; } = Guid.NewGuid();
|
[JsonInclude] public Guid Id { get; } = Guid.NewGuid();
|
||||||
|
|
||||||
[JsonIgnore] public List<Player> Players { get; } = new();
|
[JsonIgnore]
|
||||||
|
public List<Player> Players
|
||||||
|
{
|
||||||
|
get => _players;
|
||||||
|
set =>
|
||||||
|
_players = _players.Select((player, index) =>
|
||||||
|
{
|
||||||
|
player.State = value[index].State;
|
||||||
|
player.PacMan = value[index].PacMan;
|
||||||
|
player.Box = value[index].Box;
|
||||||
|
return player;
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
[JsonIgnore] public List<Character> Ghosts { get; set; } = new();
|
[JsonIgnore] public List<Character> Ghosts { get; set; } = new();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user