示例#1
0
def AutoUpdatePlayerGroups(game_state, player_id, new_player=False):
  """Auto add/remove a player from groups.

  When a player changes allegiances, automatically add/remove them
  from groups.
  If new player, there is no group removal and we need to add to groups without
  an allegiance.

  Args:
    player_id: A player ID
    new_player: This is a new player vs allegiance switch.

  Firebase entries:
    /groups/%(groupId)/players/%(playerId)
    /playersPrivate/%(playerId)/chatRooms/
    /playersPrivate/%(playerId)/missions/
  """
  game = helpers.PlayerToGame(game_state, player_id)
  allegiance = helpers.PlayerAllegiance(game_state, player_id)
  groups = game_state.get('/games/%s' % game, 'groups') or []
  for group_id in groups:
    group = game_state.get('/groups', group_id)
    if group['autoAdd'] and group['allegianceFilter'] == allegiance:
      AddPlayerToGroupInner(game_state, group_id, player_id)
    elif (not new_player and group['autoRemove'] and
          group['allegianceFilter'] != allegiance):
      RemovePlayerFromGroupInner(game_state, group_id, player_id)
    elif new_player and group['autoAdd'] and group['allegianceFilter'] == 'none':
      AddPlayerToGroupInner(game_state, group_id, player_id)
示例#2
0
def AddLife(request, game_state):
  """Add a new player life.

  Validation:

  Args:
    playerId: The player who gets the new life.

  Firebase entry:
    /playersPublic/%(playerId)/lives
    /lives/%(lifeCode)
  """
  helpers.ValidateInputs(request, game_state, {
    'gameId': 'GameId',
    'playerId': 'PlayerId',
    'lifeCode': '?String',
    'lifeId': '?!LifeId'
  })

  player_id = request['playerId']
  game_id = helpers.PlayerToGame(game_state, player_id)
  life_id = request['lifeId'] or 'life-%s' % random.randint(0, 2**52)
  life_code = request['lifeCode'] or RandomWords(3)

  public_life = {
    'time': int(time.time()),
  }

  private_life = {
    'code': life_code,
  }

  game_state.put('/playersPublic/%s/lives' % player_id, life_code, public_life),
  game_state.put('/playersPrivate/%s/lives' % player_id, life_code, private_life)
示例#3
0
def SetPlayerAllegiance(game_state, player_id, allegiance, can_infect):
  """Helper to set the allegiance of a player.

  Args:
    player_id: The player to update.
    allegiance: Human vs zombie.
    can_infect: Can they infect. Must be true for zombies.

  Validation:
    None.

  Firebase entries:
    /playersPublic/%(playerId)/allegiance
    /playersPrivate/%(playerId)/canInfect
    /groups/%(groupId) indirectly
  """
  game_id = helpers.PlayerToGame(game_state, player_id)
  game_state.put('/playersPublic/%s' % player_id, 'allegiance', allegiance)
  game_state.put('/playersPrivate/%s' % player_id, 'canInfect', can_infect)
  AutoUpdatePlayerGroups(game_state, player_id, new_player=False)
示例#4
0
def Infect(request, game_state):
  """Infect a player via life code.

  Infect a human and gets points.

  Args:
    playerId: The person doing the infecting.
    lifeCode: The life code being taken/infected, makes to the victom.


  Validation:
    Valid IDs. Infector can infect or is self-infecting. Infectee is human.

  Firebase entries:
    /games/%(gameId)/players/%(playerId)
    /groups/%(groupId) indirectly
  """
  helpers.ValidateInputs(request, game_state, {
    'infectionId': '!InfectionId',
    'gameId': 'GameId',
    'infectorPlayerId': 'PlayerId',
    'victimLifeCode': '?String',
    'victimPlayerId': '?PlayerId',
  })

  game_id = request['gameId']
  infector_player_id = request['infectorPlayerId']
  infection_id = request['infectionId']
  victim_life_code = request['victimLifeCode']
  victim_player_id = helpers.LifeCodeToPlayerId(game_state, game_id, victim_life_code)

  infector_player = helpers.GetWholePlayer(game_state, infector_player_id)
  victim_player = helpers.GetWholePlayer(game_state, victim_player_id)

  print "Infector %s is infecting %s" % (infector_player_id, victim_player_id)
  print "infector:"
  print infector_player

  # Both players must be in the same game.
  if helpers.PlayerToGame(game_state, victim_player_id) != game_id:
    raise InvalidInputError('Those players are not part of the same game!')
  # The infector must be able to infect or be doing a self-infect
  if infector_player_id != victim_player_id and not infector_player['canInfect']:
    raise InvalidInputError('You cannot infect another player at the present time.')
  # The victim must be human to be infected
  if victim_player['allegiance'] != constants.HUMAN:
    raise InvalidInputError('Your victim is not human and cannot be infected.')

  # Add points and an infection entry for a successful infection
  if infector_player_id != victim_player_id:
    helpers.AddPoints(game_state, infector_player_id, constants.POINTS_INFECT)
    infect_path = '/playersPublic/%s/infections' % victim_player_id
    infect_data = {
      'infectorId': infector_player_id,
      'time': int(time.time()),
    }
    game_state.put(infect_path, infection_id, infect_data)

  # If secret zombie, set the victim to secret zombie and the infector to zombie
  # Else set the victom to zombie
  if infector_player_id != victim_player_id and infector_player['allegiance'] == constants.HUMAN:
    logging.warn('Secret infection')
    SetPlayerAllegiance(game_state, victim_player_id, allegiance=constants.HUMAN, can_infect=True)
    SetPlayerAllegiance(game_state, infector_player_id, allegiance=constants.ZOMBIE, can_infect=True)
  else:
    logging.warn('Normal infection')
    SetPlayerAllegiance(game_state, victim_player_id, allegiance=constants.ZOMBIE, can_infect=True)

  # DO NOT BLINDLY COPY THIS
  # Returning game data from the server (other than an error message or a success boolean)
  # is risky for the client; the client has to be careful about race conditions when reading
  # data returned from the server. In this case, this playerId response will likely reach
  # the client before firebase tells the client that this player was zombified.
  return victim_player_id
示例#5
0
def RemovePlayerFromGroup(request, game_state):
  """Remove a player from a group.

  Either a member of the group or the admin adds a player.

  Validation:
    * Player doing the removing is a member of the group AND the group supports removing
      or
      The player is the group owner.
    * playerToAddId is in the group.
    * Both players and the groupId all point to the same game.

  Args:
    groupId: The group to remove a player from.
    playerId: The player doing the removing (unless an admin).
    playerToAddId: The player being removed.

  Firebase entries:
    /groups/%(groupId)/players/%(playerId)
    /playersPrivate/%(playerId)/chatRooms/
    /playersPrivate/%(playerId)/missions/
  """
  helpers.ValidateInputs(request, game_state, {
    'groupId': 'GroupId',
    'gameId': 'GameId',
    'playerToRemoveId': 'PlayerId',
    'actingPlayerId': '?PlayerId'
  })

  requesting_player_id = request['requestingPlayerId']
  requesting_user_id = request['requestingUserId']
  acting_player_id = request['actingPlayerId']
  group_id = request['groupId']
  player_to_remove_id = request['playerToRemoveId']
  game_id = request['gameId']

  if helpers.IsAdmin(game_state, game_id, requesting_user_id):
    pass
  elif acting_player_id is not None:
    pass
  else:
    raise InvalidInputError('Only a player or an admin can call this method!')

  if game_id != helpers.PlayerToGame(game_state, player_to_remove_id):
    raise InvalidInputError('Other player is not in the same game as you.')
  if game_id != helpers.GroupToGame(game_state, group_id):
    raise InvalidInputError('That group is not part of your active game.')

  # Validate otherPlayer is in the group
  if not game_state.get('/groups/%s/players' % group_id, player_to_remove_id):
    raise InvalidInputError('Other player is not in the chat.')

  # Player must be admin or the owner or (be in the group and group allows adding).
  if helpers.IsAdmin(game_state, game_id, requesting_user_id):
    pass
  elif acting_player_id == game_state.get('/groups/%s' % group_id, 'ownerPlayerId'):
    pass
  else:
    # Validate player is in the chat room.
    if not game_state.get('/groups/%s/players' % group_id, acting_player_id):
      raise InvalidInputError('You are not a member of that group nor an owner.')
    # Validate players are allowed to remove other players.
    if not game_state.get('/groups/%s' % group_id, 'canRemoveOthers'):
      raise InvalidInputError('Players are not allowed to remove from this group.')

  RemovePlayerFromGroupInner(game_state, group_id, player_to_remove_id)
示例#6
0
def ClaimReward(request, game_state):
  """Claim a reward for a player.

  Validation:
    Reward is valid.
    Reward was not yet claimed.
    This player doesn't have the reward in their claims.

  Args:
    playerId: Player's ID
    gameId: Game ID
    rewardId: reward-foo-bar. Must start with the category

  Firebase entries:
    /playersPublic/%(playerId)/claims/%(rewardId)
    /playersPublic/%(playerId)/points
    /rewards/%(rewardId)/playerId
  """
  helpers.ValidateInputs(request, game_state, {
    'playerId': 'PlayerId',
    'gameId': 'GameId',
    'rewardCode': 'String'
  })

  player_id = request['playerId']
  game_id = request['gameId']
  reward_code = request['rewardCode']
  game = helpers.PlayerToGame(game_state, player_id)

  reward_id = helpers.RewardCodeToRewardId(game_state, game_id, reward_code)
  reward = game_state.get('/rewards', reward_id)
  reward_category_id = reward['rewardCategoryId']
  reward_category_path = '/rewardCategories/%s' % reward_category_id

  player_path = '/playersPublic/%s' % player_id
  reward_path = '/rewards/%s' % reward_id

  reward_category =  game_state.get(reward_category_path, None)

  # Validate the user hasn't already claimed it.
  if game_state.get('%s/claims/%s' % (player_path, reward_id), 'time'):
    raise InvalidInputError('Reward was already claimed by this player.')
  # Validate the reward was not yet claimed by another player.
  already_claimed_by_player_id = game_state.get(reward_path, 'playerId')
  if already_claimed_by_player_id != "" and already_claimed_by_player_id != None:
    raise InvalidInputError('Reward was already claimed.')
  # Check the limitPerPlayer
  if 'limitPerPlayer' in reward_category and int(reward_category['limitPerPlayer']) >= 1:
    limit = int(reward_category['limitPerPlayer'])
    claims = game_state.get(player_path, 'claims')
    if claims:
      claims = [c for c in claims if c['rewardCategoryId'] == reward_category_id]
      if len(claims) >= limit:
        raise InvalidInputError('You have already claimed this reward type %d times, which is the limit.' % limit)

  game_state.patch(reward_path, {'playerId': player_id})

  reward_points = int(reward_category['points'])
  rewards_claimed = int(reward_category['claimed'])

  helpers.AddPoints(game_state, player_id, reward_points)
  game_state.patch(reward_category_path, {'claimed': rewards_claimed + 1})
  game_state.patch(reward_path, {'playerId': player_id})
  claim_data = {'rewardCategoryId': reward_category_id, 'time': int(time.time())}
  game_state.put('%s/claims' % player_path, reward_id, claim_data)

  return reward_category_id