Ejemplo n.º 1
0
class Main():

  def __init__(self, serial = None):
    parser = argparse.ArgumentParser(description='BraidsTag gun logic.')
    parser.add_argument('-s', '--serial', type=str, help='serial device to which the arduino is connected')

    self.args = parser.parse_args()

    self.player = None
    self.logic = StandardGameLogic()
    self.gameState = GameState()

    self.serverConnection = Client(self)
    self._sendToServer(proto.HELLO.create())

    if serial:
      self.serial = serial
      self.responsiveSerial = True
    else:
      if not self.args.serial:
        raise ArgumentError("You must specify -s if you do not start in fakeGun mode")

      try:
        import serial
        self.serial = serial.Serial(self.args.serial, 115200)
        self.responsiveSerial = True
      except ImportError:
        #We'll have to open this as a file
        print("WARNING: No serial module, assuming the serial argument is a normal file for testing")
        self.serial = open(self.args.serial)
        self.responsiveSerial = False
      except serial.serialutil.SerialException:
        #Try just opening this as a file
        self.serial = open(self.args.serial)
        self.responsiveSerial = False

    self.connectToArduino()

  def setPlayer(self, player):
    self.player = player

  def serialWrite(self, line):
    if (self.responsiveSerial):
      self.serial.write(line + "\n")

    print("-a>", repr(line + "\n"))
    sys.stdout.flush()

  def eventLoop(self):
    for line in self.serial:
      line = line.rstrip()
      print("<a-", repr(line))
      sys.stdout.flush()

      h = proto.MessageHandler()

      @h.handles(proto.HIT)
      def hit(sentTeam, sentPlayer, damage): # pylint: disable=W0612
        self.logic.hit(self.gameState, self.player, Player(sentTeam, sentPlayer), damage)
        return True

      @h.handles(proto.FULL_AMMO)
      def fullAmmo(): # pylint: disable=W0612
        self.logic.fullAmmo(self.gameState, self.player)
        return True

      @h.handles(proto.TRIGGER)
      def trigger(): # pylint: disable=W0612
        if (self.player and self.logic.trigger(self.gameState, self.player)):
          self.serialWrite(proto.FIRE.create(self.player.teamID, self.player.playerID, self.player.gunDamage))
        return True

      #TODO be more discerning about unparseable input here.
      h.handle(line)

      if (self.player):
        msg = proto.RECV.create(self.player.teamID, self.player.playerID, line)
      else:
        msg = proto.RECV.create(0, 0, line)
      self._sendToServer(msg)

  def _sendToServer(self, msg):
    "queue this packet to be sent to the server"
    self.serverConnection.queueMessage(msg)
  
  def connectToArduino(self):
    self.serialWrite(proto.CLIENTCONNECT.create())
    line = self.serial.readline()
    print("<a-", repr(line))
    sys.stdout.flush()

    if not proto.CLIENT_CONNECTED.parse(line):
      raise RuntimeError("incorrect ack to ClientConnect(): %s" % (line))

  def shutdown(self):
    #TODO: is this the right message for this?
    self.serialWrite(proto.CLIENTCONNECT.create())
Ejemplo n.º 2
0
class ServerMsgHandler():
  """A class to handle messages from clients to the server. There should only be one instance of this class""" 
  def __init__(self, listeningThread, gameState):
    self.listeningThread = listeningThread
    self.logic = StandardGameLogic()
    self.gameState = gameState

  #so we don't try to process messages from 2 clients at once.
  eventLock = Lock()
    
  def handleMsg(self, fullLine, connection):
    with self.eventLock:
      if mainWindow: # This should only be None in tests.
        mainWindow.lineReceived(fullLine)

      event = proto.parseEvent(fullLine)

      self.__handleEvent(event, self.gameState, connection)

    #TODO be more discerning 
    return True

  def __handleEvent(self, event, gameState, connection):
    """handle an event, you must be holding self.eventLock before calling this"""
    msgStr = event.msgStr

    h1 = proto.MessageHandler()

    @h1.handles(proto.RECV)
    def recv(recvTeamStr, recvPlayerStr, line):
      recvTeam = int(recvTeamStr)
      recvPlayer = int(recvPlayerStr)

      h2 = proto.MessageHandler()

      @h2.handles(proto.HIT)
      def hit(sentTeamStr, sentPlayerStr, damage):
        sentTeam = int(sentTeamStr)
        sentPlayer = int(sentPlayerStr)

        #TODO: add some sanity checks in here. The shooting player shouldn't be dead at this point 

        player = gameState.getOrCreatePlayer(recvTeam, recvPlayer)
        self.logic.hit(gameState, player, sentTeam, sentPlayer, damage)
        gameState.playerUpdated.emit(recvTeam, recvPlayer)

        return True

      @h2.handles(proto.TRIGGER)
      def trigger():
        player = gameState.getOrCreatePlayer(recvTeam, recvPlayer)
        if (self.logic.trigger(gameState, player)):
          gameState.playerUpdated.emit(recvTeam, recvPlayer)

        return True

      @h2.handles(proto.FULL_AMMO)
      def fullAmmo():
        player = gameState.getOrCreatePlayer(recvTeam, recvPlayer)
        if (self.logic.fullAmmo(gameState, player)):
          gameState.playerUpdated.emit(recvTeam, recvPlayer)

        return True

      return h2.handle(line)

    @h1.handles(proto.HELLO)
    def hello():
      clientId = event.id
      existingIds = self.listeningThread.isConnected(clientId)
      if existingIds:
        #TODO maintain the state of this client by sending it an update (taking our send queu into account).
        #For now, simply remove the ghost player from the game.
        self.gameState.deletePlayer(existingIds[0], existingIds[1])

      player = gameState.createNewPlayer()
      connection.queueMessage(proto.TEAMPLAYER.create(player.teamID, player.playerID))

      self.listeningThread.establishConnection(connection, player, clientId)

      if self.gameState.isGameStarted():
        connection.queueMessage(proto.STARTGAME.create(self.gameState.gameTimeRemaining()))

      return True

    return h1.handle(msgStr)
Ejemplo n.º 3
0
class Main():
    def __init__(self):
        parser = argparse.ArgumentParser(description='BraidsTag gun logic.')
        parser.add_argument(
            '-s',
            '--serial',
            type=str,
            help='serial device to which the arduino is connected',
            required=True)
        #parser.add_argument('-p', '--playerID', type=self._stringToPlayerID, help='player id', default=1)
        #parser.add_argument('-t', '--teamID', type=int, choices=xrange(1, 8), help='team id', default=1)

        self.args = parser.parse_args()

        self.serverConnection = Client(self)
        self._sendToServer(proto.HELLO.create(-1, -1))

        try:
            self.serial = serial.Serial(self.args.serial, 115200)
            self.properSerial = True
        except serial.serialutil.SerialException:
            #Try just opening this as a file
            self.serial = open(self.args.serial)
            self.properSerial = False

        def playerDead():
            print "Out of lives!"

        self.logic = StandardGameLogic()
        self.logic.playerDead.connect(playerDead)
        self.gameState = GameState()

        self.connectToArduino()

    def serialWrite(self, line):
        if (self.properSerial):
            self.serial.write(line + "\n")

        print "-a>", repr(line)
        sys.stdout.flush()

    def eventLoop(self):
        for line in self.serial:
            line = line.rstrip()
            print "<a-", repr(line)
            sys.stdout.flush()

            try:
                (sentTeam, sentPlayer, damage) = proto.HIT.parse(line)

                self.logic.hit(self.gameState, self.player, sentTeam,
                               sentPlayer, damage)
            except proto.MessageParseException:
                pass

            try:
                proto.FULL_AMMO.parse(line)

                self.logic.fullAmmo(self.gameState, self.player)
            except proto.MessageParseException:
                pass

            try:
                proto.TRIGGER.parse(line)

                if (self.logic.trigger(self.gameState, self.player)):
                    self.serialWrite(
                        proto.FIRE.create(self.player.teamID,
                                          self.player.playerID,
                                          self.player.gunDamage))
            except proto.MessageParseException:
                pass

            msg = proto.RECV.create(self.player.teamID, self.player.playerID,
                                    line)
            self._sendToServer(msg)

    def _stringToPlayerID(self, inp):
        out = int(inp)
        if out < 1 or out > 32:
            raise argparse.ArgumentTypeError(
                "playerId must be between 1 and 32.")
        return out

    def _sendToServer(self, msg):
        "queue this packet to be sent to the server"
        self.serverConnection.queueMessage(msg)

    def connectToArduino(self):
        self.serialWrite(proto.CLIENTCONNECT.create())
        line = self.serial.readline()
        print "<a-", repr(line)
        sys.stdout.flush()
        try:
            proto.CLIENT_CONNECTED.parse(line)
        except proto.MessageParseException:
            raise RuntimeError("incorrect ack to ClientConnect(): %s" % (line))
Ejemplo n.º 4
0
class ServerMsgHandler():
    """A class to handle messages from clients to the server. There should only be one instance of this class"""
    def __init__(self, listeningThread, gameState):
        self.listeningThread = listeningThread
        self.logic = StandardGameLogic()
        self.gameState = gameState

    #so we don't try to process messages from 2 clients at once.
    eventLock = Lock()

    def handleMsg(self, fullLine, connection):
        with self.eventLock:
            if mainWindow:  # This should only be None in tests.
                mainWindow.lineReceived(fullLine)

            event = proto.parseEvent(fullLine)

            self.__handleEvent(event, self.gameState, connection)

        #TODO be more discerning
        return True

    def __handleEvent(self, event, gameState, connection):
        """handle an event, you must be holding self.eventLock before calling this"""
        msgStr = event.msgStr

        h1 = proto.MessageHandler()

        @h1.handles(proto.RECV)
        def recv(recvTeamStr, recvPlayerStr, line):
            recvTeam = int(recvTeamStr)
            recvPlayer = int(recvPlayerStr)
            player = gameState.getOrCreatePlayer(recvTeam, recvPlayer)
            player.lastContact = time.time()

            h2 = proto.MessageHandler()

            @h2.handles(proto.HIT)
            def hit(sentTeamStr, sentPlayerStr, damage):
                sentTeam = int(sentTeamStr)
                sentPlayer = int(sentPlayerStr)

                #TODO: add some sanity checks in here. The shooting player shouldn't be dead at this point
                self.logic.hit(gameState, player, sentTeam, sentPlayer, damage)
                gameState.playerUpdated.emit(recvTeam, recvPlayer)

                return True

            @h2.handles(proto.TRIGGER)
            def trigger():
                if (self.logic.trigger(gameState, player)):
                    gameState.playerUpdated.emit(recvTeam, recvPlayer)

                return True

            @h2.handles(proto.FULL_AMMO)
            def fullAmmo():
                if (self.logic.fullAmmo(gameState, player)):
                    gameState.playerUpdated.emit(recvTeam, recvPlayer)

                return True

            return h2.handle(line)

        @h1.handles(proto.HELLO)
        def hello():
            clientId = event.id
            existingIds = self.listeningThread.isConnected(clientId)
            if existingIds:
                #TODO maintain the state of this client by sending it an update (taking our send queu into account).
                #For now, simply remove the ghost player from the game.
                self.gameState.deletePlayer(existingIds[0], existingIds[1])

            player = gameState.createNewPlayer()
            connection.queueMessage(
                proto.TEAMPLAYER.create(player.teamID, player.playerID))

            self.listeningThread.establishConnection(connection, player,
                                                     clientId)

            if self.gameState.isGameStarted():
                connection.queueMessage(
                    proto.STARTGAME.create(self.gameState.gameTimeRemaining()))

            return True

        return h1.handle(msgStr)
Ejemplo n.º 5
0
class Main():

  def __init__(self):
    parser = argparse.ArgumentParser(description='BraidsTag gun logic.')
    parser.add_argument('-s', '--serial', type=str, help='serial device to which the arduino is connected', required=True)
    #parser.add_argument('-p', '--playerID', type=self._stringToPlayerID, help='player id', default=1)
    #parser.add_argument('-t', '--teamID', type=int, choices=xrange(1, 8), help='team id', default=1)

    self.args = parser.parse_args()

    self.serverConnection = Client(self)
    self._sendToServer(proto.HELLO.create())

    try:
      self.serial = serial.Serial(self.args.serial, 115200)
      self.properSerial = True
    except serial.serialutil.SerialException:
      #Try just opening this as a file
      self.serial = open(self.args.serial)
      self.properSerial = False

    def playerDead():
      print "Out of lives!"

    self.logic = StandardGameLogic()
    self.logic.playerDead.connect(playerDead)
    self.gameState = GameState()

    self.connectToArduino()

  def serialWrite(self, line):
    if (self.properSerial):
      self.serial.write(line + "\n")

    print "-a>", repr(line)
    sys.stdout.flush()

  def eventLoop(self):
    for line in self.serial:
      line = line.rstrip()
      print "<a-", repr(line)
      sys.stdout.flush()

      h = proto.MessageHandler()

      @h.handles(proto.HIT)
      def hit(sentTeam, sentPlayer, damage):
        self.logic.hit(self.gameState, self.player, sentTeam, sentPlayer, damage)
        return True

      @h.handles(proto.FULL_AMMO)
      def fullAmmo():
        self.logic.fullAmmo(self.gameState, self.player)
        return True

      @h.handles(proto.TRIGGER)
      def trigger():
        if (self.logic.trigger(self.gameState, self.player)):
          self.serialWrite(proto.FIRE.create(self.player.teamID, self.player.playerID, self.player.gunDamage))
        return True

      #TODO be more discerning about unparseable input here.
      h.handle(line)

      msg = proto.RECV.create(self.player.teamID, self.player.playerID, line)
      self._sendToServer(msg)

  def _stringToPlayerID(self, inp):
    out = int(inp)
    if out < 1 or out > 32:
      raise argparse.ArgumentTypeError("playerId must be between 1 and 32.")
    return out;

  def _sendToServer(self, msg):
    "queue this packet to be sent to the server"
    self.serverConnection.queueMessage(msg)
  
  def connectToArduino(self):
    self.serialWrite(proto.CLIENTCONNECT.create())
    line = self.serial.readline()
    print "<a-", repr(line)
    sys.stdout.flush()

    if not proto.CLIENT_CONNECTED.parse(line):
      raise RuntimeError("incorrect ack to ClientConnect(): %s" % (line))
Ejemplo n.º 6
0
class Main():
    def __init__(self):
        parser = argparse.ArgumentParser(description='BraidsTag gun logic.')
        parser.add_argument(
            '-s',
            '--serial',
            type=str,
            help='serial device to which the arduino is connected')
        #parser.add_argument('-p', '--playerID', type=self._stringToPlayerID, help='player id', default=1)
        #parser.add_argument('-t', '--teamID', type=int, choices=xrange(1, 8), help='team id', default=1)
        parser.add_argument('-d',
                            '--debugGun',
                            help='use the debuggin gun UI',
                            default=False,
                            action='store_true')

        self.args = parser.parse_args()

        self.player = None

        self.serverConnection = Client(self)
        self._sendToServer(proto.HELLO.create())

        if self.args.debugGun:
            import fakeGun
            self.serial = fakeGun.showUI()
            self.responsiveSerial = True
        else:
            if not self.args.serial:
                raise ArgumentError(
                    "You must specify -s if you do not specify -d")

            try:
                import serial
                self.serial = serial.Serial(self.args.serial, 115200)
                self.responsiveSerial = True
            except ImportError:
                #We'll have to open this as a file
                print "WARNING: No serial module, assuming the serial argument is a normal file for testing"
                self.serial = open(self.args.serial)
                self.responsiveSerial = False
            except serial.serialutil.SerialException:
                #Try just opening this as a file
                self.serial = open(self.args.serial)
                self.responsiveSerial = False

        def playerDead():
            print "Out of lives!"

        self.logic = StandardGameLogic()
        self.logic.playerDead.connect(playerDead)
        self.gameState = GameState()

        self.connectToArduino()

    def serialWrite(self, line):
        if (self.responsiveSerial):
            self.serial.write(line + "\n")

        print "-a>", repr(line + "\n")
        sys.stdout.flush()

    def eventLoop(self):
        for line in self.serial:
            line = line.rstrip()
            print "<a-", repr(line)
            sys.stdout.flush()

            h = proto.MessageHandler()

            @h.handles(proto.HIT)
            def hit(sentTeam, sentPlayer, damage):
                self.logic.hit(self.gameState, self.player, sentTeam,
                               sentPlayer, damage)
                return True

            @h.handles(proto.FULL_AMMO)
            def fullAmmo():
                self.logic.fullAmmo(self.gameState, self.player)
                return True

            @h.handles(proto.TRIGGER)
            def trigger():
                if (self.logic.trigger(self.gameState, self.player)):
                    self.serialWrite(
                        proto.FIRE.create(self.player.teamID,
                                          self.player.playerID,
                                          self.player.gunDamage))
                return True

            #TODO be more discerning about unparseable input here.
            h.handle(line)

            msg = proto.RECV.create(self.player.teamID, self.player.playerID,
                                    line)
            self._sendToServer(msg)

    def _stringToPlayerID(self, inp):
        out = int(inp)
        if out < 1 or out > 32:
            raise argparse.ArgumentTypeError(
                "playerId must be between 1 and 32.")
        return out

    def _sendToServer(self, msg):
        "queue this packet to be sent to the server"
        self.serverConnection.queueMessage(msg)

    def connectToArduino(self):
        self.serialWrite(proto.CLIENTCONNECT.create())
        line = self.serial.readline()
        print "<a-", repr(line)
        sys.stdout.flush()

        if not proto.CLIENT_CONNECTED.parse(line):
            raise RuntimeError("incorrect ack to ClientConnect(): %s" % (line))
Ejemplo n.º 7
0
class ServerMsgHandler():
    """A class to handle messages from clients to the server. There should only be one instance of this class"""
    def __init__(self, listeningThread, gameState):
        self.listeningThread = listeningThread
        self.logic = StandardGameLogic()
        self.gameState = gameState

        #map from id to timestamp
        self.playerLastSeen = {}
        self.confidencePointGameState = gameState
        self.eventsSinceConfidencePoint = [
        ]  # a sorted list of (timestamp, event)
        self.confidencePoint = 0
        self.confidencePointMinimumInterval = 10  # Only update the cache at most once this many seconds.

    #so we don't try to process messages from 2 clients at once.
    eventLock = Lock()

    def handleMsg(self, fullLine):
        with self.eventLock:
            if mainWindow:  # This should only be None in tests.
                mainWindow.lineReceived(fullLine)

            event = proto.parseEvent(fullLine)

            self.playerLastSeen[event.id] = event.time

            #Check if we need to update the confidence point. If so, we will do so after we have parsed/handled this message.
            newConfidencePoint = min(self.playerLastSeen.values())
            updateConfidencePoint = newConfidencePoint > self.confidencePoint + self.confidencePointMinimumInterval

            #insert this event in the correct order (just because it was recieved last, doesn't mean it happened last!)
            insort(self.eventsSinceConfidencePoint, (event.time, event))

            #loop over all events since confidence point, creating a new best-guess gameState.
            self.gameState = self.confidencePointGameState  #TODO clone/copy this
            #print("Processing", self.eventsSinceConfidencePoint)
            for currEvent in self.eventsSinceConfidencePoint:
                self.__handleEvent(currEvent[1], self.gameState)

            if updateConfidencePoint:
                self.confidencePointGameState = self.gameState
                self.eventsSinceConfidencePoint = []
                self.confidencePoint = newConfidencePoint

        return "Ack()\n"

    def __handleEvent(self, event, gameState):
        """handle an event, you must be holding self.eventLock before calling this"""
        alreadyHandled = event.handled
        event.handled = True
        msgStr = event.msgStr
        try:
            (recvTeam, recvPlayer, line) = proto.RECV.parse(msgStr)

            try:
                (sentTeam, sentPlayer, damage) = proto.HIT.parse(line)

                #TODO: add some sanity checks in here. The shooting player shouldn't be dead at this point
                #(although if they are, it could be because we have incomplete data)

                player = gameState.getOrCreatePlayer(recvTeam, recvPlayer)
                self.logic.hit(gameState, player, sentTeam, sentPlayer, damage)
                gameState.playerUpdated.emit(recvTeam, recvPlayer)
            except proto.MessageParseException:
                pass

            try:
                proto.TRIGGER.parse(line)

                player = gameState.getOrCreatePlayer(recvTeam, recvPlayer)
                if (self.logic.trigger(gameState, player)):
                    gameState.playerUpdated.emit(recvTeam, recvPlayer)
            except proto.MessageParseException:
                pass

            try:
                proto.FULL_AMMO.parse(line)

                player = gameState.getOrCreatePlayer(recvTeam, recvPlayer)
                if (self.logic.fullAmmo(gameState, player)):
                    gameState.playerUpdated.emit(recvTeam, recvPlayer)
            except proto.MessageParseException:
                pass

        except proto.MessageParseException:
            pass

        #TODO: I need to work out what I do with a Hello in the new world of clients having ids and handleEvent being called more than once per event.
        if not alreadyHandled:
            try:
                (teamID, playerID) = proto.HELLO.parse(msgStr)

                if int(teamID) == -1:
                    player = gameState.createNewPlayer()
                    self.queueMessage(
                        proto.TEAMPLAYER.create(player.teamID,
                                                player.playerID))
                else:
                    player = gameState.getOrCreatePlayer(teamID, playerID)
                    self.queueMessage("Ack()\n")
                #TODO: we need to preserve the sendQueue when we do this
                self.listeningThread.moveConnection(self, player)

                if self.gameState.isGameStarted():
                    self.queueMessage(
                        proto.STARTGAME.create(
                            self.gameState.gameTimeRemaining()))
            except proto.MessageParseException:
                pass
Ejemplo n.º 8
0
class ServerMsgHandler:
    """A class to handle messages from clients to the server. There should only be one instance of this class"""

    def __init__(self, listeningThread, gameState):
        self.listeningThread = listeningThread
        self.logic = StandardGameLogic()
        self.gameState = gameState

        # map from id to timestamp
        self.playerLastSeen = {}
        self.confidencePointGameState = gameState
        self.eventsSinceConfidencePoint = []  # a sorted list of (timestamp, event)
        self.confidencePoint = 0
        self.confidencePointMinimumInterval = 10  # Only update the cache at most once this many seconds.

    # so we don't try to process messages from 2 clients at once.
    eventLock = Lock()

    def handleMsg(self, fullLine):
        with self.eventLock:
            if mainWindow:  # This should only be None in tests.
                mainWindow.lineReceived(fullLine)

            event = proto.parseEvent(fullLine)

            self.playerLastSeen[event.id] = event.time

            # Check if we need to update the confidence point. If so, we will do so after we have parsed/handled this message.
            newConfidencePoint = min(self.playerLastSeen.values())
            updateConfidencePoint = newConfidencePoint > self.confidencePoint + self.confidencePointMinimumInterval

            # insert this event in the correct order (just because it was recieved last, doesn't mean it happened last!)
            insort(self.eventsSinceConfidencePoint, (event.time, event))

            # loop over all events since confidence point, creating a new best-guess gameState.
            self.gameState = self.confidencePointGameState  # TODO clone/copy this
            # print("Processing", self.eventsSinceConfidencePoint)
            for currEvent in self.eventsSinceConfidencePoint:
                self.__handleEvent(currEvent[1], self.gameState)

            if updateConfidencePoint:
                self.confidencePointGameState = self.gameState
                self.eventsSinceConfidencePoint = []
                self.confidencePoint = newConfidencePoint

        return "Ack()\n"

    def __handleEvent(self, event, gameState):
        """handle an event, you must be holding self.eventLock before calling this"""
        alreadyHandled = event.handled
        event.handled = True
        msgStr = event.msgStr
        try:
            (recvTeam, recvPlayer, line) = proto.RECV.parse(msgStr)

            try:
                (sentTeam, sentPlayer, damage) = proto.HIT.parse(line)

                # TODO: add some sanity checks in here. The shooting player shouldn't be dead at this point
                # (although if they are, it could be because we have incomplete data)

                player = gameState.getOrCreatePlayer(recvTeam, recvPlayer)
                self.logic.hit(gameState, player, sentTeam, sentPlayer, damage)
                gameState.playerUpdated.emit(recvTeam, recvPlayer)
            except proto.MessageParseException:
                pass

            try:
                proto.TRIGGER.parse(line)

                player = gameState.getOrCreatePlayer(recvTeam, recvPlayer)
                if self.logic.trigger(gameState, player):
                    gameState.playerUpdated.emit(recvTeam, recvPlayer)
            except proto.MessageParseException:
                pass

            try:
                proto.FULL_AMMO.parse(line)

                player = gameState.getOrCreatePlayer(recvTeam, recvPlayer)
                if self.logic.fullAmmo(gameState, player):
                    gameState.playerUpdated.emit(recvTeam, recvPlayer)
            except proto.MessageParseException:
                pass

        except proto.MessageParseException:
            pass

        # TODO: I need to work out what I do with a Hello in the new world of clients having ids and handleEvent being called more than once per event.
        if not alreadyHandled:
            try:
                (teamID, playerID) = proto.HELLO.parse(msgStr)

                if int(teamID) == -1:
                    player = gameState.createNewPlayer()
                    self.queueMessage(proto.TEAMPLAYER.create(player.teamID, player.playerID))
                else:
                    player = gameState.getOrCreatePlayer(teamID, playerID)
                    self.queueMessage("Ack()\n")
                # TODO: we need to preserve the sendQueue when we do this
                self.listeningThread.moveConnection(self, player)

                if self.gameState.isGameStarted():
                    self.queueMessage(proto.STARTGAME.create(self.gameState.gameTimeRemaining()))
            except proto.MessageParseException:
                pass