如果客户端仅存储部分状态,如何设计部分客户端预测?

时间:2019-06-16 00:32:03

标签: caching design-patterns client-server optimistic-ui client-side-prediction

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仅在使用当前player_id访问时才返回实际​​数字,而不会保存任何“秘密数据”),例如类似于coins = SecretDict(player_id = state.coins[player_id])。但这对我来说似乎有点脆弱,想知道其他人是否已经“解决了”。

0 个答案:

没有答案