Архитектура многопользовательской игровой платформы SignalR

Я работаю на multiplayer game Платформа, которая будет иметь несколько (в основном turn-based) multiplayer games, Основная идея заключается в том, что каждый player подключается к конкретному game и в этом game у них будет несколько lobbies, Пользователь может ввести каждый lobby где они будут видеть других игроков в lobby так же как game instances (открытые игры) в этом lobby, Пользователи также смогут создавать новые game instance в пределах lobby и ждите, пока другие игроки присоединятся, чтобы начать игру.

У меня проблемы с архитектурой текущего состояния игрока. Разве это нормально - иметь какую-то модель игрока (которая на самом деле была бы просто расширенной моделью пользователя), в которой сохраняется все состояние игрока? Что-то вроде этого:

public interface IPlayer
{
    Guid UserId { get; set; }
    string Name { get; set; }

    Guid GameDefinitionId { get; set; }
    Guid? LobbyId { get; set; }
    Guid? GameId { get; set; }
}
  • GameDefinitionId - Определяет, какое определение игры (покер, блэкджек и т. Д.) Выбрал пользователь. Каждая из игр имеет свою hub поэтому, когда пользователь подключен к hub (конкретный game), Player экземпляр создан с указанным GameDefinitionId который является идентификатором этого game (поэтому это не является обязательным в модели).
  • LobbyId - Необязательный идентификатор lobby показывая, что пользователь находится в указанном лобби.
  • GameId - Необязательный game идентификатор экземпляра, показывающий, что пользователь находится в указанном game,

Изменяя эти свойства (в настоящее время список IPlayer является in-memory, но при необходимости я бы переместил его в database позже) я могу точно сказать, где находится пользователь и контролировать его состояние. Обратите внимание, что пользователь не может быть в нескольких лобби или играх одновременно. Конечно, каждое изменение подтверждается service и если изменение действительно, все заинтересованные clients уведомлены.

Это базовый центр, который каждая игра должна реализовывать

public abstract class MultiplayerGameHub : HubBase
{
    protected IPlayerHandler PlayerHandler { get; private set; }        

    public MultiplayerGameHub(
        IOnlineClientManager onlineClientManager,
        ISessionProvider sessionProvider,
        IPlayerHandler playerHandler)
        : base(onlineClientManager, sessionProvider)
    {
        PlayerHandler = playerHandler;
    }

    public virtual async Task Connect()
    {
        var gameDefinition = await GetGameDefinitionAsync();
        if (gameDefinition == null)
        {
            throw new HubException("Unknown game definition");
        }

        await PlayerHandler.ConnectAsync(Context.ConnectionId, gameDefinition.Id);
    }

    public virtual Task Disconnect()
    {
        return PlayerHandler.DisconnectAsync(Context.ConnectionId);
    }

    public Task JoinLobby(JoinLobbyParams model)
    {
        return PlayerHandler.JoinLobbyAsync(Context.ConnectionId, model.LobbyId);
    }

    public Task LeaveLobby()
    {
        return PlayerHandler.LeaveLobbyAsync(Context.ConnectionId);
    }

    public abstract Task<IGameDefinition> GetGameDefinitionAsync();
}

Это хороший подход, или я должен обращаться с этим по-другому?

0 ответов

Другие вопросы по тегам