tl;dr:如果我们保持真实状态的秘密,并且只公开通过“状态视图”对请求用户可见的部分,考虑到该状态,我们如何实现客户端预测(可以预测的事物)更新对“真正的完整状态”进行操作,而不是状态视图?(无需复制状态视图的更新代码)
考虑有一个服务器“域状态”类来跟踪玩家的分数和硬币数量:
class SeverState(object):
scores: Dict[str, int]
coins: Dict[str, int]
我们希望每个客户端都知道其他玩家的分数,但对硬币计数保密,并有一些衍生状态(可能使用秘密数据),因此我们只公开服务器状态的“视图”:
class ServerStateVeiw(object):
scores: Dict[str, int]
my_wealth: int
richest_id: int
def get_state_view(state: ServerState, player_id: int):
return ServerStateVeiw(
state.scores, state.coins[player_id], argmax(state.coins))
玩家可以采取某些行动来改变游戏状态
def export_rpc(f):
@wraps(f)
def wrapper(context):
new_state = f(context.player_id, context.game_state)
return get_state_view(new_state)
rpc.register(wrapper)
return wrapper
@export_rpc
def grab_a_coin(state: ServerState, player_id: int):
updated_coin_counts = state.coins[player_id].increment()
return ServerState(coins=updated_coin_counts, scores=state.scores)
@export_rpc
def buy_score(state: ServerState, player_id: int): ...
当然,在grab_a_coin
没有服务器告诉我们的情况下,我们无法在轮到(做)之后知道谁是最富有的玩家,但我们绝对应该有足够的数据来了解我们自己的财富和其他人的得分(假设他们没有改变)。
假设我们可以与客户共享整个代码库。我想知道在这种情况下不重复自己的模式是什么:如果我们的服务器端代码在原始状态(例如grab_a_coin
函数)上运行,我们如何让用户预测他们更新的状态视图?
一种方法是ServerStateView
具有与 完全相同的字段ServerState
,仅存储用户可用的信息,并且“秘密字段”在访问或返回UnknownData()
实例时引发异常(例如coins
,仅在使用 current 访问时返回实际数字,player_id
并且不会保存任何“秘密数据”),例如coins = SecretDict(player_id = state.coins[player_id])
. 但这对我来说似乎是一个有点脆弱的设计,不知道其他人是否已经“解决了它”。