plugins room_game, quiz, radiocol, tarot: use JID instead of unicode in many methods + class attributes

This commit is contained in:
souliane 2015-03-11 12:36:22 +01:00
commit 5ef7999fa7

View file

@ -21,7 +21,7 @@ from sat.core.i18n import _
from sat.core.constants import Const as C
from sat.core.log import getLogger
log = getLogger(__name__)
from twisted.words.protocols.jabber.jid import JID
from twisted.words.protocols.jabber import jid
from twisted.words.xish import domish
from twisted.internet import defer
from time import time
@ -51,7 +51,7 @@ PLUGIN_INFO = {
class RoomGame(object):
"""This class is used to help launching a MUC game.
Bridge methods callbacks: prepareRoom, playerReady, createGame
Bridge methods callbacks: _prepareRoom, _playerReady, _createGame
Triggered methods: userJoinedTrigger, userLeftTrigger
Also called from subclasses: newRound
@ -107,7 +107,7 @@ class RoomGame(object):
self.game_init = game_init
self.player_init = player_init
self.games = {}
self.invitations = {} # list of couple (x, y) with x the time and y a list of users
self.invitations = {} # values are a couple (x, y) with x the time and y a list of users
# These are the default settings, which can be overwritten by child class after initialization
self.invite_mode = self.FROM_PLAYERS if self.player_init == {} else self.FROM_NONE
@ -126,129 +126,134 @@ class RoomGame(object):
def _createOrInvite(self, room, other_players, profile):
"""
This is called only when someone explicitly wants to play.
The game will not be created if one already exists in the room,
also its creation could be postponed until all the expected players
join the room (in that case it will be created from userJoinedTrigger).
@param room: instance of wokkel.muc.Room
@param other_players: list for other players JID userhosts
@param room (wokkel.muc.Room): the room
@param other_players (list[jid.JID]): list of the other players JID (bare)
"""
user_jid = self.host.getJidNStream(profile)[0]
room_jid_s = room.occupantJID.userhost()
nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid_s, profile)
room_jid = room.occupantJID.userhostJID()
nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid, profile)
nicks = [nick]
if self._gameExists(room_jid_s):
if not self._checkJoinAuth(room_jid_s, user_jid.userhost(), nick):
if self._gameExists(room_jid):
if not self._checkJoinAuth(room_jid, user_jid, nick):
return
nicks.extend(self._invitePlayers(room, other_players, nick, profile))
self._updatePlayers(room_jid_s, nicks, True, profile)
self._updatePlayers(room_jid, nicks, True, profile)
else:
self._initGame(room_jid_s, nick)
self._initGame(room_jid, nick)
(auth, waiting, missing) = self._checkWaitAuth(room, other_players)
nicks.extend(waiting)
nicks.extend(self._invitePlayers(room, missing, nick, profile))
if auth:
self.createGame(room_jid_s, nicks, profile)
self.createGame(room_jid, nicks, profile)
else:
self._updatePlayers(room_jid_s, nicks, False, profile)
self._updatePlayers(room_jid, nicks, False, profile)
def _initGame(self, room_jid_s, referee_nick):
"""Important: do not add the referee to 'players' yet. For a
<players /> message to be emitted whenever a new player is joining,
it is necessary to not modify 'players' outside of _updatePlayers.
def _initGame(self, room_jid, referee_nick):
"""
referee = room_jid_s + '/' + referee_nick
self.games[room_jid_s] = {'referee': referee, 'players': [], 'started': False, 'status': {}}
self.games[room_jid_s].update(copy.deepcopy(self.game_init))
self.invitations.setdefault(room_jid_s, [])
def _gameExists(self, room_jid_s, started=False):
@param room_jid (jid.JID): JID of the room
@param referee_nick (unicode): nickname of the referee
"""
# Important: do not add the referee to 'players' yet. For a
# <players /> message to be emitted whenever a new player is joining,
# it is necessary to not modify 'players' outside of _updatePlayers.
referee_jid = jid.JID(room_jid.userhost() + '/' + referee_nick)
self.games[room_jid] = {'referee': referee_jid, 'players': [], 'started': False, 'status': {}}
self.games[room_jid].update(copy.deepcopy(self.game_init))
self.invitations.setdefault(room_jid, [])
def _gameExists(self, room_jid, started=False):
"""Return True if a game has been initialized/started.
@param started: if False, the game must be initialized to return True,
otherwise it must be initialized and started with createGame.
@return: True if a game is initialized/started in that room"""
return room_jid_s in self.games and (not started or self.games[room_jid_s]['started'])
return room_jid in self.games and (not started or self.games[room_jid]['started'])
def _checkJoinAuth(self, room_jid_s, user_jid_s=None, nick="", verbose=False):
def _checkJoinAuth(self, room_jid, user_jid=None, nick="", verbose=False):
"""Checks if this profile is allowed to join the game.
The parameter nick is used to check if the user is already
a player in that game. When this method is called from
userJoinedTrigger, nick is also used to check the user
identity instead of user_jid_s (see TODO comment below).
@param room_jid_s: the room hosting the game
@param user_jid_s: JID userhost of the user
@param nick: nick of the user
@param room_jid (jid.JID): the JID of the room hosting the game
@param user_jid (jid.JID): JID of the user
@param nick (unicode): nick of the user
@return: True if this profile can join the game
"""
auth = False
if not self._gameExists(room_jid_s):
if not self._gameExists(room_jid):
auth = False
elif self.join_mode == self.ALL or self.isPlayer(room_jid_s, nick):
elif self.join_mode == self.ALL or self.isPlayer(room_jid, nick):
auth = True
elif self.join_mode == self.INVITED:
user_jid_s = JID(user_jid_s).userhost()
# considering all the batches of invitations
for invitations in self.invitations[room_jid_s]:
if user_jid_s is not None:
if user_jid_s in invitations[1]:
for invitations in self.invitations[room_jid]:
if user_jid is not None:
if user_jid.userhostJID() in invitations[1]:
auth = True
break
else:
# TODO: that's not secure enough but what to do if
# wokkel.muc.User's 'entity' attribute is not set?!
if nick in [JID(invited).user for invited in invitations[1]]:
if nick in [invited.user for invited in invitations[1]]:
auth = True
break
if not auth and (verbose or _DEBUG):
log.debug(_("%(user)s not allowed to join the game %(game)s in %(room)s") % {'user': user_jid_s or nick, 'game': self.name, 'room': room_jid_s})
log.debug(_("%(user)s not allowed to join the game %(game)s in %(room)s") % {'user': user_jid.userhost() or nick, 'game': self.name, 'room': room_jid.userhost()})
return auth
def _updatePlayers(self, room_jid_s, nicks, sync, profile):
def _updatePlayers(self, room_jid, nicks, sync, profile):
"""Update the list of players and signal to the room that some players joined the game.
If sync is True, the news players are synchronized with the game data they have missed.
Remark: self.games[room_jid_s]['players'] should not be modified outside this method.
@param room_jid_s: room userhost
@param nicks: list of players nicks in the room (referee included, in first position)
@param sync: set to True to send synchronization data to the new players
@param profile
Remark: self.games[room_jid]['players'] should not be modified outside this method.
@param room_jid (jid.JID): JID of the room
@param nicks (list[unicode]): list of players nicks in the room (referee included, in first position)
@param sync (bool): set to True to send synchronization data to the new players
@param profile (unicode): %(doc_profile)s
"""
if nicks == []:
return
# this is better than set(nicks).difference(...) as it keeps the order
new_nicks = [nick for nick in nicks if nick not in self.games[room_jid_s]['players']]
new_nicks = [nick for nick in nicks if nick not in self.games[room_jid]['players']]
if len(new_nicks) == 0:
return
def setStatus(status):
for nick in new_nicks:
self.games[room_jid_s]['status'][nick] = status
self.games[room_jid]['status'][nick] = status
sync = sync and self._gameExists(room_jid_s, True) and len(self.games[room_jid_s]['players']) > 0
sync = sync and self._gameExists(room_jid, True) and len(self.games[room_jid]['players']) > 0
setStatus('desync' if sync else 'init')
self.games[room_jid_s]['players'].extend(new_nicks)
self._synchronizeRoom(room_jid_s, [JID(room_jid_s)], profile)
self.games[room_jid]['players'].extend(new_nicks)
self._synchronizeRoom(room_jid, [room_jid], profile)
if sync:
setStatus('init')
def _synchronizeRoom(self, room_jid_s, recipients, profile):
def _synchronizeRoom(self, room_jid, recipients, profile):
"""Communicate the list of players to the whole room or only to some users,
also send the synchronization data to the players who recently joined the game.
@param room_jid_s: room userhost
@recipients: list of JIDs, the recipients of the message could be:
- room JID
- room JID + "/" + user nick
@param profile
@param room_jid (jid.JID): JID of the room
@recipients (list[jid.JID]): list of JIDs, the recipients of the message could be:
- room JID
- room JID + "/" + user nick
@param profile (unicode): %(doc_profile)s
"""
if self._gameExists(room_jid_s, started=True):
element = self._createStartElement(self.games[room_jid_s]['players'])
if self._gameExists(room_jid, started=True):
element = self._createStartElement(self.games[room_jid]['players'])
else:
element = self._createStartElement(self.games[room_jid_s]['players'], name="players")
element = self._createStartElement(self.games[room_jid]['players'], name="players")
elements = [(element, None, None)]
sync_args = []
sync_data = self._getSyncData(room_jid_s)
sync_data = self._getSyncData(room_jid)
for nick in sync_data:
user_jid = JID(room_jid_s + '/' + nick)
user_jid = jid.JID(room_jid.userhost() + '/' + nick)
if user_jid in recipients:
user_elements = copy.deepcopy(elements)
for child in sync_data[nick]:
@ -263,18 +268,18 @@ class RoomGame(object):
for args, kwargs in sync_args:
self._sendElements(*args, **kwargs)
def _getSyncData(self, room_jid_s, force_nicks=None):
def _getSyncData(self, room_jid, force_nicks=None):
"""The synchronization data are returned for each player who
has the state 'desync' or if he's been contained by force_nicks.
@param room_jid_s: room userhost
@param room_jid (jid.JID): JID of the room
@param force_nicks: force the synchronization for this list of the nicks
@return: a mapping between player nicks and a list of elements to
be sent by self._synchronizeRoom for the game to be synchronized.
"""
if not self._gameExists(room_jid_s):
if not self._gameExists(room_jid):
return {}
data = {}
status = self.games[room_jid_s]['status']
status = self.games[room_jid]['status']
nicks = [nick for nick in status if status[nick] == 'desync']
if force_nicks is None:
force_nicks = []
@ -282,14 +287,14 @@ class RoomGame(object):
if nick not in nicks:
nicks.append(nick)
for nick in nicks:
elements = self.getSyncDataForPlayer(room_jid_s, nick)
elements = self.getSyncDataForPlayer(room_jid, nick)
if elements:
data[nick] = elements
return data
def getSyncDataForPlayer(self, room_jid_s, nick):
def getSyncDataForPlayer(self, room_jid, nick):
"""This method may (and should probably) be overwritten by a child class.
@param room_jid_s: room userhost
@param room_jid (jid.JID): JID of the room
@param nick: the nick of the player to be synchronized
@return: a list of elements to synchronize this player with the game.
"""
@ -297,20 +302,19 @@ class RoomGame(object):
def _invitePlayers(self, room, other_players, nick, profile):
"""Invite players to a room, associated game may exist or not.
@param room: wokkel.muc.Room instance
@param other_players: list of JID userhosts to invite
@param nick: nick of the user who send the invitation
@return: list of room nicks for invited players who are already in the room
@param room (wokkel.muc.Room): the room
@param other_players (list[jid.JID]): list of the players to invite
@param nick (unicode): nick of the user who send the invitation
@return: list[unicode] of room nicks for invited players who are already in the room
"""
room_jid = room.occupantJID.userhostJID()
room_jid_s = room.occupantJID.userhost()
if not self._checkInviteAuth(room_jid_s, nick):
if not self._checkInviteAuth(room_jid, nick):
return []
# TODO: remove invitation waiting for too long, using the time data
players_jids = [JID(player) for player in other_players]
self.invitations[room_jid_s].append((time(), [player.userhost() for player in players_jids]))
self.invitations[room_jid].append((time(), [player.userhostJID() for player in other_players]))
nicks = []
for player_jid in [player.userhostJID() for player in players_jids]:
for player_jid in [player.userhostJID() for player in other_players]:
# TODO: find a way to make it secure
other_nick = self.host.plugins["XEP-0045"].getRoomNickOfUser(room, player_jid, secure=self.testing)
if other_nick is None:
@ -319,58 +323,59 @@ class RoomGame(object):
nicks.append(other_nick)
return nicks
def _checkInviteAuth(self, room_jid_s, nick, verbose=False):
def _checkInviteAuth(self, room_jid, nick, verbose=False):
"""Checks if this user is allowed to invite players
@param room_jid_s: room userhost
@param room_jid (jid.JID): JID of the room
@param nick: user nick in the room
@param verbose: display debug message
@return: True if the user is allowed to invite other players
"""
auth = False
if self.invite_mode == self.FROM_ALL or not self._gameExists(room_jid_s):
if self.invite_mode == self.FROM_ALL or not self._gameExists(room_jid):
auth = True
elif self.invite_mode == self.FROM_NONE:
auth = not self._gameExists(room_jid_s, started=True) and self.isReferee(room_jid_s, nick)
auth = not self._gameExists(room_jid, started=True) and self.isReferee(room_jid, nick)
elif self.invite_mode == self.FROM_REFEREE:
auth = self.isReferee(room_jid_s, nick)
auth = self.isReferee(room_jid, nick)
elif self.invite_mode == self.FROM_PLAYERS:
auth = self.isPlayer(room_jid_s, nick)
auth = self.isPlayer(room_jid, nick)
if not auth and (verbose or _DEBUG):
log.debug(_("%(user)s not allowed to invite for the game %(game)s in %(room)s") % {'user': nick, 'game': self.name, 'room': room_jid_s})
log.debug(_("%(user)s not allowed to invite for the game %(game)s in %(room)s") % {'user': nick, 'game': self.name, 'room': room_jid.userhost()})
return auth
def isReferee(self, room_jid_s, nick):
def isReferee(self, room_jid, nick):
"""Checks if the player with this nick is the referee for the game in this room"
@param room_jid_s: room userhost
@param room_jid (jid.JID): room JID
@param nick: user nick in the room
@return: True if the user is the referee of the game in this room
"""
if not self._gameExists(room_jid_s):
if not self._gameExists(room_jid):
return False
return room_jid_s + '/' + nick == self.games[room_jid_s]['referee']
return jid.JID(room_jid.userhost() + '/' + nick) == self.games[room_jid]['referee']
def isPlayer(self, room_jid_s, nick):
def isPlayer(self, room_jid, nick):
"""Checks if the user with this nick is a player for the game in this room.
@param room_jid_s: room userhost
@param room_jid (jid.JID): JID of the room
@param nick: user nick in the room
@return: True if the user is a player of the game in this room
"""
if not self._gameExists(room_jid_s):
if not self._gameExists(room_jid):
return False
# Important: the referee is not in the 'players' list right after
# the game initialization, that's why we do also check with isReferee
return nick in self.games[room_jid_s]['players'] or self.isReferee(room_jid_s, nick)
return nick in self.games[room_jid]['players'] or self.isReferee(room_jid, nick)
def _checkWaitAuth(self, room, other_players, verbose=False):
"""Check if we must wait for other players before starting the game.
@param room: wokkel.muc.Room instance
@param other_players: list of players JID userhosts without the referee
@param verbose: display debug message
@param room (wokkel.muc.Room): the room
@param other_players (list[jid.JID]): list of the players without the referee
@param verbose (bool): display debug message
@return: (x, y, z) with:
x: False if we must wait, True otherwise
y: the nicks of the players that have been checked and confirmed
z: the players that have not been checked or that are missing
x: False if we must wait, True otherwise
y: the nicks of the players that have been checked and confirmed
z: the JID of the players that have not been checked or that are missing
"""
if self.wait_mode == self.FOR_NONE or other_players == []:
result = (True, [], other_players)
@ -388,20 +393,25 @@ class RoomGame(object):
def getUniqueName(self, muc_service=None, profile_key=C.PROF_KEY_NONE):
"""Generate unique room name
@param muc_service: you can leave empty to autofind the muc service
@param profile_key: %(doc_profile_key)s
@return: a unique name for a new room to be created
@param muc_service (jid.JID): you can leave empty to autofind the muc service
@param profile_key (unicode): %(doc_profile_key)s
@return: jid.JID (unique name for a new room to be created)
"""
# FIXME: jid.JID must be used instead of strings
room = self.host.plugins["XEP-0045"].getUniqueName(muc_service, profile_key=profile_key)
return "sat_%s_%s" % (self.name.lower(), room.full())
return jid.JID("sat_%s_%s" % (self.name.lower(), room.userhost()))
def prepareRoom(self, other_players=None, room_jid_s=None, profile_key=C.PROF_KEY_NONE):
def _prepareRoom(self, other_players=None, room_jid_s='', profile_key=C.PROF_KEY_NONE):
room_jid = jid.JID(room_jid_s) if room_jid_s else None
other_players = [jid.JID(player).userhostJID() for player in other_players]
return self.prepareRoom(other_players, room_jid, profile_key)
def prepareRoom(self, other_players=None, room_jid=None, profile_key=C.PROF_KEY_NONE):
"""Prepare the room for a game: create it if it doesn't exist and invite players.
@param other_players: list for other players JID userhosts
@param room_jid_s: JID userhost of the room, or None to generate a unique name
@param profile_key
@param other_players (list[JID]): list of other players JID (bare)
@param room_jid (jid.JID): JID of the room, or None to generate a unique name
@param profile_key (unicode): %(doc_profile_key)s
"""
log.debug(_('Preparing room for %s game') % self.name)
profile = self.host.memory.getProfileName(profile_key)
@ -413,19 +423,18 @@ class RoomGame(object):
def roomJoined(room):
"""@param room: instance of wokkel.muc.Room"""
self._createOrInvite(room, [JID(player).userhost() for player in other_players], profile)
self._createOrInvite(room, other_players, profile)
# Create/join the given room, or a unique generated one if no room is specified.
if room_jid_s is not None and room_jid_s != "": # a room name has been specified
if room_jid_s in self.host.plugins["XEP-0045"].clients[profile].joined_rooms:
roomJoined(self.host.plugins["XEP-0045"].clients[profile].joined_rooms[room_jid_s])
return defer.succeed(None)
if room_jid is None:
room_jid = self.getUniqueName(profile_key=profile_key)
else:
room_jid_s = self.getUniqueName(profile_key=profile_key)
if room_jid_s == "":
if room_jid in self.host.plugins["XEP-0045"].clients[profile].joined_rooms:
roomJoined(self.host.plugins["XEP-0045"].clients[profile].joined_rooms[room_jid])
return defer.succeed(None)
user_jid = self.host.getJidNStream(profile)[0]
d = self.host.plugins["XEP-0045"].join(JID(room_jid_s), user_jid.user, {}, profile)
d = self.host.plugins["XEP-0045"].join(room_jid, user_jid.user, {}, profile)
return d.addCallback(roomJoined)
def userJoinedTrigger(self, room, user, profile):
@ -435,29 +444,29 @@ class RoomGame(object):
@user: wokkel.muc.User object. user.nick is a unicode and user.entity a JID
@return: True to not interrupt the main process.
"""
room_jid_s = room.occupantJID.userhost()
room_jid = room.occupantJID.userhostJID()
profile_nick = room.occupantJID.resource
if not self.isReferee(room_jid_s, profile_nick):
if not self.isReferee(room_jid, profile_nick):
return True # profile is not the referee
if not self._checkJoinAuth(room_jid_s, user.entity.userhost() if user.entity else None, user.nick):
if not self._checkJoinAuth(room_jid, user.entity if user.entity else None, user.nick):
# user not allowed but let him know that we are playing :p
self._synchronizeRoom(room_jid_s, [JID(room_jid_s + '/' + user.nick)], profile)
self._synchronizeRoom(room_jid, [jid.JID(room_jid.userhost() + '/' + user.nick)], profile)
return True
if self.wait_mode == self.FOR_ALL:
# considering the last batch of invitations
batch = len(self.invitations[room_jid_s]) - 1
batch = len(self.invitations[room_jid]) - 1
if batch < 0:
log.error("Invitations from %s to play %s in %s have been lost!" % (profile_nick, self.name, room_jid_s))
log.error("Invitations from %s to play %s in %s have been lost!" % (profile_nick, self.name, room_jid.userhost()))
return True
other_players = self.invitations[room_jid_s][batch][1]
other_players = self.invitations[room_jid][batch][1]
(auth, nicks, dummy) = self._checkWaitAuth(room, other_players)
if auth:
del self.invitations[room_jid_s][batch]
del self.invitations[room_jid][batch]
nicks.insert(0, profile_nick) # add the referee
self.createGame(room_jid_s, nicks, profile_key=profile)
self.createGame(room_jid, nicks, profile_key=profile)
return True
# let the room know that a new player joined
self._updatePlayers(room_jid_s, [user.nick], True, profile)
self._updatePlayers(room_jid, [user.nick], True, profile)
return True
def userLeftTrigger(self, room, user, profile):
@ -467,89 +476,95 @@ class RoomGame(object):
@user: wokkel.muc.User object. user.nick is a unicode and user.entity a JID
@return: True to not interrupt the main process.
"""
room_jid_s = room.occupantJID.userhost()
room_jid = room.occupantJID.userhostJID()
profile_nick = room.occupantJID.resource
if not self.isReferee(room_jid_s, profile_nick):
if not self.isReferee(room_jid, profile_nick):
return True # profile is not the referee
if self.isPlayer(room_jid_s, user.nick):
if self.isPlayer(room_jid, user.nick):
try:
self.games[room_jid_s]['players'].remove(user.nick)
self.games[room_jid]['players'].remove(user.nick)
except ValueError:
pass
if len(self.games[room_jid_s]['players']) == 0:
del self.games[room_jid_s] # finish the game
if len(self.games[room_jid]['players']) == 0:
return True
if self.wait_mode == self.FOR_ALL:
# allow this user to join the game again
user_jid_s = user.entity.userhost()
if len(self.invitations[room_jid_s]) == 0:
self.invitations[room_jid_s].append((time(), [user_jid_s]))
user_jid = user.entity.userhostJID()
if len(self.invitations[room_jid]) == 0:
self.invitations[room_jid].append((time(), [user_jid]))
else:
batch = 0 # add to the first batch of invitations
if user_jid_s not in self.invitations[room_jid_s][batch][1]:
self.invitations[room_jid_s][batch][1].append(user_jid_s)
if user_jid not in self.invitations[room_jid][batch][1]:
self.invitations[room_jid][batch][1].append(user_jid)
return True
def _checkCreateGameAndInit(self, room_jid_s, profile):
"""Check if that profile can create the game. If the game can be created but is not initialized yet, this method will also do the initialization.
def _checkCreateGameAndInit(self, room_jid, profile):
"""Check if that profile can create the game. If the game can be created
but is not initialized yet, this method will also do the initialization.
@param room_jid_s: room userhost
@param room_jid (jid.JID): JID of the room
@param profile
@return: a couple (create, sync) with:
- create: set to True to allow the game creation
- sync: set to True to advice a game synchronization
"""
user_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid_s, profile)
user_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid, profile)
if not user_nick:
log.error('Internal error: profile %s has not joined the room %s' % (profile, room_jid_s))
log.error('Internal error: profile %s has not joined the room %s' % (profile, room_jid.userhost()))
return False, False
if self._gameExists(room_jid_s):
is_referee = self.isReferee(room_jid_s, user_nick)
if self._gameExists(room_jid_s, started=True):
log.warning(_("%(game)s game already created in room %(room)s") % {'game': self.name, 'room': room_jid_s})
if self._gameExists(room_jid):
is_referee = self.isReferee(room_jid, user_nick)
if self._gameExists(room_jid, started=True):
log.warning(_("%(game)s game already created in room %(room)s") % {'game': self.name, 'room': room_jid.userhost()})
return False, is_referee
elif not is_referee:
log.warning(_("%(game)s game in room %(room)s can only be created by %(user)s") % {'game': self.name, 'room': room_jid_s, 'user': user_nick})
log.warning(_("%(game)s game in room %(room)s can only be created by %(user)s") % {'game': self.name, 'room': room_jid.userhost(), 'user': user_nick})
return False, False
else:
self._initGame(room_jid_s, user_nick)
self._initGame(room_jid, user_nick)
return True, False
def createGame(self, room_jid_s, nicks=None, profile_key=C.PROF_KEY_NONE):
def _createGame(self, room_jid_s, nicks=None, profile_key=C.PROF_KEY_NONE):
self.createGame(jid.JID(room_jid_s), nicks, profile_key)
def createGame(self, room_jid, nicks=None, profile_key=C.PROF_KEY_NONE):
"""Create a new game.
This can be called directly from a frontend and skips all the checks and invitation system,
but the game must not exist and all the players must be in the room already.
@param room_jid: JID userhost of the room
@param nicks: list of players nicks in the room (referee included, in first position)
@param profile_key: %(doc_profile_key)s
@param room_jid (jid.JID): JID of the room
@param nicks (list[unicode]): list of players nicks in the room (referee included, in first position)
@param profile_key (unicode): %(doc_profile_key)s
"""
log.debug(_("Creating %(game)s game in room %(room)s") % {'game': self.name, 'room': room_jid_s})
log.debug(_("Creating %(game)s game in room %(room)s") % {'game': self.name, 'room': room_jid})
profile = self.host.memory.getProfileName(profile_key)
if not profile:
log.error(_("profile %s is unknown") % profile_key)
return
(create, sync) = self._checkCreateGameAndInit(room_jid_s, profile)
(create, sync) = self._checkCreateGameAndInit(room_jid, profile)
if nicks is None:
nicks = []
if not create:
if sync:
self._updatePlayers(room_jid_s, nicks, True, profile)
self._updatePlayers(room_jid, nicks, True, profile)
return
self.games[room_jid_s]['started'] = True
self._updatePlayers(room_jid_s, nicks, False, profile)
self.games[room_jid]['started'] = True
self._updatePlayers(room_jid, nicks, False, profile)
if self.player_init:
# specific data to each player (score, private data)
self.games[room_jid_s].setdefault('players_data', {})
self.games[room_jid].setdefault('players_data', {})
for nick in nicks:
# The dict must be COPIED otherwise it is shared between all users
self.games[room_jid_s]['players_data'][nick] = copy.deepcopy(self.player_init)
self.games[room_jid]['players_data'][nick] = copy.deepcopy(self.player_init)
def playerReady(self, player, referee, profile_key=C.PROF_KEY_NONE):
def _playerReady(self, player_nick, referee_jid_s, profile_key=C.PROF_KEY_NONE):
self.playerReady(player_nick, jid.JID(referee_jid_s), profile_key)
def playerReady(self, player_nick, referee_jid, profile_key=C.PROF_KEY_NONE):
"""Must be called when player is ready to start a new game
@param player: the player nick in the room
@param referee: referee userhost
@param referee_jid (jid.JID): JID of the referee
"""
profile = self.host.memory.getProfileName(profile_key)
if not profile:
@ -557,7 +572,7 @@ class RoomGame(object):
return
log.debug('new player ready: %s' % profile)
# TODO: we probably need to add the game and room names in the sent message
self.send(JID(referee), 'player_ready', {'player': player}, profile=profile)
self.send(referee_jid, 'player_ready', {'player': player_nick}, profile=profile)
def newRound(self, room_jid, data, profile):
"""Launch a new round (reinit the user data)
@ -569,7 +584,7 @@ class RoomGame(object):
@param profile
"""
log.debug(_('new round for %s game') % self.name)
game_data = self.games[room_jid.userhost()]
game_data = self.games[room_jid]
players = game_data['players']
players_data = game_data['players_data']
game_data['stage'] = "init"
@ -578,7 +593,7 @@ class RoomGame(object):
if isinstance(msg_elts, dict):
for player in players:
to_jid = JID(room_jid.userhost() + "/" + player) # FIXME: gof:
to_jid = jid.JID(room_jid.userhost() + "/" + player) # FIXME: gof:
elem = msg_elts[player] if isinstance(msg_elts[player], domish.Element) else None
self.send(to_jid, elem, profile=profile)
elif isinstance(msg_elts, domish.Element):