tl;dr: if we keep the true state secret and only expose parts of it that should be visible to the requesting user via a "state view", how can we implement client side prediction (of things that could be predicted) considering that state updates operate on the "real full state", not state views? (without duplicating update code for state views)
Consider having a server "domain state" class that keeps track of players' scores and coin counts:
class SeverState(object):
scores: Dict[str, int]
coins: Dict[str, int]
we would like each client to know other players' scores, but keep the coin count secret, and have some derivative state (possibly using secret data) therefore we expose only a "view" of the server state:
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))
players can take certain actions to change the game state
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): ...
Of course we can not know who is the richest player after taking a turn (doing grab_a_coin
) without server telling us, but we definitely should have enough data at that point to know our own wealth and scores of others (assuming they did not change).
Assume that we can share the entirely of our codebase with the client. I wonder what are patterns for not repeating yourself in a situation like that: how can we let the user predict their updated state view if our server side code operates on original states (e.g. grab_a_coin
function)?
One way is for the ServerStateView
to have exactly same fields as ServerState
, storing only information available to the user, and "secret fields" raising exceptions upon access or returning UnknownData()
instances (e.g. coins
would only return an actual number when accessed with current player_id
and would not hold any "secret data" whatsoever), e.g. something like coins = SecretDict(player_id = state.coins[player_id])
. But this seems
Aucun commentaire:
Enregistrer un commentaire