SignalR多人游戏平台架构

时间:2019-03-06 17:46:27

标签: c# architecture signalr multiplayer real-time-multiplayer

我正在multiplayer game平台上工作,该平台将有多个(主要是turn-basedmultiplayer 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 个答案:

没有答案