使用本地和远程数据进行身份验证的体系结构/实现

时间:2015-10-09 10:39:59

标签: android ios architecture synchronization client-server

我正在开发一款用户可以匿名离线播放的游戏。只要他们想要,他们就可以通过Facebook进行身份验证,并且可以将他们的分数发布到排行榜并发挥挑战。看起来很简单。它不是!

现在我遇到了一个我没想到的架构问题,我问是否已经有一种标准方法可以解决它。

假设: 用户在本地存储他们的个人分数,直到他们进行身份验 连接后,在线服务会在线存储分数。 设备和服务器应该同步,以便用户通过不同的设备尽可能地维护分数,服务器可以使用他的分数来匹配制作和排行榜。

现在,如果出现以下情况:

  1. 之前通过身份验证的玩家,可以离线播放?新分数将在第一个连接客户端同步=>服务器

  2. 玩家更改Facebook个人资料。分数存储在本地,因此新用户使用旧分数进行播放,并且当用户连接到服务时,根据1,同步客户端=>服务器将玩家1的分数推送给新玩家。错误!

  3. 玩家维护相同的Facebook个人资料,但更改设备。新设备上的分数为0,因此同步应为server =>客户端代替客户端=>服务器。此外,每当他回到之前的设备时,同步应该是server =>客户端代替客户端=>服务器

  4. 出现了很多其他问题,实际上,结合了以下三个方面:更改用户,更改设备,离线播放。

    考虑一个可能的解决方案我想在fb id,得分,简单的数字计数器或保存日期,本地和远程执行可能的检查,但没有完整的解决方案,并且始终存在条件玩家可能会失去他们的分数,或者新玩家可以获得更强的玩家得分。

    是否有一些算法,最佳实践,架构或任何可以帮助我解决这个(奇怪)问题的东西?

2 个答案:

答案 0 :(得分:0)

不是一个完美的解决方案,而是我在玩游戏时观察到的一种行为,它使用谷歌游戏服务来同步数据。

当我从其他设备离线播放一段时间并上线时,这些游戏会提示我对话。

此对话框告诉我服务器上有不同的配置文件,我是否要加载该配置文件(已保存状态)或继续使用当前配置文件。

  1. 如果我选择继续使用当前配置文件,我的当前配置文件会上传到服务器上,之前的配置文件会丢失。
  2. 如果我选择从服务器加载个人资料,我的当前个人资料将丢失,我的游戏会与服务器同步。
  3. 此外,如果我更改了我的Google帐户,我也会丢失所有已保存的个人资料。(以前同步的个人资料仍可在之前的帐户中使用)

    这不是一个完美的解决方案,但它有效并且让用户可以选择如何处理他/她的游戏数据。

    另外需要注意的是,考虑到用户可以使用连接不稳定的多台设备,任何解决方案都不能完美。

答案 1 :(得分:0)

我认为我得出了一个部分结论,可能会在以后更好地完成。

与分数一起,我存储了FBid和一个序列号。为了涵盖最常见的情况我们需要

这是我认为同步过程需要的初始方案:

 public void Sync()
{
if (local.FBid == null)
    // there's no FBid stored locally, so it's the first connection to
    // an online profile from this device.
    // The user might have used his profile before, so we cannot trust
    // a simple client-> server sync that would wipe the online score.
    // On the other hand, the user could have played a lot offline and
    // now decided to finally go online and export his score, that would
    // be lost with a server -> client sync.
    // To decide which profile is better we must trust the serial, considering
    // that a empty profile has serial 0.
    // We must understand if there is already a online profile.
    // If there is not, create it, otherwise take the one with the highest serial.
    // To do that we initialize and simply fall in the successive case.
{
    local.FBid = used.FBid;
}

if (local.FBid == used.FBid)
    // the local user is the same as the online user, we have to check if the player has advanced
    // the score playing offline. In that case the server will be updated.
    // Instead if the player is on a new device or increased the score using a different device,
    // the client will be updated.
    // there's no way to guarantee coherence if the player uses two devices on the same time, obviously.
{
    if (local.serial > server.serial) // supposing that a non-existant profile has serial == 0
        SyncClientToServer(); // update or create
    else
        SyncServerToClient();

} else // if (local.FBid != used.FBid)
    // the local stored user is not the same that has been used for the authentication.
    // the player is asked two options:
    // 1. wipe the local score and get the currently authenticated user from the server (that may be empty)
    // 2. keep the local score as it is, but play offline (without any sync) until the correct authentication is done
{
    if (AskWipeData())
        SyncServerToClient();
    else
        logoff(); // allow user to change the profile or go on playing offline
}

}