Fixed bugs when disconnecting and reconnecting, disconnect message is sent before closing websocket connection
This commit is contained in:
parent
554b8cff2a
commit
cb9371b33b
@ -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, 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, teleportation doesn't work
|
||||
|
||||
|
@ -15,10 +15,10 @@ public class GameController : GenericController
|
||||
private readonly IActionService _actionService;
|
||||
private readonly GameService _gameService;
|
||||
|
||||
public GameController(ILogger<GameController> logger, GameService gameService, IActionService actionService) :
|
||||
base(logger, gameService)
|
||||
public GameController(ILogger<GameController> logger, GameService webSocketService, IActionService actionService) :
|
||||
base(logger, webSocketService)
|
||||
{
|
||||
_gameService = gameService;
|
||||
_gameService = webSocketService;
|
||||
_actionService = actionService;
|
||||
}
|
||||
|
||||
@ -85,5 +85,9 @@ public class GameController : GenericController
|
||||
|
||||
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
|
||||
{
|
||||
private const int BufferSize = 1024 * 4;
|
||||
protected readonly IWebSocketService GameService;
|
||||
private readonly IWebSocketService _webSocketService;
|
||||
protected readonly ILogger<GenericController> Logger;
|
||||
protected WebSocket? WebSocket;
|
||||
|
||||
protected GenericController(ILogger<GenericController> logger, IWebSocketService gameService)
|
||||
protected GenericController(ILogger<GenericController> logger, IWebSocketService webSocketService)
|
||||
{
|
||||
Logger = logger;
|
||||
GameService = gameService;
|
||||
_webSocketService = webSocketService;
|
||||
Logger.Log(LogLevel.Debug, "WebSocket Controller created");
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ public abstract class GenericController : ControllerBase
|
||||
do
|
||||
{
|
||||
var buffer = new byte[BufferSize];
|
||||
result = await GameService.Receive(WebSocket, buffer);
|
||||
result = await _webSocketService.Receive(WebSocket, buffer);
|
||||
|
||||
if (result.CloseStatus.HasValue) break;
|
||||
|
||||
@ -51,23 +51,26 @@ public abstract class GenericController : ControllerBase
|
||||
Send(segment);
|
||||
} 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)
|
||||
{
|
||||
Logger.Log(LogLevel.Error, "{}", e.Message);
|
||||
}
|
||||
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
protected virtual async void Send(ArraySegment<byte> segment)
|
||||
{
|
||||
if (WebSocket == null) return;
|
||||
await GameService.Send(WebSocket, segment);
|
||||
await _webSocketService.Send(WebSocket, segment);
|
||||
}
|
||||
|
||||
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("pacMan")] public required Character PacMan { get; init; }
|
||||
[JsonPropertyName("pacMan")] public required Character PacMan { get; set; }
|
||||
|
||||
[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;
|
||||
|
||||
|
@ -19,7 +19,7 @@ public interface IActionService
|
||||
string FindNextPlayer();
|
||||
List<Player> LeaveGame();
|
||||
void SendToAll(ArraySegment<byte> segment);
|
||||
void Disconnect();
|
||||
List<Player>? Disconnect();
|
||||
}
|
||||
|
||||
public class ActionService : IActionService
|
||||
@ -65,8 +65,12 @@ public class ActionService : IActionService
|
||||
public object? HandleMoveCharacter(JsonElement? jsonElement)
|
||||
{
|
||||
if (Game != null && jsonElement.HasValue)
|
||||
{
|
||||
Game.Ghosts = jsonElement.Value.GetProperty("ghosts").Deserialize<List<Character>>() ??
|
||||
throw new JsonException("Ghosts is null");
|
||||
Game.Players = jsonElement.Value.GetProperty("players").Deserialize<List<Player>>() ??
|
||||
throw new NullReferenceException("Players is null");
|
||||
}
|
||||
|
||||
return jsonElement;
|
||||
}
|
||||
@ -77,10 +81,11 @@ public class ActionService : IActionService
|
||||
Player = data.Player;
|
||||
|
||||
Game? game;
|
||||
Player? player;
|
||||
if ((game = _gameService.FindGameByUsername(Player.Username)) != null &&
|
||||
(player = game.Players.Find(p => p.Username == Player.Username))?.State == State.Disconnected)
|
||||
if ((game = _gameService.FindGameByUsername(Player.Username)) != null)
|
||||
{
|
||||
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 = player;
|
||||
Game = game;
|
||||
@ -125,11 +130,12 @@ public class ActionService : IActionService
|
||||
return Game.Players;
|
||||
}
|
||||
|
||||
public void Disconnect()
|
||||
public List<Player>? Disconnect()
|
||||
{
|
||||
if (Player == null) return;
|
||||
if (Player == null) return null;
|
||||
Player.State = State.Disconnected;
|
||||
if (Game != null) Game.Connections -= SendSegment;
|
||||
return Game?.Players;
|
||||
}
|
||||
|
||||
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 int _currentPlayerIndex;
|
||||
private List<Player> _players = new();
|
||||
|
||||
public Game(Queue<DirectionalPosition> spawns) => Spawns = spawns;
|
||||
|
||||
[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();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user