Architecture/Implementation 使用本地和远程数据进行身份验证
Architecture/Implementation of authentication with local and remote data
我正在开发一款用户可以离线匿名玩的游戏。只要他们愿意,他们就可以通过 Facebook 进行身份验证,并可以 post 将他们的分数提交到排行榜并参与挑战。它看起来很简单。不是!
现在我遇到了一个我没想到的架构问题,我想问一下是否已经有一个标准的方法来解决它。
假设:
用户在本地存储他们的个人分数,直到他们进行身份验证。
当它们连接时,在线服务会在线存储分数。
设备和服务器要同步,让用户通过不同设备尽可能保持分数,服务器可以用他的分数来匹配和排行榜。
现在,如果发生什么情况:
之前认证过的玩家,离线玩?新的分数会在第一次连接客户端=>服务器同步。
一位玩家更改了 facebook 个人资料。分数存储在本地,所以新用户使用旧分数进行游戏,当用户连接服务时,根据1,同步客户端=>服务器将玩家1的分数推送给新玩家。错了!
一名玩家保持相同的 facebook 个人资料,但更换了设备。新设备上的分数是0,所以同步应该是server => client而不是client => server。另外,每当他回到以前的设备时,同步应该是服务器 => 客户端而不是客户端 => 服务器。
实际上,结合这三个方面会出现很多其他问题:更改用户、更改设备、离线播放。
考虑可能的解决方案我考虑过对 fb id、分数、简单的数字计数器或保存日期执行的可能检查,本地和远程,但没有完整的解决方案,并且总是有条件玩家可能会失去他们的分数,或者新玩家可以获得更强玩家的分数。
是否有一些算法、最佳实践、体系结构或任何可以帮助我解决这个(奇怪的)问题的东西?
这不是一个完美的解决方案,而是我在玩游戏时观察到的一种行为,它使用 google 玩游戏服务来同步数据。
当我在不同的设备上离线玩一段时间然后上线时,这些游戏会提示我对话。
此对话框告诉我服务器上有不同的配置文件可用,我是要加载该配置文件(保存状态)还是继续使用当前配置文件。
- 如果我 select 继续使用当前配置文件,我当前的配置文件将上传到服务器上,而之前的配置文件将丢失。
- 如果我select从服务器加载配置文件,我的当前配置文件会丢失,我的游戏会与服务器同步。
此外,如果我更改我的 google 帐户,我也会丢失所有已保存的配置文件。(之前同步的配置文件在较早的帐户上仍然可用)
这不是一个完美的解决方案,但它有效并让用户可以选择如何处理 his/her 游戏数据。
还要注意,考虑到用户可以使用多个连接不稳定的设备,任何解决方案都不可能是完美的。
我想我得出了一个部分的结论,也许以后会更好。
我将 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
}
}
我正在开发一款用户可以离线匿名玩的游戏。只要他们愿意,他们就可以通过 Facebook 进行身份验证,并可以 post 将他们的分数提交到排行榜并参与挑战。它看起来很简单。不是!
现在我遇到了一个我没想到的架构问题,我想问一下是否已经有一个标准的方法来解决它。
假设: 用户在本地存储他们的个人分数,直到他们进行身份验证。 当它们连接时,在线服务会在线存储分数。 设备和服务器要同步,让用户通过不同设备尽可能保持分数,服务器可以用他的分数来匹配和排行榜。
现在,如果发生什么情况:
之前认证过的玩家,离线玩?新的分数会在第一次连接客户端=>服务器同步。
一位玩家更改了 facebook 个人资料。分数存储在本地,所以新用户使用旧分数进行游戏,当用户连接服务时,根据1,同步客户端=>服务器将玩家1的分数推送给新玩家。错了!
一名玩家保持相同的 facebook 个人资料,但更换了设备。新设备上的分数是0,所以同步应该是server => client而不是client => server。另外,每当他回到以前的设备时,同步应该是服务器 => 客户端而不是客户端 => 服务器。
实际上,结合这三个方面会出现很多其他问题:更改用户、更改设备、离线播放。
考虑可能的解决方案我考虑过对 fb id、分数、简单的数字计数器或保存日期执行的可能检查,本地和远程,但没有完整的解决方案,并且总是有条件玩家可能会失去他们的分数,或者新玩家可以获得更强玩家的分数。
是否有一些算法、最佳实践、体系结构或任何可以帮助我解决这个(奇怪的)问题的东西?
这不是一个完美的解决方案,而是我在玩游戏时观察到的一种行为,它使用 google 玩游戏服务来同步数据。
当我在不同的设备上离线玩一段时间然后上线时,这些游戏会提示我对话。
此对话框告诉我服务器上有不同的配置文件可用,我是要加载该配置文件(保存状态)还是继续使用当前配置文件。
- 如果我 select 继续使用当前配置文件,我当前的配置文件将上传到服务器上,而之前的配置文件将丢失。
- 如果我select从服务器加载配置文件,我的当前配置文件会丢失,我的游戏会与服务器同步。
此外,如果我更改我的 google 帐户,我也会丢失所有已保存的配置文件。(之前同步的配置文件在较早的帐户上仍然可用)
这不是一个完美的解决方案,但它有效并让用户可以选择如何处理 his/her 游戏数据。
还要注意,考虑到用户可以使用多个连接不稳定的设备,任何解决方案都不可能是完美的。
我想我得出了一个部分的结论,也许以后会更好。
我将 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
}
}